How to create Google + cards UI in a list view?
Asked Answered
L

5

27

I want to create a listView of cards, but after reading this blog post goolge-plus-layout, I'm cards are a viable solution for a list of anything. The animation part seems too memory intensive to load say a listview with more than 40 elements simultaneously.

Is there a better way to achieve a cards UI in listView?

Lermontov answered 10/7, 2013 at 12:51 Comment(5)
I think you should review the getView method once again. Please share your implementation detail.Monocular
a bit off tpoic but cards are not the default visual pattern to use for any list. They have a precise use among Google apps and should not be used randomly.Tanyatanzania
I disagree that cards should not be used for a list. This is the quickly emerging pattern (what do you think G+ uses to back their timeline UI - it is a ListView with customized adapters). Card UI FTW!Cardiac
this link will help you:technotalkative.com/lazy-productive-android-developer-4Harmsworth
is it possible to swap cards ??Normand
C
36

You can create a custom drawable, and apply that to each of your listview elements.

I use this one for cards in my UI. I don't think there is significant performance issues with this approach.

The drawable code (in drawable\big_card.xml) looks like this:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape android:shape="rectangle" >
            <solid android:color="@color/second_grey" />
        </shape>
    </item>
    <item
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp">
        <shape android:shape="rectangle" >
            <corners android:radius="3dp" />

            <solid android:color="@color/card_shadow" />
        </shape>
    </item>
    <item
        android:bottom="12dp"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp">
        <shape android:shape="rectangle" >
            <corners android:radius="3dp" />

            <solid android:color="@color/card_white" />
        </shape>
    </item>


</layer-list>

I apply the background to my listview elements like this:

<ListView
    android:id="@+id/apps_fragment_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:listSelector="@drawable/big_card" />

If you want to add this as a background to any View (not just a list), you just make the custom drawable that View's background element:

<TextView
        android:id="@+id/any_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/big_card" />
Cardiac answered 10/7, 2013 at 12:58 Comment(14)
I'm really curious about what colours you use.Caricature
I use <color name="second_grey">#ff999999</color> <color name="card_white">#ffffffff</color> <color name="card_shadow">#8c666666</color> (note the transparency on this color)Cardiac
Thanks. This looks really nice. I'm using your layout in my app, though, and I changed second_grey to #ffeeeeee which is a lot lighter (more googley, imho) - and moved it to the background of my view so there's less overdraw. I wish I could figure out how to get that shadow without overdraw.. Google+ does it somehow..Caricature
Somehow I am missing something. Could you please explain how the drawable is applied to the list item layout? When I try your approach, the big_card drawable is only shown when a list item is pressed.Alcmene
Change that from android:listSelector to android:backgroundCardiac
When I create a ListView, all of the items in the ListView end up on a single card... I'm very new to Android development, so I'm not understanding why it's putting all the text on a single card...Specific
If you are using the ViewHolder pattern (you should, it is very important) - you are probably not recycling your view correctly. I would start with a ViewHolder tutorial, essential first step. Good luck.Cardiac
Can you please edit your answer to show how do we add it to the listview elements as of now your answer states that how to add it complete listview..But I'm unable to get it worked for each individual listview element.Saveall
You would just add the element as a background to your adapter, instead of the list itself.Cardiac
I'm new to Android too, but I've read one note about this way (layer-list as CardView implementation) - 'I don't think the layer list is the way to go. Actually, it does the trick but it will lead to overdraw (draw twice the same pixel on your screen) which is not a good practice if you're a developer who's taking care of optimizing.' Is it true? Is there any way to solve dowuble-drawing?Corabella
I am not sure of another way to create this same effect (but I am open to suggestions, and will happily update this answer).Cardiac
I don't think there is a different way to achieve this effect (including the drop shadow, which is important to me) without a Layer-list (and thus over-draw).Cardiac
is it possible to swap cards ??Normand
I'm considering using a 9-patch image for the gray background, white card and its drop shadow. It would minimize overdraw (all is 1 layer), but I wonder if it negatively affects performance/at which point it does. Any way to measure this that you know? cc: @CorabellaDoloresdolorimetry
R
7

