简体   繁体   English

ScrollView中具有RecyclerView / ListView的CardView

[英]CardView with RecyclerView/ListView in ScrollView

tl;dr: How to achieve the layout shown in the screenshot below? tl; dr:如何实现下面的屏幕快照中所示的布局? Placing ListView to a ScrollView is apparently not recommended, but is there actually any other way to achieve it? 显然不建议将ListView放置到ScrollView,但是实际上还有其他方法可以实现吗?

The whole question: I want to have multiple CardViews in my app, and one (or more) of them will have either RecyclerView or ListView in it (it doesn't really matter to me which one of those). 整个问题:我想在我的应用程序中拥有多个CardView,其中一个(或多个)将具有RecyclerView或ListView(这对我来说并不重要)。 The whole view is supposed to be scrollable - not only the ListViews in their parent CardViews. 整个视图应该是可滚动的-不仅是其父级CardView中的ListView。 I basically need to achieve similar layout as the Play Store app has. 我基本上需要实现与Play商店应用类似的布局。

Play商店的“我的应用”屏幕

The first option I tried was this (the code is obviously simplified): 我尝试的第一个选项是这样(代码明显简化了):

<LinearLayout android:orientation="vertical">
    <CardView>
        <!-- Some content of the first card. -->
    </CardView>
    <CardView>
        <ListView/>
    </CardView>
</LinearLayout>

The result was not what I wanted, the ListView was only scrollable in its parent CardView but the whole view wasn't scrollable like it is in the Play Store app. 结果不是我想要的,ListView仅可在其父级CardView中滚动,但整个视图却无法像Play Store应用程序中那样滚动。 So now I wrapped it all in a ScrollView: 所以现在我将其全部包装在ScrollView中:

<ScrollView 
    android:fillViewport="true"
    android:isScrollContainer="true">
    <LinearLayout orientation="vertical">
        <CardView>
            <!-- Some content of the first card. -->
        </CardView>
        <CardView>
            <ListView/>
        </CardView>
    </LinearLayout>
</ScrollView>

And I programmatically set the height of the bottom card to fit the ListView's height (number of elements in the ListView * height of one list item element). 然后,我以编程方式将底部卡片的高度设置为适合ListView的高度(ListView中的元素数*一个列表项元素的高度)。 Now the whole view is scrollable, and the bottom card's height is the same as the height of the ListView, so the ListView isn't scrollable inside the CardView which is exactly what I wanted. 现在整个视图都是可滚动的,并且底部卡片的高度与ListView的高度相同,因此ListView在CardView内不可滚动,这正是我想要的。

Now the actual problem: I got it working as described above, but I know this particular issue (ListView in a ScrollView) has been asked about many times before and the answer has always been the same - don't put neither RecyclerView nor ListView in a ScrollView because it causes performance problems . 现在是实际的问题:如上所述,它可以正常工作,但是我知道这个特殊问题(ScrollView中的ListView)已经被问过很多次了,而且答案始终是相同的- 不要在其中放入RecyclerView和ListView ScrollView,因为它会导致性能问题 Well, so what's the correct approach then? 那么,那么正确的方法是什么呢? How did Google do it in the Play Store app? Google如何在Play商店应用中做到这一点? I tried decompiling the Play Store app with APKTool but there weren't any layout files (maybe I did something wrong). 我尝试使用APKTool反编译Play商店应用,但没有任何布局文件(也许我做错了)。 Is my approach correct? 我的方法正确吗? My ListView will only display a few items (I guess it will be at most 20 items) - will it cause some performance issues in this case? 我的ListView仅显示几个项目(我猜最多是20个项目)-在这种情况下是否会引起一些性能问题?

I wouldn't ask about this if all the answers wouldn't always mention that we shouldn't put ListView in a ScrollView. 我不会问这个问题,是否所有答案都不会总是提到我们不应该将ListView放在ScrollView中。 Is there any other way how to achieve the layout described by the screenshot above? 还有什么其他方法可以实现上述屏幕截图所述的布局?

The first thing to address is why you're "not supposed to" use wrap_content on a ListView or a RecyclerView and put it in a scrollable container: it defeats the entire view-recycling purpose of these components. 首先要解决的问题是为什么您不应该在ListViewRecyclerView上使用wrap_content并将其放在可滚动的容器中:这违背了这些组件的整个视图回收目的。

What makes a ListView or RecyclerView better than a LinearLayout inside a ScrollView is that the system only needs to create enough views to display everying that fits inside the visible area. 使ListViewRecyclerView优于ScrollViewLinearLayout的原因在于,系统仅需要创建足够的视图即可显示适合可见区域的所有内容。 When you "scroll" the visible area, the views that disappear off one end can be re-used for the views that scroll into view from the other end. 当“滚动”可见区域时,从一端消失的视图可以重新用于从另一端滚动到视图的视图。 When you make your list/recycler wrap_content , this recycling is impossible, so you might as well just manually add your views to a LinearLayout instead. 当您创建列表/回收器wrap_content ,这种回收是不可能的,因此您最好将视图手动添加到LinearLayout

That being said, RecyclerView does support using wrap_content ... it just means you won't get view recycling. 话虽这么说, RecyclerView 确实支持使用wrap_content ……这仅意味着您不会获得视图回收。 If this performance hit doesn't cause you problems, there's no objectively evil code here. 如果性能下降不会给您带来问题,那么这里就没有客观的恶意代码。

The only way to know for sure if the performance penalty is problematic or not is to just try it, test it, measure it, and decide for yourself. 唯一确定性能损失是否有问题的唯一方法是尝试,测试,衡量并自行决定。 With 20 items, I suspect you have nothing to worry about. 我怀疑有20件物品,您无需担心。

The next thing to think about is the fact that Google has tons of resources and manpower and can afford to be extremely clever. 接下来要考虑的是Google拥有大量的资源和人力,并且可以负担得起非常聪明的事实。 Perhaps the Play Store app is as you say, with some sort of scrollable parent container that holds cards, each of which have some sort of adapter view within. 就像您说的那样,也许Play Store应用具有某种可滚动的父容器,用于容纳卡,每个卡中都有某种适配器视图。 But it's equally possible that they're doing something completely different, like using a single RecyclerView and "faking" the appearance of cards by using an ItemDecoration . 但是他们也有可能做完全不同的事情,例如使用单个RecyclerView并通过使用ItemDecoration来“伪造”卡片的外观。 Or perhaps they are using some sort of custom view subclass that the public doesn't have access to. 也许他们正在使用某种公众无法访问的自定义视图子类。

As for how you could recreate something similar, I suspect a hierarchy like this will work just fine: 至于如何重新创建类似的东西,我怀疑这样的层次结构会正常工作:

<NestedScrollView>
  <LinearLayout>
     <CardView>
       <RecyclerView/>
     </CardView>
     <CardView>
       <RecyclerView/>
     </CardView>
     <CardView>
       <RecyclerView/>
     </CardView>
  </LinearLayout>
</NestedScrollView>

I would recommend you to use Sectioned RecyclerView for this purpose. 我建议您为此使用Sectioned RecyclerView。 Every single item layout would have a cardView in it instead of creating a cardView as a parent. 每个项目布局都将具有cardView而不是将cardView创建为父对象。

Refer to this library: https://github.com/luizgrp/SectionedRecyclerViewAdapter 引用此库: https : //github.com/luizgrp/SectionedRecyclerViewAdapter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM