【问题标题】:What is the best practice to group items into CardView?将项目分组到 CardView 的最佳做法是什么?
【发布时间】:2015-09-25 05:09:03
【问题描述】:

CardView 通常只用来装饰一个元素。但有时您需要将几个项目包装到这个小部件中。例如,在 Inbox 应用中。

那么最好的方法是什么?它可以通过自定义 LayoutManager 甚至自定义 ItemDecoration 来实现。自定义 LayoutManager 的实现不是一件容易的事(完全支持动画、项目装饰等)。在第二个选项中,边界的绘制必须手动实现,忽略 CardView(和 Android-L 高程)实现。

【问题讨论】:

  • 使用 uiautomatorviewer 看看 Inbox 应用是如何做到的。

标签: android android-recyclerview android-cardview


【解决方案1】:

TL;DR:

托管元素的不是一个CardView,而是几个连续的CardViews,具有不同的边距:

对于组内排名靠前的CardView

    android:layout_marginTop="5dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="0dp"
    card_view:cardCornerRadius="0dp"

对于组中底部的CardView

    android:layout_marginTop="0dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    card_view:cardCornerRadius="0dp"

还有中间的,设置页边距 Top&Bottom 为 0:

    android:layout_marginTop="0dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="0dp"
    card_view:cardCornerRadius="0dp"

关于 Inbox 应用:

这是应用程序的层次结构(当然,简化了一点):

|android.support.v4.widget.DrawerLayout
---|框架布局
-------|android.support.v7.widget.RecyclerView
--------|android.support.v7.widget.Toolbar
---|android.support.design.widget.NavigationView

即使没有导航抽屉和折叠卡片,完整结构也如下所示:

当您深入了解RecyclerView 的项目结构时,有趣的部分就开始了。
Google 使用了 2 种类型的项目 - 分隔符(右侧带有日期和操作)和卡片。尽管卡片内部有不同的内容,但从 ViewHolder 的角度来看 - RecyclerView 有两种类型的项目)

  1. 分隔符

    这只是一个LinearLayout,里面有TextViewImageView

  2. 物品卡片

    它的布局会根据被绑定ViewHolder的内容进行调整 例如,像焦点这样的简单电子邮件是CardView,其中嵌套了ImageView 和3 个TextViews:

所以剩下的唯一问题是,谷歌人如何将卡片“合并”成一张大卡片并避免额外的阴影。

诀窍很简单:

  1. 所有CardView 都有card_view:cardCornerRadius="0dp"
  2. 组的顶部CardView 的顶部/左侧/右侧边距设置为 5dp,底部设置为 0dp:

    android:layout_marginTop="5dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="0dp"
    
  3. 组的底部CardView 的左/右/下边距设置为 5dp,但顶部为 0dp:

    android:layout_marginTop="0dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    
  4. 组的中间CardView 的边距设置为左/右 5dp,但上/下边距设置为 0dp:

    android:layout_marginTop="0dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="0dp"
    

就是这样!

这是我写的一个小例子:

布局(带有棘手的边距)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    xmlns:card_view="http://schemas.android.com/apk/res-auto">
    <android.support.v7.widget.CardView
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="0dp"
        card_view:cardCornerRadius="0dp"
        card_view:contentPadding="10dp">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:text="card1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"/>
        </FrameLayout>
    </android.support.v7.widget.CardView>
    <android.support.v7.widget.CardView
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="0dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="0dp"
        card_view:cardCornerRadius="0dp"
        card_view:contentPadding="10dp">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:text="card2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"/>
        </FrameLayout>
    </android.support.v7.widget.CardView>
    <android.support.v7.widget.CardView
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="0dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="5dp"
        card_view:cardCornerRadius="0dp"
        card_view:contentPadding="10dp">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:text="card3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"/>
        </FrameLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

希望对你有帮助

【讨论】:

  • 据我了解,这种方法会导致透支。一开始它会绘制顶部元素的所有阴影,然后 Recycler 添加下一个部分隐藏阴影的卡片视图。
  • @veon 好吧,这就是 Inbox 所做的。不完全是过度绘制,只是在 CardViews 的交界处左右有一点阴影重叠。
  • @veon 正确的方法是像上面写的那样做 - 一个 recyclerview,几种类型的 ViewHolders,连续的 CardViews“假”组行为。肮脏的解决方案 - 将 LinearLayout 放入 CardView 并在其中动态创建行。这很糟糕,因为你的巨大 CardView 将被一次性回收,如果它太大 - 它可能会导致 OutOfMemory 等。即你正在扼杀 RecyclerView 的所有意义。但是,如果您的列表中等大 - 您可以尝试看看它是否适合您。
  • 在 Android 4.4.4 中这不起作用,因为卡片的布局中间有空格:i.stack.imgur.com/pDWzl.png 我在这里读到:stackoverflow.com/questions/27599603/…“CardView 中的内容区域在 pre 采用不同的大小-棒棒糖和棒棒糖设备"
  • @thekekc 尝试添加负值边距,它对我有用。 android:layout_marginBottom="-5dp"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多