EDIT: Google provides a nice class called CardView. I didn't check it but it looks promising.

Here's the previous way, which also works fine (that's what I wrote before the edit) :

There is a nice tutorial here and a nice sample of it here .

in short , these are the files you can create:

listView definition:

android:divider="@null"
android:dividerHeight="10dp"
android:listSelector="@android:color/transparent" 
android:cacheColorHint="@android:color/transparent"
android:headerDividersEnabled="true"
android:footerDividersEnabled="true"

also this:

m_list.addHeaderView(new View(this));
m_list.addFooterView(new View(this));

res/drawable/selector_card_background.xml

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item
      android:state_pressed="true"
      android:drawable="@drawable/layer_card_background_selected" />

   <item android:drawable="@drawable/layer_card_background" />
</selector>

listView item :

res/layout/list_item_card.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:paddingLeft="15dp"
   android:paddingRight="15dp"
   android:descendantFocusability="beforeDescendants">

   <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:paddingLeft="15dp"
      android:paddingTop="15dp"
      android:paddingBottom="15dp"
      android:paddingRight="15dp"
      android:background="@drawable/selector_card_background"
      android:descendantFocusability="afterDescendants">

      <TextView
         android:id="@+id/text1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>

      <TextView
         android:id="@+id/text2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>

      <TextView
         android:id="@+id/text3"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>
   </LinearLayout>
</FrameLayout>

res/drawable/layer_card_background_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#CABBBBBB"/>
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item
        android:left="0dp"
        android:right="0dp"
        android:top="0dp"
        android:bottom="2dp">
        <shape android:shape="rectangle">
            <solid android:color="#CCCCCC"/>
            <corners android:radius="2dp" />
        </shape>
    </item>
</layer-list>

res/drawable/layer_card_background.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#CABBBBBB"/>
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item
        android:left="0dp"
        android:right="0dp"
        android:top="0dp"
        android:bottom="2dp">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white"/>
            <corners android:radius="2dp" />
        </shape>
    </item>
</layer-list>
Roumell answered 10/4, 2014 at 19:22 Comment(0)
H
2

If all you want is a ListView that simulates the cards-look you can use a 9-patch as background for your listitems to make them look like cards. You can find a 9-patch and some more tips and explanation here: http://www.tiemenschut.com/simply-get-cards-ui-look/

Hotze answered 14/2, 2014 at 12:26 Comment(0)
S
1

Add divider for the Listview item and padding :

 android:divider="@android:color/transparent"
    android:dividerHeight="1dip"

Add RelativeLayout into your LinearLayout for ListItem with some desired padding :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="100dp"
    android:orientation="vertical"
    android:padding="3dp" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:background="@drawable/rowshadow" >

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
...

Add Background to the listview item , like :

<?xml version="1.0" encoding="utf-8"?>
   <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item >
        <shape 
          android:shape="rectangle">
              <solid android:color="@android:color/darker_gray" />
              <corners android:radius="0dp"/>
        </shape>
     </item>
     <item android:right="1dp" android:left="1dp" android:bottom="2dp">
        <shape 
          android:shape="rectangle">
              <solid android:color="@android:color/white"/>
              <corners android:radius="0dp"/>
        </shape>
     </item>
   </layer-list>

Use https://github.com/elcrion/demo.cardlistview as an example. It is somehow close to google style

Swithbart answered 24/10, 2013 at 20:2 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Isodynamic
S
1

As "android developer" briefly mentions in his answer, the CardView class can be used to easily create card views.

Just wrap you UI widgets in a CardView element and you are ready to go. See the short introduction to the CardView widget at https://developer.android.com/training/material/lists-cards.html#CardView.

The CardView class requires a v7 support library, remember to add the dependencies to your .gradle file!

compile 'com.android.support:cardview-v7:21.0.+'
Socio answered 28/12, 2014 at 13:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.