Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

android - What is the best practice to group items into CardView?

CardView usually used to decorate exactly one element. But sometimes you need to wrap into this widget several items. Like in Inbox app, for example.

enter image description here

So what is the best way to do this? It can be implemented via custom LayoutManager or even custom ItemDecoration. Implementation of custom LayoutManager is not an easy task(with full support of animations, item decorations, etc). In the second option, the drawing of the boundaries must be implemented manually, ignoring CardView(and Android-L elevation) implementation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TL;DR:

It's not one CardView which hosts elements, it's several successive CardViews with different margins:

For the top CardView in group:

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

For the bottom CardView in group:

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

And the middle one, as set margins Top&Bottom to 0:

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

About Inbox app:

This is hierarchy of the app (of course, simplified a bit):

|android.support.v4.widget.DrawerLayout
---|FrameLayout
-------|android.support.v7.widget.RecyclerView
-------|android.support.v7.widget.Toolbar
---|android.support.design.widget.NavigationView

The full structure even without navigation drawer & collapsed cards looks like: enter image description here

The interesting part starts, when you dive into the RecyclerView's items structure.
There're 2 types of items Google uses - the separators (with date and actions on the right) and the cards. Even though cards have different content inside, from the ViewHolder perspective - RecyclerView has 2 types of items)

  1. Separator enter image description here

    This one is just a LinearLayout with TextView and ImageView inside:

    enter image description here

  2. Item Card
    enter image description here

    Its layout adjusts based on the content being bind to the ViewHolder For example, simple email like the one in focus is a CardView with nested ImageView and 3 TextViews:

    enter image description here

So the only question left, how do Google-guys "merge" cards into one big card and avoid extra shadows.

The trick is really simple:

  1. All CardView's have card_view:cardCornerRadius="0dp"
  2. Top CardView of the group have margin set 5dp for top/left/right, but 0dp for the bottom:

    android:layout_marginTop="5dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="0dp"
    
  3. Bottom CardView of the group have margin set 5dp for left/right/bottom, but 0dp for the top:

    android:layout_marginTop="0dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    
  4. Middle CardView of the group have margin set 5dp for left/right, but 0dp for the top/bottom:

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

That's it!

Here's a small example I've wrote:

enter image description here

The layout (with tricky margins)

<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>

I hope, it helps


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...