Basic Lesson 5: Customize Listview

Thảo luận trong 'Khóa học lập trình Android' bắt đầu bởi Nem, 10/4/13.

  1. Nem

    Nem Moderator

    Lượt xem: 9,689
    Trong bài này mình sẽ hướng dẫn các bạn customize một view thuộc nhóm List như: ListView và ExpandableListView bằng cách sử dụng các ArrayAdapter và dùng Cursor.

    ListView


    ListView using ArrayAdapter

    Giả sử bây giờ ListView của bạn sẽ dùng để hiển thị danh sách các người bạn và trạng thái của họ.nên mỗi item của ListView lúc này sẽ phải hiển thị nhiều hơn 1 thông tin. nên việc sử dụng "android.R.layout.simple_list_item_1" chắc là không đc rồi. vì "android.R.layout.simple_list_item_1" sẽ chỉ cho hiện 1 thông tin trên một dòng Text. Ở hướng dẫn sau đây tôi sẽ tùy chỉnh để mỗi item của ListView sẽ hiện lên 3 thông tin (Tên - String, Trạng Thái - String, và accept - boolean) các đối tượng của lớp Friend.
    • Lớp Friend được mô tả như sau:
    PHP:
    package com.namnd.gingerbread;
     
    import java.io.Serializable;
     
    public class 
    Friend implements Serializable{
        private 
    String nickName;
        private 
    String status;
        private 
    boolean checked;
        public 
    Friend(String nickName){
            
    this.nickName nickName;
            
    this.setChecked(false);
        }
        public 
    String getNickName(){
            return 
    this.nickName;
        }
        public 
    void setStatus(String status) {
            
    this.status status;
        }
        public 
    String getStatus() {
            return 
    this.status;
        }
        public 
    void setChecked(boolean checked) {
            
    this.checked checked;
        }
        public 
    boolean isChecked() {
            return 
    this.checked;
        }
        @
    Override
        
    public boolean equals(Object o) {
            
    // TODO Auto-generated method stub
            
    if(instanceof Friend) {
                
    Friend f = (Friend)o;
                return 
    this.nickName.equalsIgnoreCase(f.getNickName());
            }
            return 
    false;
        }
        @
    Override
        
    public int hashCode() {
            
    // TODO Auto-generated method stub
            
    return this.nickName.hashCode();
        }
    }
    • Sửa file main.xml như sau:
    PHP:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
      <ListView
            android:id="@+id/listfriend"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical"
        />
    </LinearLayout>
    • trong res/layout ta thêm 1 file tên là listview.xml với nội dung sau:
    PHP:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content">
      <CheckBox
      android:id="@+id/_check_nick"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text=""
      android:paddingTop="20px"
      android:paddingRight="10px"
      />
      <LinearLayout
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:orientation ="vertical"
      >
      <TextView
              android:id="@+id/_nickname"
              android:textSize = "15px"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:lines="1"
              android:textStyle="bold"
              android:textColor="#ff0099"
      />
      <TextView
              android:id="@+id/_status"
              android:textSize="13px"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:lines="1"
              android:textColor="#99ff00"
      />
      </LinearLayout>
    </LinearLayout>
    • file listview.xml sẽ tạo ra giao diện cách bố trí cho 1 item của ListView
    Thêm lớp CustomViewFriend trong package com.namnd.gingerbread ở trên. lớp này dùng để load giao diện trong file listview.xml nội dung như sau:
    PHP:
    package com.namnd.gingerbread;
     
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.widget.CheckBox;
    import android.widget.LinearLayout;
    import android.widget.TextView;
     
    public class 
    CustomViewFriend extends LinearLayout {
        
    CheckBox checkBox;
        
    TextView tvNickName;
        
    TextView tvStatus;
        
    Context context;
        public 
    CustomViewFriend(Context context) {
            
    super(context);
            
    // TODO Auto-generated constructor stub
            // su dung LayoutInflater de gan giao dien trong listview.xml
            
    this.context context;
            
    LayoutInflater li = (LayoutInflater)this.getContext()
            .
    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            
    li.inflate(R.layout.listviewthis,true);
     
            
    checkBox = (CheckBox)findViewById(R.id._check_nick);
            
    tvNickName= (TextView)findViewById(R.id._nickname);
            
    tvStatus = (TextView)findViewById(R.id._status);
        }
    }
    • CustomViewFriend của chúng ta ở đây khá đơn giản, đó là 1 LinearLayout chứa 2 thành phần: 1 CheckBox và 1 LinearLayout khác gồm 2 TextView để hiển thị nickName và status. Sau đó ta thêm 1 lớp có tên ListFriendAdapter cũng trong package trên, lớp này kế thừa từ lớp ArrayAdapter. ListFriendAdapter sẽ được sử dụng thay thế cho ArrayAdapter để bind với ListView. Thông thường ArrayAdapter chỉ cho hiển thị String bằng TextView, nhưng với việc kế thừa và override phương thức getView, ta có thể định nghĩa lại hiển thị cho các thành phần của ListView.
    PHP:
    package com.namnd.gingerbread;
     
    import java.util.ArrayList;
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.CheckBox;
    import android.widget.TextView;
     
    public class 
    ListFriendAdapter extends ArrayAdapter<Friend>{
        
    ArrayList<Friend> array;
        
    int resource;
        
    CheckBox check;
        
    TextView tvNickName;
        
    TextView tvStatus;
        
    Context context;
        
    Friend friend;
     
        public 
    ListFriendAdapter(Context contextint textViewResourceId,ArrayList<Friend> array) {
            
    super(contexttextViewResourceId,array);
            
    // TODO Auto-generated constructor stub
     
            
    this.context context;
            
    this.resource textViewResourceId;
            
    this.array = array;
        }
        
    //Phương thức xác định View mà Adapter hiển thị, ở đây chính là CustomViewFriend
        
    public View getView(int positionView convertViewViewGroup parent){
            
    View friendView convertView;
            if(
    friendView ==null ){
                
    friendView = new CustomViewFriend(getContext());
            }
            
    friend = array.get(position);
            if(
    friend !=null){
                
    tvNickName = ((CustomViewFriend)friendView).tvNickName;
                
    tvStatus = ((CustomViewFriend)friendView).tvStatus;
                
    check =((CustomViewFriend)friendView).checkBox;
                
    // lay doi tuong friend va dua ra UI
                
    tvNickName.setText(friend.getNickName());
                
    tvStatus.setText(friend.getStatus());
                
    check.setChecked(friend.isChecked());
            }
            return 
    friendView;
        }
     
    }
    Và việc cuối cùng cần làm là viết lại Activity. Tới ListDemo.java (extends Activity) và chỉnh sửa theo nội dung sau:
    PHP:
    package com.namnd.gingerbread;
     
    import java.util.ArrayList;
     
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ListView;
     
    public class 
    ListDemo extends Activity {
     
        private static final 
    int LOGOUT Menu.FIRST;
        private static final 
    int CHANGE Menu.FIRST+2;
        private static final 
    int EXIT = Menu.FIRST+6;
        private static final 
    int ABOUT Menu.FIRST+4;
     
            
    ArrayList<Friend> array;
        
    ListFriendAdapter arrayAdapter;
        
    ListView list;
        public 
    void onCreate(Bundle savedInstanceState){
            
    super.onCreate(savedInstanceState);
            
    setContentView(R.layout.main);       
            list = (
    ListView)findViewById(R.id.listfriend);
            array = new 
    ArrayList<Friend>();
            
    arrayAdapter = new ListFriendAdapter(thisR.layout.listview, array);
     
            list.
    setAdapter(arrayAdapter);
            
    Friend f = new Friend("namd");
            
    f.setStatus("Có ai thích tắm nước mắm không?");
            
    f.setChecked(true);
            
    this.addNick(f);
            
    this.addNickf= new Friend("MungTV"));
            
    this.addNick(new Friend("TuyenHL"));
            
    f.setStatus("nước mắm thơm quá đi mất");
            
    this.addNick(= new Friend("QuangLH"));
            
    f.setStatus("được tắm nước mắm thật sảng khoái quá đi mất! :D");
            
    f.setChecked(true);
            
    this.addNick(= new Friend("TuanPV"));
            
    f.setStatus("miễn bàn, tuy thích nhưng chắc không được");   
        }
        
    // tao Option Menu
        
    public boolean onCreateOptionsMenu(Menu menu){
            
    super.onCreateOptionsMenu(menu);
            
    menu.add(0,LOGOUT,0,"LogOut").setIcon(android.R.drawable.ic_menu_revert);
            
    menu.add(0,CHANGE,0,"Change Password").setIcon(android.R.drawable.ic_menu_edit);
            
    menu.add(0,ABOUT,0,"About").setIcon(android.R.drawable.ic_menu_info_details);
            
    menu.add(0,EXIT,0,"Exit").setIcon(android.R.drawable.ic_menu_close_clear_cancel);
            return 
    true;
        }
            
    // xu ly cac su kien cho menu
        
    public boolean onOptionsItemSelected(MenuItem item){
     
            return 
    true;
        }
     
        public 
    void addNick(Friend friend){
            array.
    add(0,friend);
            
    arrayAdapter.notifyDataSetChanged();
        }
    }
    Các bạn có thể lưu ý là thay vì sử dụng ArrayList<String> như trước mình đã thay bằng ArrayList<Friend> và trong khởi tạo đối tượng arrayAdapter thì đối số thứ 2 là R.layout.listview thay vì android.R.layout.simple_list_item_1, nghĩa là chúng ta đã sử dụng layout do mình tự tạo thay vì layout Android cung cấp sẵn cho hiển thị các thành phần của ListView. Kết quả khi chương trình chạy như sau:
    Android-less-5-1
    listview, custom listview, android, arrayadapter
    nhatchimai111, PhongBV, quynhcoi1653 others thích bài này.
  2. Vũ Duy Hoàng

    Vũ Duy Hoàng New Member

    thank anh bài viết rất bổ ích!
  3. hakoo4568

    hakoo4568 New Member

    hướng dẫn rất chi tiết ! cám ơn bạn vì bài viết !
  4. HaiHack

    HaiHack Member

    ListView của mình có CheckBox hoặc RadioButton, mỗi lần scrolling lên xuống là nó lại gọi lại làm getView làm mất trạng thái của nó, khắc phục kiểu gì bây giờ :rolleyes:
    Nếu đc xin demo Nem
  5. viet55pm

    viet55pm New Member

    Quá hay :)
  6. quocdai

    quocdai New Member

    hi ban, giờ mình thêm một cái button vào listview. Mỗi lần click thì thì thực hiện hàm RemoveNick(friend) thì truyền sự kiện kiểu gì nhỉ?
  7. quocdai

    quocdai New Member

    hi ban, giờ mình thêm một cái button vào listview. Mỗi lần click thì thì thực hiện hàm RemoveNick(friend) thì truyền sự kiện kiểu gì nhỉ?
  8. phuongvv0606

    phuongvv0606 New Member

    Bác ơi em muốn có sự kiện onclick ở trong listview này thì làm thế nào bác giúp em với ạg
  9. brucelee

    brucelee New Member

    PHP:
    Bạn lưu lại trạng thái của các CheckBox đó bằng cách tạo một mảng
    số nguyên int 
    [] arr có số phần tử bằng số lượng CheckBox Ban
    đầu cho các phần tử của mảng 
    =0
    Bắt sự kiện cho CheckBox 
    ,nếu CheckBox thứ position đang được check
    thì cho arr
    [position]=1,nếu CheckBox thứ position không được check
    thì cho arr
    [position]=0
        
    if(checkbox.isCheck){
             
    arr[position]=1;
        } else{
             
    arr[position]=0;
        }
    Trong hàm getView() bạn setChecked cho CheckBox thứ position như sau:
        if(
    arr[position]=1){
             
    checkbox.setChecked(true);
        } else{
             
    checkbox.setChecked(false);
        }

Chia sẻ trang này