1. 程式人生 > >自定義listView及其adapter動態重新整理

自定義listView及其adapter動態重新整理

轉自:http://www.2cto.com/kf/201203/122878.html


本文主要探討自定義的adapter及其notifyDataSetChanged()方法的使用(無listView的監聽部分):

先上圖看下效果:(整個操作過程中,當前Activity未被pause或者stop, 豌豆莢截的圖真大....無語)

1,初始化狀態,共20個dataItem

2, 15秒後向下滑動,增加了一個text100的item:

3,點選新增後,向下滑動,增加了一個text200的item(每點一次新增按鈕就會增加一個text200的item):

4,點選刪除按鈕,上下滑動(每點一次,listView中的item就減少一個):


 
程式碼部分未貼完整,有簡要註釋,未考慮優化
adapter.xml:
  
 

<ListView
        android:id="@+id/listview1"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:cacheColorHint="#00000000" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >

        <Button
            android:id="@+id/button_add"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="新增" >
        </Button>

        <Button
            android:id="@+id/button_delete"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="刪除" >
        </Button>
    </LinearLayout>

<ListView/>標籤中屬性android:layout_height="0dp"和android:layout_weight="1"保證了Android平臺在佈局時會先計算其他元素(linearLayout)的寬高,再計算當前listView的寬高等屬性,因android:layout_weight="XXX"預設值為0, 1的優先順序要比0低(如果整個xml是RelativeLayout佈局,就easy了,有直接的屬性可以設定)
兩個<Button/>標籤中的屬性android:layout_weight="1"和android:layout_width="0dp",使得他們的父元素在佈局時,為他們平均分配空間,如果在其中一個<Button/>設定了間隔,如android:layout_marginLeft = "xxxdp",那麼父元素會先減去此間隔xxxdp,剩下空間依舊平均分配給兩個button按鈕
如圖:

\


 

adapter_item.xml:
<TextView
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FF0000"
        android:textSize="25dp" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="150dp"
        android:focusable="false" />

 
Activity類AdapterActivity:
public class AdapterActivity extends Activity {

    private ListView listView;

    private List<HashMap<String, String>> data;

    private ListViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.adapter);

        listView = (ListView) findViewById(R.id.listview1);

        Button addButton = (Button) findViewById(R.id.button_add);
        Button deleteButton = (Button) findViewById(R.id.button_delete);
        ButtonListener listener = new ButtonListener();
        addButton.setOnClickListener(listener);
        deleteButton.setOnClickListener(listener);

        this.initListView();

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {// 15秒後向data集合中增加一條資料
                    @Override
                    public void run() {
                        HashMap<String, String> map = new HashMap<String, String>();
                        map.put("text", "text100");
                        map.put("buttonText", "buttonText100");
                        data.add(map);
                        Log.i(Constant.TAG, "新增資料成功");

                        // adapter.notifyDataSetChanged(); 非UI執行緒報錯

                        Message msg = new Message();
                        msg.what = 1;
                        handler.sendMessage(msg);
                    }
                }, 15000);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // super.handleMessage(msg);
            switch (msg.what) {
            case 1:
                // UI執行緒中呼叫此方法通知觀察者(原始碼中關於adapter存在一個observer,未深究!)adapter資料已改變,重新整理view
                adapter.notifyDataSetChanged();
                // adapter.notifyDataSetInvalidated();// 與上面
                // 效果相同,原始碼中除了註釋不同,執行的程式碼一樣,同樣未深究
                // listView.postInvalidate();重新整理無效
                break;
            }
        }
    };

    private void initListView() {
        data = ViewApp.getData();// ViewApp是一個全域性的類,程式執行時data資料即載入完畢,這是隻是賦值到data成員變數中www.2cto.com
        adapter = new ListViewAdapter(this, data, R.layout.adapter_item);
        SimpleAdapter simpleAdapter = new SimpleAdapter(this, data,
                R.layout.adapter_item, new String[] { "text", "buttonText" },
                new int[] { R.id.textview1, R.id.button1 });

        listView.setAdapter(adapter);
    }

    class ListViewAdapter extends BaseAdapter {

        private List<HashMap<String, String>> data;
        private int resource;
        private LayoutInflater inflater;

        private HashMap<String, String> itemData;

        public ListViewAdapter(Context context,
                List<HashMap<String, String>> data, int resource) {
            // super(context, data, resource, from, to);
            this.data = data;
            this.resource = resource;
            inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        // 渲染每一個item的資料,每次上下滑動顯示資料時都會呼叫此方法
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (null == convertView) {
                convertView = inflater.inflate(resource, null);

            }
            // convertView.setTag("abc");
            itemData = data.get(position);
            TextView textView = (TextView) convertView
                    .findViewById(R.id.textview1);
            textView.setText(itemData.get("text"));
            final Button button = (Button) convertView
                    .findViewById(R.id.button1);
            button.setText(itemData.get("buttonText"));
            button.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Toast.makeText(AdapterActivity.this, button.getText(),
                            Toast.LENGTH_SHORT).show();
                }
            });
            return convertView;
        }
    }

    class ButtonListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.button_add:

                HashMap<String, String> map = new HashMap<String, String>();
                map.put("text", "text200");
                map.put("buttonText", "buttonText200");
                data.add(map);
                Log.i(Constant.TAG, "ADD");

                break;
            case R.id.button_delete:
                Log.i(Constant.TAG, "DELETE");
                data.remove(1);
                break;
            }
            adapter.notifyDataSetChanged();// adapter更改後重新整理view
        }
    }

}