ListFragment OnListItemClick не вызывается

У меня есть класс, который расширяет ListFragment и переопределяет метод OnListItemClick. Я также делаю это в другом ListFragment таким же образом (и метод вызывается). Мне интересно, почему метод не вызван, когда я нажимаю на элемент списка?

Вот код:

package org.doraz.fdboard.activity; import java.sql.SQLException; import java.util.Collection; import org.doraz.fdboard.FantasyDraftBoardApplication; import org.doraz.fdboard.R; import org.doraz.fdboard.activity.DraftBoardActivity.PlayerDetailsActivity; import org.doraz.fdboard.domain.FantasyLeague; import org.doraz.fdboard.domain.FantasyTeam; import org.doraz.fdboard.domain.Player; import org.doraz.fdboard.domain.Position; import org.doraz.fdboard.repository.FantasyDraftBoardRepository; import org.doraz.fdboard.view.PlayerAdapter; import org.doraz.fdboard.view.PlayerCursorAdapter; import android.app.FragmentTransaction; import android.app.ListFragment; import android.app.ProgressDialog; import android.content.Intent; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class ListPlayersFragment extends ListFragment implements OnItemClickListener { private final static String TAG = "ListPlayersFragment"; private boolean mDualPane; private int curSelectedPlayerPosition = 0; private PlayerCursorAdapter playerAdapter; private QueryPlayersTask currentTask; private FantasyDraftBoardRepository repository; private FantasyLeague fantasyLeague; private FantasyTeam fantasyTeam; private Position position; private ProgressDialog progressDialog; /* (non-Javadoc) * @see android.app.ListFragment#onActivityCreated(android.os.Bundle) */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //Check for the view players view along with the pane View teamListFragment = getActivity().findViewById(R.id.team_list_fragment); mDualPane = teamListFragment != null && teamListFragment.getVisibility() == View.VISIBLE; if(mDualPane) { Log.i(TAG, "Setting list select mode to single"); getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); } getListView().setSmoothScrollbarEnabled(false); } /* (non-Javadoc) * @see android.app.ListFragment#onListItemClick(android.widget.ListView, android.view.View, int, long) */ @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Log.i(TAG, "[onListItemClick] Selected Position "+ position); selectPlayer(position); } /* (non-Javadoc) * @see android.app.Fragment#onSaveInstanceState(android.os.Bundle) */ @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("curSelectedPlayerPosition", curSelectedPlayerPosition); outState.putInt("fantasyLeague", fantasyLeague.getLeaguePID()); if(!Position.ALL.equals(position)) { outState.putInt("position", position.getPositionPID()); } if(!(FantasyTeam.ALL_AVAILABLE_TEAM.equals(fantasyTeam) || FantasyTeam.ALL_TEAM.equals(fantasyTeam))) { outState.putInt("fantasyTeam", fantasyTeam.getTeamPID()); } } /** * Selects the player at this position in the current list * @param listPosition */ public void selectPlayer(int listPosition) { curSelectedPlayerPosition = listPosition; Player player = (Player) playerAdapter.getItem(listPosition); Log.i(TAG, "Select Player ("+ listPosition +", "+ player.getName() +") called"); //Get the player url String mPlayerUrl = player.getPlayerUrl(); Log.d(TAG, "Selected Player URL: "+mPlayerUrl); if(mDualPane) { if(getListView().getSelectedItemPosition() == listPosition) { //Remove the selected item return; } //Select the item getListView().setItemChecked(listPosition, true); Log.d(TAG, "Creating ViewPlayerFragment"); ViewPlayerFragment vpf = ViewPlayerFragment.newInstance(mPlayerUrl); ListTeamsFragment ltf = (ListTeamsFragment) getFragmentManager().findFragmentById(R.id.team_list_fragment); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.player_web_view_fragment, vpf); if(ltf != null && !ltf.isHidden()) { //Hide the list of teams ft.hide(ltf); ft.addToBackStack(null); } ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.commit(); Log.d(TAG, "Committed to ViewPlayerFragment"); } else { Log.d(TAG, "Launching new activity to view player"); Intent intent = new Intent(); intent.setClass(getActivity(), PlayerDetailsActivity.class); intent.putExtra("playerURL", mPlayerUrl); startActivityForResult(intent, 0); } } public void clearSelectedPlayer() { Log.i(TAG, "Clearing selected player"); curSelectedPlayerPosition = -1; //Clear the list view getListView().clearChoices(); ViewPlayerFragment vpf = (ViewPlayerFragment) getFragmentManager().findFragmentById(R.id.player_web_view_fragment); if(vpf != null) { Log.d(TAG, "Closing ViewPlayerFragment"); //Close the ViewPlayersFragment FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.remove(vpf); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); ft.commit(); Log.d(TAG, "Closed ViewPlayerFragment"); } } /** * Initializes the player adapter */ private void initializePlayerAdapter(Cursor cursor) { if(playerAdapter != null) return; playerAdapter = new PlayerCursorAdapter(getActivity(), cursor, (DraftBoardActivity)getActivity(), repository); setListAdapter(playerAdapter); setEmptyText(getText(R.string.no_players_msg)); } /** * Initializes the player adapter */ public void setPlayersCursor(Cursor cursor) { if(playerAdapter == null) { initializePlayerAdapter(cursor); } else { playerAdapter.changeCursor(cursor); } } /** * Drafts a player * * @param mPlayer the player to draft * @param fantasyTeam the fantasy team * @param value the draft value */ public void draftPlayer(Player mPlayer, FantasyTeam fantasyTeam, Double value) { mPlayer.setFantasyTeam(fantasyTeam); mPlayer.setDraftValue(value); mPlayer.setDrafted(true); fantasyTeam.draftPlayer(mPlayer); try { repository.savePlayer(mPlayer); repository.saveFantasyTeam(fantasyTeam); } catch (SQLException e) { Log.e(TAG, "Error drafting player", e); } //Refresh the query refresh(); } /** * Refreshes the players list */ public void refresh(){ if(fantasyLeague == null) { fantasyLeague = ((FantasyDraftBoardApplication) (getActivity().getApplication())).getCurrentFantasyLeague(); } if(fantasyTeam == null) { fantasyTeam = FantasyTeam.ALL_AVAILABLE_TEAM; } if(position == null) { position = Position.ALL; } if(currentTask != null) { currentTask.cancel(true); } if(progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } progressDialog = ProgressDialog.show(getActivity(), null, "Loading..."); currentTask = new QueryPlayersTask(fantasyLeague, fantasyTeam, position, repository); currentTask.execute(); } /** * Sets the fantasyLeague * @param fantasyLeague the fantasyLeague to set */ public void setFantasyLeague(FantasyLeague fantasyLeague) { this.fantasyLeague = fantasyLeague; } /** * Sets the fantasyTeam * @param fantasyTeam the fantasyTeam to set */ public void setFantasyTeam(FantasyTeam fantasyTeam) { this.fantasyTeam = fantasyTeam; } /** * Sets the position * @param position the position to set */ public void setPosition(Position position) { this.position = position; } /** * Sets the repository * @param repository the repository to set */ public void setRepository(FantasyDraftBoardRepository repository) { this.repository = repository; } private class QueryPlayersTask extends AsyncTask<Integer, Integer, Cursor> { private FantasyLeague fantasyLeague; private FantasyTeam fantasyTeam; private Position position; private FantasyDraftBoardRepository repository; public QueryPlayersTask(FantasyLeague fantasyLeague, FantasyTeam fantasyTeam, Position position, FantasyDraftBoardRepository repository) { this.fantasyLeague = fantasyLeague; this.fantasyTeam = fantasyTeam; this.position = position; this.repository = repository; } @Override protected Cursor doInBackground(Integer... params) { try { return repository.queryForPlayersCursor(position, fantasyLeague, fantasyTeam); } catch (SQLException e) { Log.e("QueryPlayersTask", "Unable to query for players", e); } return null; } /* (non-Javadoc) * @see android.os.AsyncTask#onPostExecute(java.lang.Object) */ @Override protected void onPostExecute(Cursor result) { super.onPostExecute(result); if(!isCancelled()) { //Update the player cursor updatePlayerCursor(result); } } } /** * Updates the player cursor * @param c the player cursor */ private final void updatePlayerCursor(Cursor c){ Log.d(TAG, "Updating player cursor."); if(playerAdapter == null) initializePlayerAdapter(c); else playerAdapter.changeCursor(c); if(progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } //Clear the current task currentTask = null; } @Override public void onItemClick(AdapterView<?> adapter, View arg1, int listPosition, long id) { Log.d(TAG, "[onItemClick] Clicked item "+position); selectPlayer(listPosition); } } 

Любая помощь будет высоко оценена. Я могу получить желаемый эффект, внедряя несколько других слушателей и назначая их каждому элементу списка, но я думаю, что это правильный способ сделать это, и СЛЕДУЕТ работать. Я просто не знаю, почему это не

Заранее спасибо.

Если у вас есть элемент в макете, который может украсть входные данные других компонентов, таких как CheckBox, этот компонент должен быть определен как не настраиваемый.

Я столкнулся с такой же проблемой после преобразования моего приложения из ListActivity в ListFragment.

ListFragment был единственным фрагментом активности (без вкладок и т. Д.), Но ListFragment не видел ни одного щелчка.

Проблема заключалась в том, что моя активность по-прежнему определялась как ListActivity. Изменил его на активность, зафиксировав его, и теперь ListFragment видит клики.

  public class MyActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); } 

