You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android NestedScrollView smoothScrollBy无法显示最后一项求助

XML更新说明
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="100"> 
    <!--App Bar Layout Pane--> 
    <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="7" android:background="@drawable/AppBarBackground" android:weightSum="100"> 
        <!--Unrelated XML Code--> 
    </LinearLayout> 
    <!--App Bar Layout Pane end--> 
    <!--Body Pane--> 
    <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="93" android:weightSum="100" android:background="@drawable/AppBackground"> 
        <!--Left Pane--> 
        <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="37" android:background="@color/whiteWithAlpha75"> 
            <!--Unrelated XML Code--> 
        </LinearLayout> 
        <!--Left Pane end--> 
        <!--Right Pane--> 
        <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="43"> 
            <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="100"> 
                <!--Right Pane Header--> 
                <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="8" android:weightSum="100" android:background="@color/whiteWithAlpha10" android:paddingLeft="15dp" android:paddingRight="15dp"> 
                    <TextView android:text="Item(s)" android:fontFamily="@string/fontFamily" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="24" android:textColor="@color/grayDark" android:gravity="center|left" android:textSize="@dimen/textSizeXSmall" /> 
                    <TextView android:text="Unit Price" android:fontFamily="@string/fontFamily" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="17" android:textColor="@color/grayDark" android:gravity="center" android:textSize="@dimen/textSizeXSmall" /> 
                    <TextView android:text="Quantity" android:fontFamily="@string/fontFamily" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="28" android:textColor="@color/grayDark" android:gravity="center" android:textSize="@dimen/textSizeXSmall" /> 
                    <TextView android:text="Discount" android:fontFamily="@string/fontFamily" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="16" android:textColor="@color/grayDark" android:gravity="center" android:textSize="@dimen/textSizeXSmall" /> 
                    <TextView android:text="Total" android:fontFamily="@string/fontFamily" android:gravity="center|right" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="15" android:textColor="@color/grayDark" android:textSize="@dimen/textSizeXSmall" /> 
                </LinearLayout> 
                <!--Right Pane Header end--> 
                <!--Right Pane Item Selected--> 
                <android.support.v4.widget.NestedScrollView android:id="@+id/scrollItemSelectedArea" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="92" android:paddingBottom="5dp" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:background="@color/whiteWithAlpha15"> 
                    <LinearLayout android:id="@+id/llItemSelectedArea" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp" /> 
                </android.support.v4.widget.NestedScrollView> 
                <!--Right Pane Item Selected end--> 
                <!--Right Pane Functions--> 
                <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="39" android:weightSum="100"> 
                    <!--Unrelated XML Code--> 
                </LinearLayout> 
                <!--Right Pane Functions end--> 
            </LinearLayout> 
        </FrameLayout> 
        <!--Right Pane end--> 
    </LinearLayout> 
    <!--Body Pane end--> 
</LinearLayout>

问题

当列表项高度达到NestedScrollView的高度上限时,理应自动滚动以显示最后选中的项。我每次选中项时都会调用smoothScrollBy方法,但出现异常:例如ScrollView可视区域仅能容纳5项,添加第6项时不会向上滚动,导致第6项无法显示;添加第7项时,第6项显示出来,但第7项又被隐藏。我的ScrollView高度设为match_parent,底部无重叠布局,不清楚是否存在额外空间。请问如何修复该问题?

以下是添加新项的位置:


解决方案

我之前遇到过一模一样的问题!核心原因是你调用smoothScrollBy的时候,新添加的Item还没完成布局测量,NestedScrollView根本拿不到正确的滚动距离,自然就滚不准了。给你几个亲测有效的解决办法:

1. 用post延迟执行滚动

添加完新Item后,把滚动操作放到UI线程的消息队列末尾,等新View完成布局再执行:

// 先添加新项到llItemSelectedArea
llItemSelectedArea.addView(newItemView);

// 延迟滚动,确保布局完成
scrollItemSelectedArea.post(() -> {
    // 直接滚动到子布局的底部,也就是最后一项的位置
    scrollItemSelectedArea.smoothScrollTo(0, llItemSelectedArea.getBottom());
});

如果还是想用smoothScrollBy,可以计算需要滚动的偏移量:

llItemSelectedArea.addView(newItemView);
scrollItemSelectedArea.post(() -> {
    int requiredScroll = llItemSelectedArea.getHeight() - scrollItemSelectedArea.getHeight();
    if (requiredScroll > 0) {
        scrollItemSelectedArea.smoothScrollBy(0, requiredScroll);
    }
});

2. 检查NestedScrollView的布局参数

你的NestedScrollView用了layout_weight="92",先确认父LinearLayout的weightSum是正确的(看你的XML里父布局是weightSum="100",这个没问题)。另外,注意到你加了app:layout_behavior="@string/appbar_scrolling_view_behavior"——如果你的布局里没有AppBarLayout,这个behavior完全没必要,反而可能干扰布局计算,建议删掉试试。

3. 直接用fullScroll快速滚动

如果不需要平滑滚动,NestedScrollView有个快捷方法可以瞬间滚到底部:

scrollItemSelectedArea.post(() -> {
    scrollItemSelectedArea.fullScroll(View.FOCUS_DOWN);
});

这个方法会自动把最后一个Item带到可视区域。

4. 监听布局变化

要是上面的方法都不行,可以给子LinearLayout加个布局变化监听器,每次布局更新就滚动到底部:

llItemSelectedArea.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
    scrollItemSelectedArea.smoothScrollTo(0, llItemSelectedArea.getBottom());
});

最推荐的是第一种方法,用post延迟滚动,几乎能解决90%以上的ScrollView滚动不准问题,因为它等新View完全布局好了再计算滚动距离,自然就准确了。


内容的提问来源于stack exchange,提问作者jace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:42:20