Test Script

Sunday, December 29, 2013

Android Card Layout

I have been using the Card layout in my apps for quite a while now and I absolutely love the look they provide. I recently came across the updated Book My Show app which leverages the Card Layout as well and I liked it. So I decided to write a small tutorial on how to use the Card Layout in your app, I have tried to replicate the BMS app to some extent(Also we won't be using any external libraries to get the Card Layout). Here is what the end result will look like :





Looks great, doesn't it ? So what are we waiting for lets get going. We are going to use 3 classes, 2 xml files and an image to achieve that.


Update : I have improved this tutorial by using nine patch images. I have the code updated on the Github Repo. I have now updated this tutorial to reflect the same. Now I set the background of the list_row.xml to the nine patch image.

 


MainActivity.java

package com.example.testcardlayout;

import java.util.ArrayList;
import java.util.List;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ListView;

public class MainActivity extends Activity {

 private List rowItems;

    private static Integer[] images = {
            R.drawable.red,
            R.drawable.red,
            R.drawable.red,
            R.drawable.red,
            R.drawable.red,
            R.drawable.red,
            R.drawable.red,            
            R.drawable.red
    };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  // Intialize and set the Action Bar Background to Holo Blue
  ActionBar actionBar = getActionBar();
  actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#33b5e5" )));
  
  ListView lv = (ListView) findViewById(R.id.myList);
  rowItems = new ArrayList();
   
         String[] titles = {"Movie1","Movie2","Movie3","Movie4","Movie5","Movie6","Movie7","Movie8"};
         String[] descriptions = {"First Movie","Second movie","Third Movie","Fourth Movie","Fifth Movie",
           "Sixth Movie","Seventh Movie","Eighth Movie"};
        
                //Populate the List
         for (int i = 0; i < titles.length; i++) {
             RowItem item = new RowItem(images[i], titles[i], descriptions[i]);
             rowItems.add(item);
         }

         // Set the adapter on the ListView
         LazyAdapter adapter = new LazyAdapter(getApplicationContext(), R.layout.list_row, rowItems);
         lv.setAdapter(adapter);
 }

}

Let me explain what we did there :


  1. Defined a set of images, I have all pointing to the same image in the drawable folder. These images are going to be used for the imageview. Typically in a real life scenario these images will be added dynamically from your server.
  2. We then initialized the ActionBar and set the background to HOLO Blue.
  3. We populated the rowItems list with RowItem objects(RowItem is a simple POJO class)
  4. We then create an instance of the LazyAdapter(Our Custom Adapter) and  set it to our listview.
  5. Also note we passed in the resource for each list item as R.layout.list_row. This defines what each list item will contain.

Now lets have a look at out Custom Adapter:

LazyAdapter.java

package com.example.testcardlayout;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class LazyAdapter extends ArrayAdapter {

    Context context;

    public LazyAdapter(Context context, int resourceId, List items){
        super(context, resourceId, items);
        this.context = context;
    }

    public class ViewHolder{
        ImageView image;
        TextView title;
        TextView description;
    }


    public View getView(int position, View convertView, ViewGroup parent){
        ViewHolder holder;
        RowItem rowItem = getItem(position);

        LayoutInflater mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null){
            convertView = mInflater.inflate(R.layout.list_row, null);
            holder = new ViewHolder();
            holder.image = (ImageView)convertView.findViewById(R.id.list_image);
            holder.title = (TextView)convertView.findViewById(R.id.title);
            holder.description = (TextView)convertView.findViewById(R.id.description);
            convertView.setTag(holder);
        } else
            holder = (ViewHolder)convertView.getTag();

        holder.image.setImageResource(rowItem.getImageId());
        holder.title.setText(rowItem.getTitle());
        holder.description.setText(rowItem.getDesc());

        return convertView;
    }

Here I implement a custom Adapter for our ListView. I have made use of the Holder pattern to make sure the performance of our ListView is maximum. But if none of this makes sense to you at the moment, don't worry I am planning to write a small tutorial on the same soon. For now trust me and agree with me on this.

There is one final java class which is the POJO class:

RowItem.java
package com.example.testcardlayout;

public class RowItem {
    private int imageId;
    private String title;
    private String description;

    public RowItem(int imageId, String title, String desc) {
        this.imageId = imageId;
        this.title = title;
        this.description = desc;
    }
    public int getImageId() {
        return imageId;
    }
    public void setImageId(int imageId) {
        this.imageId = imageId;
    }
    public String getDesc() {
        return description;
    }
    public void setDesc(String desc) {
        this.description = desc;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    @Override
    public String toString() {
        return title + "\n" + description;
    }
}

Now let us have a look at the XML files which define our layouts :

1. activity_main.xml

This layout defines a plain simple ListView within a Linear Layout



    




2. list_row.xml

This layout defines a an ImageView and 2 TextViews to be displayed as an individual list item. Also look at how I set the background of this layout to @drawable/card_greenborder. That gives it the Card look.



       
    
    



    







That's all ! Congratulations, you have successfully built the Card Layout and can now use it in your app. A few things to note here though :

  • I have used a Nine Patch drawable for better performance.
  • This was just a simple demo of how to achieve the Card UI in your app without using any external libraries, you can customize the list_row.xml to suit your needs.
  • A big thanks to Andrew Ruffalo for his help on the card background.
  • Also beginning from this tutorial onwards I will be maintaining a Github repo to post all the source code I develop for tutorials.
Source Code :  Github

Feel free to drop me a comment below if you like my tutorial or if you run into any problem. I would really appreciate it if you could share this post if you liked it.
UA-42774700-1 Twitter Bird Gadget