должно было:

  public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); } <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <fragment class="com.davidmarkscott.myapp.MyFragment" android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 

Вот изящное решение, которое позволяет onListItemClick так, как вам кажется, а также onListItemClick любые дочерние представления получать события (или нет, в зависимости от того, как вы хотите его установить). По заданному вопросу это позволит сохранить Флажок checkbox. Пожалуйста, позаботьтесь о том, является ли это интуитивным опытом для пользователей.

В корневой группе ViewGroup всех элементов списка установите атрибут descendantFocusability в XML:

 android:descendantFocusability="blocksDescendants" 

Документация Android SDK о потоке потомства . Был частью SDK с Android 1.0. Другие настройки для android:descendantFocusability включают "beforeDescendants" и "afterDescendants" .

Пример cluster_layout.xml, который устанавливает descendantFocusability (Элементы списка, применяемые к cluster_list.xml через ArrayAdapter):

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/cluster_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="#e0e0e0" android:clickable="false" android:descendantFocusability="blocksDescendants" > <FrameLayout android:id="@+id/cluster_sentiment_handle" android:layout_width="40dp" android:layout_height="match_parent" android:background="@color/handle_red" /> <!-- other elements --> </LinearLayout> 

Пример cluster_list.xml, который не имеет никакого отношения к этому решению, кроме того, чтобы показать, что он предназначен для использования в ListFragment, имея элемент ListView с идентификатором id @ id / android: list:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="8dp" android:background="#f6f6f6" > <include layout="@layout/cluster_header" /> <ListView android:id="@id/android:list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top|center_horizontal" android:gravity="center_horizontal" android:divider="@android:color/transparent" android:dividerHeight="8dp" android:fastScrollEnabled="true" /> </LinearLayout> 

