HorizontalScrollView重新layout之后自动滑动初始位置问题解决

本文探讨了HorizontalScrollView在重新layout时自动滑动的问题,并详细分析了其内部机制,包括焦点处理逻辑。最后提供了解决方案,即通过覆写onLayout方法避免自动滚动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HorizontalScrollView在重新layout时,有时候会自动滑动到其他位置,这是由于他的后代view获取到焦点导致的,来让我们从代码层面看清这个问题:

 @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childWidth = 0;
        int childMargins = 0;

        if (getChildCount() > 0) {
            childWidth = getChildAt(0).getMeasuredWidth();
            LayoutParams childParams = (LayoutParams) getChildAt(0).getLayoutParams();
            childMargins = childParams.leftMargin + childParams.rightMargin;
        }

        final int available = r - l - getPaddingLeftWithForeground() -
                getPaddingRightWithForeground() - childMargins;

        final boolean forceLeftGravity = (childWidth > available);

        layoutChildren(l, t, r, b, forceLeftGravity);

        mIsLayoutDirty = false;
        // Give a child focus if it needs it
        //就是在这一行,scrollView自动滑动到那个有焦点的view的位置
        if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
            scrollToChild(mChildToScrollTo);
        }
        mChildToScrollTo = null;

        if (!isLaidOut()) {
            final int scrollRange = Math.max(0,
                    childWidth - (r - l - mPaddingLeft - mPaddingRight));
            if (mSavedState != null) {
                mScrollX = isLayoutRtl()
                        ? scrollRange - mSavedState.scrollOffsetFromStart
                        : mSavedState.scrollOffsetFromStart;
                mSavedState = null;
            } else {
                if (isLayoutRtl()) {
                    mScrollX = scrollRange - mScrollX;
                } // mScrollX default value is "0" for LTR
            }
            // Don't forget to clamp
            if (mScrollX > scrollRange) {
                mScrollX = scrollRange;
            } else if (mScrollX < 0) {
                mScrollX = 0;
            }
        }

        // Calling this with the present values causes it to re-claim them
        scrollTo(mScrollX, mScrollY);
    }


而mChildToScrollTo这个view是在requestChildFocus中赋值的,

  @Override
    public void requestChildFocus(View child, View focused) {
        if (!mIsLayoutDirty) {
            scrollToChild(focused);
        } else {
            // The child may not be laid out yet, we can't compute the scroll yet
            mChildToScrollTo = focused;
        }
        super.requestChildFocus(child, focused);
    }


解决办法 :

覆写父类方法onLayout,就可以解决这个问题

  @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int tempScrollX = getScrollX();
        super.onLayout(changed, l, t, r, b);
        final int scrollX = getScrollX();

       
            if (tempScrollX != scrollX) {
                this.scrollTo(tempScrollX, 0);
            }
        
    }





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值