天天看點

Android查缺補漏之ListView

上一篇“查缺補漏”總結了Toolbar的用法,這次我們來看一看ListView。

或許很多人會認為Android出了RecyclerView之後就不用再去了解ListView了,但實際上,ListView作為一種展示清單的控件,曾經在很多的APP中大量的使用,在很多場景中都是很經典的,而且了解了ListView,也會更容易了解RecyclerView。

什麼是ListView

ListView是Android開發中非常重要的基礎元件之一,它使得開發者能夠很容易的展示一組資料。一般而言,實作一個ListView通常需要三個部分:ListView控件、Data資料、Adpter擴充卡,通過擴充卡實作将資料綁定到ListView裡面的控件中。

基本用法

和其他控件一樣,ListView需要先在布局檔案中聲明(當然特殊情況下也可以直接在Java中建立對象)

<ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
           

然後在相應的Acrivity中進行綁定

mListView = (ListView)findViewById(R.id.listview);
           

之後,建立一些資料,這裡我們需要使用ArrayList對資料進行管理

List<Map<String, String>> datas = new ArrayList<Map<String,String>>();
        Map<String,String> map1 = new HashMap<String,String>();
        map1.put("key","item1");
        datas.add(map1);
        Map<String,String> map2 = new HashMap<String,String>();
        map2.put("key","item2");
        datas.add(map2);
           

建立一個SimpleAdapter将資料放到listView中

mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_1,
                new String[]{"key"},
                new int[]{android.R.id.text1}
        ));
           

這樣一個最基本的ListView就完成了

Android查缺補漏之ListView

在上面的代碼中,可以看到在建立SimpleAdapter的時候,傳入了一個R.layout.simple_list_item_1的參數,這個參數用來确定item中展示的樣式,除了simple_list_item_1以外,還有一些其他的樣式。

樣式simple_list_item_2

simple_list_item_2是一種包含副标題的樣式,用法和simple_list_item_1類似,我們在設定資料的時候增加一個參數

List<Map<String, String>> datas = new ArrayList<Map<String,String>>();
        Map<String,String> map1 = new HashMap<String,String>();
        map1.put("key1","item1");
        map1.put("key2","value1");
        datas.add(map1);
        Map<String,String> map2 = new HashMap<String,String>();
        map2.put("key1","item2");
        map2.put("key2","value1");
        datas.add(map2);
           

建立一個新的SimpleAdapter,設定為simple_list_item_2

mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_2,
                new String[]{"key1","key2"},
                new int[]{android.R.id.text1,android.R.id.text2}
        ));
           

其中key1和key2的值分别對應android.R.id.text1和android.R.id.text2

Android查缺補漏之ListView

樣式simple_list_item_checked

simple_list_item_checked是一種選擇的樣式,用法和simple_list_item_1相似,也隻需設定一個key

mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_checked,
                new String[]{"key1"},
                new int[]{android.R.id.text1}
        ));
           

但是需要設定選擇的模式

/*
         * CHOICE_MODE_SINGLE  單選--ListView中隻能有一個item被選中
         * CHOICE_MODE_MULTIPLE  多選--允許選中多個item
         * CHOICE_MODE_NONE  預設值,點選沒反應
         */
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
           
Android查缺補漏之ListView

除此之外,還有simple_list_item_multiple_choice,simple_list_item_single_choice,可以實作其他的選擇樣式。

自定義布局

很多時候,這些自定義布局并不能滿足我們的需求,那麼便需要我們自己定義item的布局。比如我們建立一個布局檔案名為list_item.xml,裡面放了一個高度為150dp的TextView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="150dp">

    <TextView
        android:gravity="center"
        android:id="@+id/text"
        android:text="asd"
        android:layout_width="match_parent"
        android:layout_height="150dp" />
    
</LinearLayout>
           

然後在activity中建立SimpleAdapter

mListView.setAdapter(new SimpleAdapter(this,datas,R.layout.list_item,
                new String[]{"key1"},
                new int[]{R.id.text}
        ));
           

就可以在ListView中看到我們自定義的布局

Android查缺補漏之ListView

自定義擴充卡

雖然自定義了布局,但是在很多時候使用SimpleAdapter并不能滿足我們的需求,我們可以通過自己定義擴充卡的方式實作我們期望的各種效果,比如我們再次實作上圖的效果,建立一個繼承BaseAdapter的擴充卡

package com.example.steveyg.listdemo;

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

/**
 * Created by steveyg on 17/1/16.
 */

public class MyAdapter extends BaseAdapter{

    //資料集
    String []datas = {"item1","item2"};
    Context context;

    public MyAdapter(Context context){
        this.context = context;
    }
    @Override
    public int getCount() {
        return datas.length;
    }

    @Override
    public Object getItem(int position) {
        return datas[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater li = LayoutInflater.from(context);
        TextView tv = (TextView) li.inflate(R.layout.list_item, null);
        tv.setText(datas[position]);
        return tv;
    }
}
           

在這個擴充卡裡面重寫5個方法,通過view的方式生成view進行處理,這樣就可以使得item更加複雜,實作更多的效果,甚至可以傳回不同的樣式。而資料集datas也可以使用List的方式傳入,更加的靈活。

ViewHolder

當ListView裡面的資料特别多的時候,如果每次都重新建立一個View的話,會占用大量記憶體,對性能造成影響,是以我們需要通過重新填充的方式減少對象的建立。

Android查缺補漏之ListView

圖檔來自網絡 修改我們的Adapter

package com.example.steveyg.listdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Created by steveyg on 17/1/16.
 */

public class MyAdapter extends BaseAdapter {

    //資料集
    String[] datas = {"item1", "item2"};
    Context context;

    public MyAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getCount() {
        return datas.length;
    }

    @Override
    public Object getItem(int position) {
        return datas[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;
        if (convertView == null) {
            convertView = LinearLayout.inflate(context, R.layout.list_item, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.textview.setText(datas[position]);
        return convertView;
    }

    class ViewHolder {
        TextView textview;

        public ViewHolder(View view) {
            this.textview = (TextView) view.findViewById(R.id.text);
        }
    }
}
           

這樣便實作了view holder對于adapter的優化。

點選事件

ListView的點選事件可以通過listview實作也可以通過adaper設定,如果使用了SimpleAdapter則需要通過listview實作:

//點選事件
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //點選了第position個item
            }
        });

        //長按事件
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                return false;
            }
        });
           

而如果通過adapter設定,那麼直接在getView中設定各個控件的點選事件即可。

繼續閱讀