Как и другие, у меня есть CustomAdapter с моим ListFragment, который переопределяет getView (), чтобы предоставить представление для каждой строки. Настройка прослушивателей на возвращаемом мне представлении. Пример:

 public class MyAdapter extends ArrayAdapter<SomeType> { private Context context; private List<SomeType> objects; public MyAdapter(Context context, int resource, List<SomeType> objects) { super(context, resource, objects); this.context = context; this.objects = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.list_subscription_item, null); TextView subTo = (TextView)rowView.findViewById(R.id.itemName); SomeType sub = objects.get(position); subTo.setText(sub.getName() + sub.getId()); rowView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { Toast.makeText(context, "from long click", Toast.LENGTH_SHORT).show(); return false; } }); rowView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "from click", Toast.LENGTH_SHORT).show(); } }); return rowView; } } 

Только обходной путь до сих пор, используйте Fragment и ListView затем используйте setOnItemClickListener() которые сделают ListFragment и все его «устаревшие удобства» … После того, как я создал новый класс, содержащий точно такой же код (только имя класса было изменено) и Построил проект на другой машине, «магически» работал (все тот же API-уровень). Ниже кода, который работал. Я также попробовал project-> clean, который обычно исправляет большинство проблем, но это не срабатывало.

 public class ContainerFragment extends ListFragment { private ContainerFragmentListener listener; public ContainerFragment(ContainerFragmentListener listener) { super(); this.listener = listener; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setListAdapter(new ContainerAdapter(getActivity())); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Container container = (Container) getListAdapter().getItem(position); listener.containerSelected(container.id); } } 

