解决listview setSelection不生效问题

本文探讨了ListView中setSelection方法在数据加载完成后才能生效的问题。通过分析源码,找到dataChanged属性并重写handleDataChanged方法,使用回调确保setSelection在数据加载完毕后执行,从而确保百分百合生效。
摘要由CSDN通过智能技术生成

  之前有个需求要实现这么一个功能,进入到一个有listview的页面,然后自动定位到某个item.listview有提供一个api就是setSelection来实现跳转到某个ITEM,开始以为这个实现挺简单的,但是尝试了之后发现直接setSelection没有起作用。后来查了下资料发现,这个方法只有在listvie完成数据加载之后调用才会生效。
  网上大部分文章提供的解决方法是,把setSelection的调用放在postdelay里面延迟几百毫秒执行,这个的确有效,但是这个延迟的时间不好确定,有时候数据加载得很慢的情况下,这个方法还是会失效的。
  这时我想到了一 listview有一个transcripmode的属性。这个属性设置为alwayscroll之后会自动滑到底部,这个属性每次都能滑动成功,我就想listview内部肯定有对这个做处理。然后就顺着这个属性看了下listview的源码,发现里面有个datachanged的属性。表示数据加载完成,数据加载完成之后会调用一个叫做handlechange的方法。

      if (dataChanged) {
                handleDataChanged();
            }

  看到这,我就想到这个办法,自定义一个listview重写里面的handledatachanded方法,在里面加一个回调,然后将setSelection这个方法放在这个回调里面去执行。测试了一下,发现这个方法果然能保证setSelection百分百生效。下面附上自定义的listview代码。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
ListViewsetEmptyView方法是用来设置列表为空时显示的View,但是有时候我们在使用该方法时发现并没有生效,可能是以下几个原因: 1. 没有ListView设置Adapter,因为只有当Adapter没有数据时才会显示EmptyView。 2. 在设置EmptyView之前已经给ListView设置了数据源,需要在设置EmptyView之前将数据源清空。 3. 在设置EmptyView之前需要先inflate出EmptyView的布局,并将其添加到ListView的父布局中。 以下是一个setEmptyView无效的例子: ```java ListView listView = findViewById(R.id.list_view); View emptyView = findViewById(R.id.empty_view); listView.setEmptyView(emptyView); String[] data = {"item1", "item2", "item3"}; ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data); listView.setAdapter(adapter); ``` 上述代码中,设置了EmptyView,但是并没有生效,因为在设置EmptyView之前已经给ListView设置了数据源,需要将数据源清空,即在setAdapter之前添加如下代码: ```java listView.setAdapter(null); ``` 另外,还需要注意,EmptyView需要先inflate出来并添加到ListView的父布局中,例如: ```java View emptyView = LayoutInflater.from(this).inflate(R.layout.empty_view, (ViewGroup) listView.getParent(), false); ``` 至于ListView的源码实现,可以参考以下几个方法: 1. setEmptyView方法: ```java public void setEmptyView(View emptyView) { mEmptyView = emptyView; final T adapter = mAdapter; final boolean empty = ((adapter == null) || adapter.isEmpty()); updateEmptyStatus(empty); } private void updateEmptyStatus(boolean empty) { if (isInFilterMode()) { empty = false; } if (empty) { if (mEmptyView != null) { mEmptyView.setVisibility(View.VISIBLE); setVisibility(View.GONE); } else { // If the caller just removed our empty view, make sure the list view is visible setVisibility(View.VISIBLE); } // We are now GONE, so pending layouts will not be dispatched. // Force one here to ensure that the state of the list matches // the state of the adapter. if (mDataChanged) { this.onLayout(false, getLeft(), getTop(), getRight(), getBottom()); } } else { if (mEmptyView != null) { mEmptyView.setVisibility(View.GONE); } setVisibility(View.VISIBLE); } } ``` 2. setAdapter方法: ```java public void setAdapter(ListAdapter adapter) { if (mAdapter != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); resetList(); } mAdapter = adapter; if (mAdapter != null) { mOldSelectedPosition = INVALID_POSITION; mOldSelectedRowId = INVALID_ROW_ID; mItemCount = mAdapter.getCount(); mDataChanged = true; // Detect the case where a cursor that was previously invalidated has // been repopulated with new data. mHasStableIds = mAdapter.hasStableIds(); if (mChoiceMode != CHOICE_MODE_NONE && mAdapter.hasStableIds()) { mChoiceMode = CHOICE_MODE_SINGLE; if (mCheckStates == null) { mCheckStates = new SparseBooleanArray(); } if (mCheckedIdStates == null) { mCheckedIdStates = new LongSparseArray<Boolean>(); } } if (!mPopupHidden) { // Show the popup if we have one if (mAdapter.getCount() > 0) { showPopup(); } } } else { mItemCount = 0; mDataChanged = false; mHasStableIds = false; mOldSelectedPosition = INVALID_POSITION; mOldSelectedRowId = INVALID_ROW_ID; mChoiceMode = CHOICE_MODE_NONE; mCheckStates.clear(); mCheckedIdStates.clear(); // Hide the currently visible popup dismissPopup(); } if (mFilter != null) { mAdapter.getFilter().filter(mFilter); } requestLayout(); } ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值