ListView的OnItemClickListener点击事件失效问题求助
ListView项点击事件不触发的解决方法
问题背景
使用ListView组件时,列表项点击后无法触发OnItemClickListener的onItemClick方法,无法跳转至详情Fragment。列表项仅包含继承自AppCompatTextView的自定义TextView,无按钮类交互组件,相关代码及布局如下:
ListView初始化代码
listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(getContext(), "dwdwdwdw", Toast.LENGTH_SHORT).show(); selectRow(position); } }); listView.setOnScrollListener(new AbsListView.OnScrollListener() {.....
fragment_listview布局
<?xml version="1.0" encoding="utf-8"?> <androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/background"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@null" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
列表项布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/listview_background" android:padding="10dp"> <....MainFontTextView android:id="@+id/nameTextView" style="@style/black_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:singleLine="true" android:text="New Text" /> <!-- 另外4个TextView --> </RelativeLayout>
Adapter代码
public class BasePagingAdapter extends ArrayAdapter<Object> { protected final static int EMPTY_TYPE = 0; protected final static int LOADING_TYPE = 1; protected final static int ITEM_TYPE = 2; protected ArrayList<?> items; protected boolean showLoadingRow; public ArrayList<?> getItems() { return items; } public boolean isShowLoadingRow() { return showLoadingRow; } public void setShowLoadingRow(boolean showLoadingRow) { this.showLoadingRow = showLoadingRow; } public BasePagingAdapter(Context context, int resource, ArrayList<?> items) { super(context, resource); this.items = items; } protected static class EmptyViewHolder { TextView emptyTextView; } protected static class LoadingViewHolder { TextView loadingTextView; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (getItemViewType(position) == EMPTY_TYPE) { EmptyViewHolder holder; if (row == null || !(row.getTag() instanceof EmptyViewHolder)) { LayoutInflater inflater = LayoutInflater.from(getContext()); row = inflater.inflate(R.layout.row_empty, parent, false); holder = new EmptyViewHolder(); holder.emptyTextView = row.findViewById(R.id.emptyTextView); row.setTag(holder); } } else if (getItemViewType(position) == LOADING_TYPE) { LoadingViewHolder holder; if (row == null || !(row.getTag() instanceof LoadingViewHolder)) { LayoutInflater inflater = LayoutInflater.from(getContext()); row = inflater.inflate(R.layout.row_loading, parent, false); holder = new LoadingViewHolder(); holder.loadingTextView = row.findViewById(R.id.loadingTextView); row.setTag(holder); } holder = (LoadingViewHolder) row.getTag(); holder.loadingTextView.setText(String.format(getContext().getString(R.string.list_loading_more), Constants.PAGE_SIZE)); } return row; } @Override public int getCount() { if (items.size() > 0) { if (showLoadingRow) { return items.size() + 1; } else { return items.size(); } } else { return 1; } } @Override public int getViewTypeCount() { return 3; } @Override public int getItemViewType(int position) { if (items.size() == 0) { return EMPTY_TYPE; } else if (items.size() == position) { return LOADING_TYPE; } else { return ITEM_TYPE; } } @Override public boolean isEnabled(int position) { return items.size() != 0 && position != items.size(); } public void updateItems(ArrayList<?> items) { this.items = items; notifyDataSetChanged(); } }
问题原因
- Adapter的getView方法未处理ITEM_TYPE:在getView中仅实现了EMPTY_TYPE和LOADING_TYPE的视图加载逻辑,完全漏掉了ITEM_TYPE(正常列表项)的处理,导致实际展示的列表项视图未被正确初始化,点击事件无法触发。
- 自定义TextView可能拦截焦点:如果自定义TextView设置了
android:focusable="true"或android:clickable="true",会抢占ListView项的焦点,导致父布局的点击事件无法传递。
解决方案
1. 补全Adapter的getView方法中ITEM_TYPE的处理逻辑
在getView方法中添加ITEM_TYPE的分支,加载对应的列表项布局,并初始化ViewHolder:
@Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (getItemViewType(position) == EMPTY_TYPE) { // 原EMPTY_TYPE处理逻辑不变 EmptyViewHolder holder; if (row == null || !(row.getTag() instanceof EmptyViewHolder)) { LayoutInflater inflater = LayoutInflater.from(getContext()); row = inflater.inflate(R.layout.row_empty, parent, false); holder = new EmptyViewHolder(); holder.emptyTextView = row.findViewById(R.id.emptyTextView); row.setTag(holder); } } else if (getItemViewType(position) == LOADING_TYPE) { // 原LOADING_TYPE处理逻辑不变 LoadingViewHolder holder; if (row == null || !(row.getTag() instanceof LoadingViewHolder)) { LayoutInflater inflater = LayoutInflater.from(getContext()); row = inflater.inflate(R.layout.row_loading, parent, false); holder = new LoadingViewHolder(); holder.loadingTextView = row.findViewById(R.id.loadingTextView); row.setTag(holder); } holder = (LoadingViewHolder) row.getTag(); holder.loadingTextView.setText(String.format(getContext().getString(R.string.list_loading_more), Constants.PAGE_SIZE)); } else if (getItemViewType(position) == ITEM_TYPE) { // 添加ITEM_TYPE的处理逻辑 // 假设你的列表项布局是R.layout.list_item_layout,根据实际修改 ItemViewHolder holder; if (row == null || !(row.getTag() instanceof ItemViewHolder)) { LayoutInflater inflater = LayoutInflater.from(getContext()); row = inflater.inflate(R.layout.list_item_layout, parent, false); holder = new ItemViewHolder(); holder.nameTextView = row.findViewById(R.id.nameTextView); // 初始化其他4个TextView row.setTag(holder); } holder = (ItemViewHolder) row.getTag(); // 绑定数据到视图,比如: Object item = items.get(position); holder.nameTextView.setText(item.toString()); // 设置其他TextView的数据 } return row; } // 添加ItemViewHolder类 protected static class ItemViewHolder { MainFontTextView nameTextView; // 声明其他4个TextView }
2. 检查并修改自定义TextView的焦点属性
确保列表项中的所有自定义TextView没有设置android:focusable="true"或android:clickable="true",如果有,改为false:
<....MainFontTextView android:id="@+id/nameTextView" style="@style/black_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:singleLine="true" android:text="New Text" android:focusable="false" android:clickable="false" />
3. 确认isEnabled方法逻辑正确性
当前Adapter的isEnabled方法逻辑正确,仅对正常列表项启用点击事件,无需修改:
@Override public boolean isEnabled(int position) { return items.size() != 0 && position != items.size(); }
完成以上修改后,ListView的列表项点击事件应该能正常触发,进而执行跳转至详情Fragment的逻辑。
内容的提问来源于stack exchange,提问作者Dazai
相关产品推荐
相关产品推荐