Я также столкнулся с той же проблемой. Использование ListFragment которое было завышено как содержимое вкладки вкладки внутри TabHost .

Один из моих TabHost имеет 3 вкладки, onListItemClick() был вызван правильно.

Но у другой TabHost есть только 2 вкладки, onListItemClick() не был вызван.

Поэтому я решил реализовать работу над этим Marcel и H9kDroid, упомянутые выше, и все получилось отлично. Спасибо за Ваш ответ.

Обновление: после нескольких часов работы, кажется, что проблема связана с макетом элемента списка и адаптером ListView.

Внутри макета списка элементов есть один флажок, и состояние флажка переключается внутри адаптера. Я думаю, после переключения, ListView перепутался и не может доставить вызов onListItemClick() .

Я просто изменил макет, снимите флажок, и он отлично работает.

Приветствия.

Повторяя, что сказал @auselen выше, в моем случае у меня был android:textIsSelectable="true" установленный в TextView , и он крал обратный вызов.

Установив это в false проблема решена.

Я выяснил, что установка свойства android: focusable to false для любого дочернего представления элемента списка не позволяет запустить обработчик кликов. Следующая настройка работает с ListFragment.

navigation_fragment.xml:

 <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/navigationEntries" android:layout_height="wrap_content" android:layout_width="fill_parent" /> 

navigation_entry.xml:

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/navigationEntry" android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="fill_parent" <!-- enhance this --> <ImageView android:layout_width="fill_parent" android:layout_height="1dp" android:background="@android:color/darker_gray" /> 1  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/navigationEntry" android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="fill_parent" <!-- enhance this --> <ImageView android:layout_width="fill_parent" android:layout_height="1dp" android:background="@android:color/darker_gray" /> 

Я часами пытался выяснить свою аналогичную проблему. У меня было довольно простое текстовое представление, содержащее флажок и два текстовых изображения и простой пользовательский адаптер. Попробовав различные вещи, которые были предложены, я отобрал представления, пока у меня не было только одного текстового комментария. Все еще не работал. Вы знаете, что сделали? Я просто удалил файл макета xml для пользовательского представления, которое я использовал, и сделал его снова, по частям. Сделал ту же самую вещь с тем же именем. По какой-то причине это просто не понравилось. Так что ты идешь. Я думаю, какой-то странный глюк в Eclipse.

Я вызвал listfragment.getListView (). SetOnItemClickListener (), а также переопределил onListItemClick () в ListFragment, и это привело к тому, что onListItemClick не был вызван. Я удалил метод setOnItemClickListener () и вместо него был вызван метод onListItemClick listFragment.