ListView.setSelection(int)方法执行流程源码解析(API 21)

先从setSelection(int)方法开始讲吧

@Override
public void setSelection(int position) {
    // 很简单,就调用了setSelectionFromTop方法
    setSelectionFromTop(position, 0);
}

接着看看AbsListView.setSelectionFromTop(int, int)方法:

// position:所选item在数据源中的索引
// y:指定所选item距离AbsListView顶部的距离。最终item与顶部的距离还会在y的基础上将padding值计算进去
public void setSelectionFromTop(int position, int y) {
    if (mAdapter == null) {
        // mAdapter为null,直接返回吧。。
        return;
    }
    // isInTouchMode()方法返回true表示用户正在操作屏幕
    if (!isInTouchMode()) {
        // 由于并不是所有的item都是可选的,以及考虑到adapter有可能为null,position的合理性,因此调用lookForSelectablePosition来寻找可选的position
        position = lookForSelectablePosition(position, true);
        if (position >= 0) {
            // 设置mNextSelectedPosition和mNextSelectedRowId
            // setNextSelectedPositionInt(int)方法中其实还有mSyncPosition和mSyncRowId需要注意
            // 不过由于mNeedSync只有在数据源改变,或者onRestoreInstanceState方法中使能,因此暂时不去理会
            setNextSelectedPositionInt(position);
        }
    } else {
        // reconcileSelectedPosition和resurrectSelection方法中使用到
        mResurrectToPosition = position;
    }

    if (position >= 0) {
        // 在layout中会因不同mLayoutMode值,布局方式有所区别
        mLayoutMode = LAYOUT_SPECIFIC;
        // mSpecificTop记录position对应的item与AbsListView顶部之间的距离,该变量在layout的时候会用到
        mSpecificTop = mListPadding.top + y;
        // 暂时不理会
        if (mNeedSync) {
            mSyncPosition = position;
            mSyncRowId = mAdapter.getItemId(position);
        }
        // mPositionScroller是一个AbsPositionScroller抽象类的实例,负责AbsListView的position之间的平滑滚动过度,AbsListView.smoothScrollToXXX系列方法就是通过该工具类实现的。在设置selection的时候先停止该滚动事件。
        if (mPositionScroller != null) {
            mPositionScroller.stop();
        }
        // 请求重新布局
        requestLayout();
    }
}

稍微了解下ListView.lookForSelectablePosition(int,boolean)方法:

@Override
int lookForSelectablePosition(int position, boolean lookDown) {
    final ListAdapter adapter = mAdapter;
    if (adapter == null || isInTouchMode()) {
        // INVALID_POSITION的值为-1
        return INVALID_POSITION;
    }

    final int count = adapter.getCount();
    // mAreAllItemsSelectable默认为true,不过会根据header、footer以及Adapter.areAllItemsEnabled()方法来重新设置
    if (!mAreAllItemsSelectable) {
        if (lookDown) {
            // 向下找,positon累加
            position = Math.max(0, position);
            while (position < count && !adapter.isEnabled(position)) {
                position++;
            }
        } else {
            // 向上找,position递减
            position = Math.min(position, count - 1);
            while (position >= 0 && !adapter.isEnabled(position)) {
                position--;
            }
        }
    }

    if (position < 0 || position >= count) {
        // 非法的position返回-1
        return INVALID_POSITION;
    }

    return position;
}

好了,接下来看看ListView.onMeasure(int,int)方法吧:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // super.onMeasure(int,int)方法主要是添加Selector的padding值到mListPadding中,mListPadding是一个Rect类记录了ListView个个方向的padding值
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    // 获取宽高的mode和size
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMe
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值