整理一下Android中的ListView

Android中的listview目測是一個使用頻率很高的組件,所以今天來總結一下listview的基礎的用法。


一、最基本的綁定

java代碼:

package com.tmnw;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
    /*----ListView MVC實現----*/
    // model
    List<String> data;
    // view
    ListView lv;
    // controller
    ArrayAdapter<String> adapter;
    int size = 1;
    // 初始化組件
    private void initWidget() {
        lv = (ListView) findViewById(R.id.list);
    }
    // 初始化綁定數據
    private void initData() {
        if (lv == null)
            return;
        // 第一步:獲取數據源(model)
        data = new ArrayList<String>();
        appendData();
        // 第二步:new一個適配器(controller)
        // 參數1:Context
        // 參數2:listview的item佈局
        // 參數3:數據填充在item佈局下的那個控件id
        // 參數4:填充的數據
        adapter = new ArrayAdapter<String>(this, R.layout.simple_text,
                R.id.text1, data);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
        // 第三步:給listview設置適配器(view)
        lv.setAdapter(adapter);
    }
    // 添加數據
    private void appendData() {
        if (data == null)
            return;
        for (int i = 0; i < 10; i++) {
            data.add("" + size++);
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWidget();
        initData();
    }
}

吐槽一下爲神馬把我代碼裏的空行去掉了,感覺好難看

xml代碼:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1" >
    </ListView>
</LinearLayout>

simple_text.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp"
    android:textIsSelectable="false" />

畫面效果:



二、給ListView添加頭和尾部

java代碼:

// 初始化組件
    private void initWidget() {
        lv = (ListView) findViewById(R.id.list);
        header = getLayoutInflater().inflate(R.layout.simple_text, null);
        ((TextView) header.findViewById(R.id.text1)).setText("這是一個頭部");
        footer = getLayoutInflater().inflate(R.layout.simple_text, null);
        ((TextView) footer.findViewById(R.id.text1)).setText("加載中...");
    }
// 初始化綁定數據
    private void initData() {
        if (lv == null)
            return;
        // 第一步:獲取數據源(model)
        data = new ArrayList<String>();
        appendData();
        // 第二步:new一個適配器(controller)
        // 參數1:Context
        // 參數2:listview的item佈局
        // 參數3:數據填充在item佈局下的那個控件id
        // 參數4:填充的數據
         adapter = new ArrayAdapter<String>(this, R.layout.simple_text,
         R.id.text1, data);
        // 第三步:給listview設置適配器(view)
        // addHeaderView和addFooterView一定要有一個在setAdapter之前調用,或者2個都在setAdapter之前調用
        lv.addHeaderView(header);
        lv.setAdapter(adapter);
        // 這裏的參數null是數據,false說明是不能被選中的
        lv.addFooterView(footer, null, false);
        // 設置尾部無分割線,頭部不想要分割線同理
        lv.setFooterDividersEnabled(false);
    }

只貼了部分修改過的代碼

畫面效果:

三、給ListView添加下滑加載中的一種實現方式

因爲listview要滾動,所以給它添加滾動監聽,爲了書寫簡便,我讓本Activity實現了OnScrollListener

public class MainActivity extends Activity implements OnScrollListener

java代碼:

先增加幾個變量

Button scrollInfo;
Thread currentThread;

初始化組件代碼修改下

lv = (ListView) findViewById(R.id.list);
        scrollInfo = (Button) findViewById(R.id.scroll_info);
        header = getLayoutInflater().inflate(R.layout.simple_text, null);
        ((TextView) header.findViewById(R.id.text1)).setText("這是一個頭部");
        footer = getLayoutInflater().inflate(R.layout.simple_text, null);
        ((TextView) footer.findViewById(R.id.text1)).setText("加載中...");


在onCreate中添加

lv.setOnScrollListener(this);

實現OnScrollListener方法:

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    // 手指接觸屏幕滑動
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        // 手指離開屏幕做慣性滑動
    case OnScrollListener.SCROLL_STATE_FLING:
        // 當滑動要最後一行時加載數據
        if (view.getLastVisiblePosition() == view.getCount() - 1) {
            // 可以通過網絡加載數據等。
            // 判斷是否還是在加載中
            if (currentThread == null || !currentThread.isAlive()) {
                // 添加listview尾部控件加載中
                lv.addFooterView(footer, null, false);
                // 啓動線程加載數據
                currentThread = new DataLoadThread();
                currentThread.start();
            }
        }
        break;
    // 不滑動
    case OnScrollListener.SCROLL_STATE_IDLE:
        break;
    }
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    // firstVisibleItem:第一個顯示的item位置
    // visibleItemCount:當前顯示的item個數
    // totalItemCount:listview的item總個數
    scrollInfo.setText("first:" + firstVisibleItem + "  visible:"
            + visibleItemCount + "  total:" + totalItemCount);
}

添加加載數據的線程

// 模擬加載數據
    class DataLoadThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                appendData();
                // 因爲Android控件只能通過主線程(ui線程)更新,所以用此方法
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 加載完畢,移除尾部控件
                        lv.removeFooterView(footer);
                        // 當數據改變時調用此方法通知view更新
                        adapter.notifyDataSetChanged();
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

畫面效果:

四、給ListView添加item點擊事件

爲了書寫簡便,我讓本Activity實現了OnItemClickListener

public class MainActivity extends Activity implements OnScrollListener,
        OnItemClickListener

java代碼:

然後實現其方法

@Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        Toast.makeText(
                this,
                "position:" + position + "  item:"
                        + parent.getItemAtPosition(position).toString(),
                Toast.LENGTH_LONG).show();
    }

給listview添加監聽

lv.setOnItemClickListener(this);


畫面效果:

(模擬器出問題了使用了真機調試,沒想到圖片這麼大,不過比模擬器快多了)


五、自定義適配器的使用

java代碼:

// 自定義基礎適配器
    class MyAdapter extends BaseAdapter {
        // listview顯示的個數,如果有數據源有10條,而返回5,那麼lv永遠只能顯示5條
        // 所以最好就返回數據源的條數就好了
        @Override
        public int getCount() {
            return data.size();
        }
        // 獲取item綁定的數據時調用
        @Override
        public Object getItem(int position) {
            return data.get(position);
        }
        // itemId
        @Override
        public long getItemId(int position) {
            return position;
        }
        // lv顯示幾個item就會調用幾次此方法,然後返回一個view對象顯示
        // position:位置
        // convertView:如果lv不能顯示全部的數據,那麼滾動後會把從顯示到不顯示的View傳進來複用
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            if (convertView == null) {
                view = getLayoutInflater().inflate(R.layout.simple_text, null);
            } else {
                view = convertView;
            }
            TextView tv = (TextView) view.findViewById(R.id.text1);
            tv.setText(data.get(position));
            // 隔行變色,可以隨心所欲
            if ((position & 1) == 1) {
                tv.setBackgroundResource(android.R.color.holo_green_light);
            } else {
                tv.setBackgroundResource(android.R.color.holo_red_light);
            }
            return view;
        }
    }


然後修改一下setAdapter()

// adapter = new ArrayAdapter<String>(this, R.layout.simple_text,
        // R.id.text1, data);
        adapter = new MyAdapter();


畫面效果:


源   碼

(基礎的到此爲止,又是一個雞肉味的週末)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章