Android NestedScrollView在设置app:layout_behavior后尺寸错误

20
自从 Google 发布了 Android 的设计支持库以来,许多好东西可以在不实现自定义代码的情况下完成。虽然我已经测试过该库中的自定义视图,但我发现了一个更糟糕的事情,我不知道这是否是一个错误。

我在 Github 上找到了 Cheesesquare 项目。在 activity_detail.xml(layout file) 中有3个 CardViews 在 NestedScrollView 中。如果您删除其中2个 CardView,您会发现 NestedScrollView 没有父元素(match_parent)的完整大小。NestedScrollView 绑定到父视图的底部。http://i.stack.imgur.com/BXl7w.png

当我删除了 app:layout_behavior="@string/appbar_scrolling_view_behavior" 后,NestedScrollView 才能获得其完整大小。

但是,当我删除布局行为时,工具栏就不会折叠。

这个问题有解决方法吗?示例布局文件可以在这里找到:https://github.com/Smove/cheesesquare/blob/stackoverflow/app/src/main/res/layout/activity_detail.xml

你可以从我的 Github 分支 stackoverflow 构建 Cheesesquare 应用程序。


我遇到了同样的问题。如果在NestedScrollView顶部使用阴影,看起来尤其糟糕。 - Jimeux
这里也有同样的问题!如果内容不大于滚动视图,则其会对齐在底部并表现得非常奇怪 :( RecyclerView运行良好(即使只有一个元素)... - Philip Giuliani
android:layout_gravity="fill_vertical" 应该可以工作,但我希望他们在下一个版本中修复它。 - natario
我也在使用这个库,但似乎它仍然存在许多布局问题。 - Tommy Chan
5个回答

37

我遇到了这个问题,并通过添加以下内容进行了修复:

android:layout_gravity="fill_vertical"

将NestedScrollView添加到布局中。按照我在这里所解释的那样,它就可以正常工作了。当然,NestedScrollView需要一些子项(即不能是空的),否则工具栏将不会折叠。

更新

虽然这对于小内容来说工作得很好,但我注意到它在显示更长的内容时存在一些问题,例如上面完整的activity_detail.xml文件。问题在于您无法滚动到内容的最底部-底部无法触及。

通过我的测试,我发现缺失的部分与折叠的工具栏一样大(或者至少在我看来是这样)。要解决这个问题,并获得可靠的适用于小和大内容的解决方案,您应该向ScrollView添加一个layout_marginBottom,以使其被测量并释放缺失的底部部分。因此:

android:layout_gravity="fill_vertical"
android:layout_marginBottom="?attr/actionBarSize"

或者你给Toolbar设置的任何大小。

但是

使用这种解决方案进行小内容滚动,即使内容恰好对齐在顶部,与大内容滚动相比并不真正平滑。在库修���之前,我会继续使用它。

更新2

看起来在v22.2.1中已经修复了此问题。


这个解决方案非常好!在谷歌修复之前,我会一直使用它。 - Jan
我尝试了几乎所有的解决方案,但只有这个对我有效。谢谢..! - Tushar Kathuria
太棒了!我喜欢这个社区,因为无论我们是什么编程水平,都能在这里找到我们所缺少的小细节。谢谢! - sud007
1
@Mike 不,设计库现在开始看起来更加健壮了。 - natario
我在某些情况下仍然遇到问题。我的支持库版本是23.4.0。有人可以帮帮我吗? - Nigam Patro
显示剩余2条评论

1

使用@natario提供的答案,如果你为子项(在我的情况下是LinearLayout)设置padding,效果会更好:

<androidx.core.widget.NestedScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
                android:layout_gravity="fill_vertical">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingBottom="?attr/actionBarSize">
                <!--Rest of the code-->

或者在 Kotlin 中你可以像这样做:

 coordinator.doOnLayout {
        nestedScrollView.minimumHeight = resources.displayMetrics.heightPixels - with(TypedValue().also {theme.resolveAttribute(android.R.attr.actionBarSize, it, true)}) {
            TypedValue.complexToDimensionPixelSize(data, resources.displayMetrics)}
    }

0

CollapsingToolbarLayout中添加android:minHeight="?attr/actionBarSize"


-2

解决方法

在显示我的NestedScrollView之前,在将数据绑定到NestedScrollView内容后,我调用了我的NestedScrollView实例的fullScroll(int direction)方法,并将View.FOCUS_UP方向作为参数。

片段的代码示例:

NestedScrollView scrollView = (NestedScrollView) getActivity().findViewById(R.id.scroll_view); scrollView.fullScroll(View.FOCUS_UP);


-3
使用RecyclerView替换NestedScrollView来修复此错误,将item count设置为1,ViewHolder返回您的真实的contentView;
我的代码:
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    // 添加分割线
    recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext()));

    recyclerView.setAdapter(new Adapter<ViewHolder>() {

        @Override
        public int getItemCount() {
            return 1;
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int arg1) {
            WebView view = (WebView) holder.itemView;
            view.getSettings().setJavaScriptEnabled(true);
            view.loadUrl("http://www.baidu.com");
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {
            return new ViewHolder(inflater.inflate(R.layout.webview, arg0, false)) {
            };
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接