Customizing Android ListView Items with Custom ArrayAdapter

来源:互联网 发布:java编写九九乘法表 编辑:程序博客网 时间:2024/06/06 02:35

http://www.ezzylearning.com/tutorial.aspx?tid=1763429&q=customizing-android-listview-items-with-custom-arrayadapter

很典型的分析文章,值得一读

For real-world commercial mobile applications, the default look and feel of the Android ListView is not very attractive. It only renders a simple String in every ListView row using the internal TextView control. For most applications, you want to create an interface that is more graphically rich and visually pleasing to the user. Luckily, ListView is very powerful control and with the help of custom item layouts, it can be customized to suit your needs easily. In this tutorial, I will show you how you can create custom ListView items with icons, custom header layout and how you can use custom ArrayAdapter to glue everything together. I will also show you some performance improvement tips you can use to optimize the memory usage of your ListView control.
Android Custom ListView and Custom ArrayAdapter

Create a new Android project in Eclipse with MainActivity as your default Activity andmain.xmlas your default layout file. Declare a ListView control in yourmain.xml layout file as shown in the following code.

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF">
   
     <ListView
        android:id="@+id/listView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
     
</LinearLayout>

The above code is using simple LinearLayout with vertical orientation, and a ListView is declared to cover the entire width and height of the parent container using thefill_parent as the value of both android:layout_height andandroid:layout:width properties. ListView also has a unique id listView1 that will be used in the MainActivity to reference the ListView control.

To create the custom header for the ListView, create a new xml layout file listview_header_row.xml in the layout folder of your project and declare a TextView control in it with the properties shown in the following code. This will create a blue header with the white color text showing Weather Photos.


listview_header_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
       
     
<TextView android:id="@+id/txtHeader"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center_vertical"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:textStyle="bold"
        android:textSize="22dp"
        android:textColor="#FFFFFF"
        android:padding="10dp"
        android:text="Weather Photos"
        android:background="#336699" />


</LinearLayout>

To create a custom ListView row, create another xml layout filelistview_item_row.xml in the project layout directory. Android will render this file content in every ListView item and you are free to declare any control you want in it. For this tutorial I am using an ImageView for an icon and a TextView for displaying items titles. Following is the code forlistview_item_row.xml file.

listview_item_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp">
   
     
<ImageView android:id="@+id/imgIcon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:gravity="center_vertical"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="15dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp" />
       
     <TextView android:id="@+id/txtTitle"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center_vertical"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:textStyle="bold"
        android:textSize="22dp"
        android:textColor="#000000"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp" />

       
</LinearLayout>

For this tutorial, I have downloaded some 32 x 32 pixels icons in PNG format. You can use your own icons if you want. Once your icons are ready, drag the icons from your folder to the projectdrawable-mdpi directory. Next create a new Java class in your project and named itWeather.java. This class will be used to create a custom ArrayAdapter and to bind the objects with the ListView later in this tutorial. Following is the code ofWeather.java class. It has two simple properties icon and title and a typical class constructor to initialize the properties.

Weather.java
public class Weather {
    public int icon;
    public String title;
    public Weather(){
        super();
    }
   
    public Weather(int icon, String title) {
        super();
        this.icon = icon;
        this.title = title;
    }
}

Notice that the above listview_item_row.xml file has two views, which are correspondent to the properties of theWeather class. The values of the Weather class properties will be displayed on those views and to connect these two pieces together you need to create a custom ArrayAdapter that will inherit the Android ArrayAdapter class and will override thegetView method. Add a new java class in your project with the nameWeatherAdapter and implement the code as shown below:


WeatherAdapter.java
public class WeatherAdapter extends ArrayAdapter<Weather>{

    Context context;
    int layoutResourceId;   
    Weather data[] = null;
   
    public WeatherAdapter(Context context, int layoutResourceId, Weather[] data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }

   
@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        WeatherHolder holder = null;
       
        if(row == null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
           
            holder = new WeatherHolder();
            holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
            holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
           
            row.setTag(holder);
        }
        else
        {
            holder = (WeatherHolder)row.getTag();
        }
       
        Weather weather = data[position];
        holder.txtTitle.setText(weather.title);
        holder.imgIcon.setImageResource(weather.icon);
       
        return row;
    }

   
    static class WeatherHolder
    {
        ImageView imgIcon;
        TextView txtTitle;
    }
}

In the above code, the first important thing is the constructor of the class that takes three parameters. The first parameter is the Context and we can pass the reference of the activity in which we will use WeatherAdapter class. The second parameter is the resource id of the layout file we want to use for displaying each ListView item. We will pass the resource id of our layout filelistview_item_row.xmlfor this parameter. The third parameter is an array ofWeather class objects that will be used by the Adapter to display data.

Next the parent class getView method is overridden. This method will be called for every item in the ListView to create views with their properties set as we want. ThegetViewmethod is also using a temporary holder class declared inside theWeatherAdapterclass. This class will be used to cache the ImageView and TextView so they can be reused for every row in the ListView and this will provide us a great performance improvement as we are recycling the same two views with different properties and we don’t need to find ImageView and TextView for every ListView item. The above code is also using the Android built in Layout Inflator to inflate (parse) the xml layout file.

The final piece of code is our application MainActivity in which we will be using all the above objects we declared. Following is the code of theMainActivity.java file.


MainActivity.java
public class MainActivity extends Activity {

    private ListView listView1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
       
Weather weather_data[] = new Weather[]
        {
            new Weather(R.drawable.weather_cloudy, "Cloudy"),
            new Weather(R.drawable.weather_showers, "Showers"),
            new Weather(R.drawable.weather_snow, "Snow"),
            new Weather(R.drawable.weather_storm, "Storm"),
            new Weather(R.drawable.weather_sunny, "Sunny")
        };
       
        WeatherAdapter adapter = new WeatherAdapter(this,
                R.layout.listview_item_row, weather_data);

       
       
        listView1 = (ListView)findViewById(R.id.listView1);
        
       
View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
        listView1.addHeaderView(header);
       
        listView1.setAdapter(adapter);

    }

There are few things in theMainActivitythat required explanation for your better understanding. First notice, we are creating an array of Weather class objects and icons and titles are passed as constructor parameters. Next,WeatherAdapterobject is created and listview_item_row.xml layout file resource id and Weather objects array is passed in its constructor. Once again, we are using Android Layout Inflator to inflate ourlistview_header_row.xml layout file and once it is parses as header View it is passed as a parameter of ListViewaddHeaderView method. Finally we are passing our custom adapter to ListViewsetAdapter method. That’s about it. You are ready to build and run our project. If everything implemented properly you will see the following output.

Android Custom ListView and Custom ArrayAdapter


原创粉丝点击