Bài 10. ListView


ListView

ListView là một trong những view rất quen thuộc đối với những ai lập trình ứng dụng cho Android. Nó giúp ta hiển thị một danh sách nào đó trong ứng dụng.Sau đây là giao diện của ListView.

Giao diện

Bây giờ tạo 1 giao diện bao gồm các 1 TextView và 1 ListView như sau :

 listview1

File activity_main.xml:

 

<LinearLayoutxmlns:Android="http://schemas.Android.com/apk/res/Android"
   xmlns:tools="http://schemas.Android.com/tools"
  tools:context="apps1pro.com.MainActivity"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical”>
 
   <TextView
  android:id="@+id/textView1"
  android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Danh sach "
      android:textSize="25sp"/>
 
    <ListView
        android:id="@+id/ lvDanhSach."
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

Mọi người có thể thấy trong ListView cũng có các thuộc tính cơ bản tương tự như các View khác. Với ví dụ trên ta đã set ID cho ListView này là lvDanhSach. 


Dữ liệu truyền vào ListView

Trường hợp 1: Sử dụng ListView control với mảng dữ liệu định sẵn.

Bây giờ để đổ dữ liệu vào trong ListView thì ta sẽ quay sang file MainActivity.java:

package apps1pro.com;
importAndroid.support.v7.app.ActionBarActivity;
importAndroid.app.Activity;
importAndroid.os.Bundle;
importAndroid.view.Menu;
importAndroid.view.MenuItem;
importAndroid.widget.ArrayAdapter;
importAndroid.widget.ListView;
publicclassMainActivityextendsActivity
{
    publicString[] danhSach ={"Lập Trình","Android","Winfrom ","Software","Tài Liệu","C++","C#"};
privateListView lvDanhSach;
privateArrayAdapter<String> mainAdapter;
          @Override
          protectedvoid onCreate(Bundle savedInstanceState)
          {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
                   lvDanhSach =(ListView)
                             findViewById(R.id.lvDanhSach);        

                   mainAdapter=newArrayAdapter<String>(this,android.R.layout.simple_list_item_1,danhSach);
                   lvDanhSach.setAdapter(mainAdapter);
          }
} 

- Mọi người thấy một mảng String chứa các dữ liệu mà ở đây là danh sách:

public String [] danhSach ={"Lập Trình", "Android", “Winfrom ", "Software", "Tài Liệu","C++","C#"};

- Khai báo 1 ArrayAdapter với tên là mainAdapter. ArrayAdapter ở đây các bạn có thể hiểu nó là thứ trung gian trong việc lấy dữ liệu danh sách và đẩy chúng vào Listview.

private ArrayAdapter<String> mainAdapter;

- Khai báo 1 ListView và liên kết nó tới Listview trong phần XML đã tạo ở trên thông qua ID mà ta đã gắn trước

private ListView lvDanhSach;

lvDanhSach = (ListView) findViewById(R.id.lvDanhSach);

- Khi bạn khởi tạo 1 Adapter lên thì nó sẽ có sẵn  phần từ đó là Android.R.layout.simple_list_item_1 phần tử này được Android xây dựng sẵn cho bạn và nó có nhiệm vụ  lưa trữ dữ liệu được truyền vào:

mainAdapter = new ArrayAdapter<String>(this, Android.R.layout.simple_list_item_1,danhSach);

lvDanhSach.setAdapter(mainAdapter);


Trường hợp 2: Sử dụng ListView với mảng dữ liệu được lưu trong XML

       - Giao diện và xử lý sự kiện trong trường hợp này là tương tự trường hợp 1. Chỉ khác ở chỗ là dữ liệu sẽ được load từ XML, nên mình chỉ hướng dẫn cách tạo String Array trong XML và cách load String-Array trong coding như thế nào.
       - Bạn tạo một Android Project tên là: Vidu_ListView_Xml_Array

       - Để tạo String – Array trong XML bạn làm như sau:

Bước 1: Bấm chuột phải vào thư mục values của Project/ chọn New/Values resource file:  

lv11

 

Bước 2: Màn hình Values resource file hiển thị lên, bạn đặt tên tập tin là array1.xml rồi nhấn nút OK:

lv12

 

Xem kết quả khi bấm nút Finish và quan sát:

lv13

- Xem nội dung XML:

<?xml version="1.0" encoding="utf-8"?>

<resources>

<string-array name="myarray">

        <item>Chaper 1: Compilers</item>

        <item>Chaper 2: Structure of a program</item>

        <item>Chaper 3: Variables and types</item>

        <item>Chaper 4: Constants</item>

        <item>Chaper 5: Operators</item>

        <item>Chaper 6: Basic Input/Output</item>

        <item>Chaper 7: Statements and flow control</item>

        <item>Chaper 8: Functions</item>

        <item>Chaper 9: Name visibility Scopes</item>

        <item>Chaper 10: Arrays</item>

        <item>Chaper 11: Character sequences</item>

        <item>Chaper 12: Pointers</item>

        <item>chapter 13: Dynamic memory</item>

        <item>chapter 14: Data structures</item>

        <item>chapter 15: Other data types</item>

        <item>chapter 16: Classes (I)</item>

        <item>Chapter 17: Classes (II)</item>

        <item>Chapter 18: Special members</item>

        <item>Chapter 19: Friendship and inheritance</item>

        <item>Chapter 20: Polymorphism</item>

        <item>Chapter 21: Type conversions</item>

        <item>Chapter 22: Exceptions</item>

        <item>Chapter 23: Preprocessor directives</item>

        <item>Chapter 24: Input/output with files</item>

        </string-array>

    </resources>

      - Như vậy bạn đã biết cách tao 1 tập tin XML và biết cách tạo String Array cũng như tạo các phần tử nằm bên trong nó, Bây giờ trong Coding ta sẽ dựa vào myarray để đọc toàn bộ dữ liệu từ XML ra. Bạn cũng chú ý là myarray khi bạn tạo ra ở trên thì nó cũng được tạo ra trong gen.

 Dựa vào đây để lấy ra: R.array.myarray.

* Mở MainActivity.java:

public class MainActivity extends Activity

{

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        String arr[]=getResources().getStringArray(R.array.myarray);

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

        ArrayAdapter<String> mainAdapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arr);

        lv.setAdapter(mainAdapter);

    }

}

     - Giống như trường hợp số 1, dó đó trong trường hợp này ta chỉ viết dòng lệnh đọc dữ liệu từ XML đổ về một Mảng (thay vì trường hợp 1 ta hardcode mấy phần tử khi khai báo mảng), còn các phần khác bạn tự làm giống trường hợp 1:

final String arr[]=getResources().getStringArray(R.array.cplusplus);

Tức là bạn thay thế dòng:

public String [] danhSach ={"Lập Trình", "Android", "Winfrom ","Software", "Tài Liệu","C++","C#"};

trong trường hợp 1 của MainActivity.java bằng dòng lệnh trên.


Trường hợp 3: Sử dụng ArrayList và ListView control

 -   Sử dụng ArrayList để lưu trữ dữ liệu và đổ lên ListView như thế nào, bạn xem giao diện của chương trình:

Mô tả:

   + Nhập dữ liệu và nhấn nút “Nhập” thì sẽ đưa vào ArrayList và hiển thị lên ListView.
   + Nhấn vào phần tử nào thì hiển thị vị trí và giá trị của phần tử đó lên TextView.
   + Nhấn thật lâu (long click ) vào phần tử nào đó trên ListView thì sẽ xóa phần tử đó.
* Tạo Android Project tên: Vidu_ListView_ArrayList,

  Xem Layout XML của ứng dụng (main.xml):

<RelativeLayout

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"

tools:context=".MainActivity">

<EditText

Android:id="@+id/txtTen"

Android:layout_width="wrap_content"

Android:layout_height="wrap_content"

Android:layout_alignParentTop="true"

Android:inputType="text"

Android:layout_toRightOf="@+id/textView1"

Android:ems="10"/>

<TextView

Android:id="@+id/textView1"

Android:layout_width="wrap_content"

Android:layout_height="wrap_content"

Android:layout_alignBaseline="@+id/txtTen"

Android:layout_alignBottom="@+id/txtTen"

Android:layout_alignParentLeft="true"

Android:background="#deb887"

Android:text="Nhập tên:"/>

<Button

Android:id="@+id/btnNhap"

Android:layout_width="wrap_content"

Android:layout_height="wrap_content"

Android:layout_alignRight="@+id/txtTen"

Android:layout_below="@+id/txtTen"

Android:layout_toRightOf="@+id/textView1"

Android:textAlignment="center"

Android:text="Nhập"/>

<TextView

Android:id="@+id/txtselection"

Android:layout_width="match_parent"

Android:layout_height="wrap_content"

Android:layout_alignParentLeft="true"

Android:layout_below="@+id/btnNhap"

Android:background="#007380"/>

<ListView

Android:id="@+id/lvperson"

Android:layout_width="match_parent"

Android:layout_height="wrap_content"

Android:layout_alignParentLeft="true"

Android:layout_below="@+id/txtselection"

Android:background="#cccccc">

</ListView>

</RelativeLayout>

Xem MainActivity.java:

public class MainActivity extends Activity

{EditText txtten;

TextView txtchon;

Button btn;

ListView lv;

ArrayList<String>arrList=null;

ArrayAdapter<String> adapter=null;

                    @Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

          txtten=(EditText) findViewById(R.id.txtTen);

           txtchon=(TextView) findViewById(R.id.txtselection);

          lv=(ListView) findViewById(R.id.lvperson);

//1. Tạo ArrayList object

          arrList=new ArrayList<String>();

//2. Gán Data Source (ArrayList object) vào ArrayAdapter

adapter=new ArrayAdapter<String>(this, Android.R.layout.simple_list_item_1,

arrList);

//3. gán Adapter vào ListView

          lv.setAdapter(adapter);

           btn=(Button) findViewById(R.id.btnNhap);

//4. Xử lý sự kiện nhấn nút Nhập

        btn.setOnClickListener(new View.OnClickListener() {

public void onClick(View arg0) {

           arrList.add(txtten.getText()+"");

           adapter.notifyDataSetChanged();

           }

});

//5. Xử lý sự kiện chọn một phần tử trong ListView

           lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

 public void onItemClick( AdapterView<?> arg0,View arg1,int arg2,long arg3) {

            txtchon.setText("vị trí : "+ arg2+ "; giá trị ="+arrList.get(arg2));

          }

});

//6. xử lý sự kiện Long click

           lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

@Override

public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

                   arrList.remove(arg2);//xóa phần tử thứ arg2

                   adapter.notifyDataSetChanged();

                   return false;

              }

          });

}

}

Giải thích coding:

   ArrayList bạn đã được học trong môn Java 1 rồi. Ở đây hàm adapter.notifyDataSetChanged(); Bạn chú ý là ArrayList được gán vào adapter nên mọi sự thay đổi trong ArrayList thì adapter đều nhận biết được. Khi có sự thay đổi trong ArrayList bạn chỉ cần gọi notifyDataSetChanged thì ListView sẽ được cập nhật (bởi vì Adapter được gắn vào ListView).

  - Sự kiện setOnItemLongClickListener, được gắn cho ListView Item, khi nhấn lâu từ 2.5 tới 3 giây thì sự kiện này sẽ sảy ra. Tương tự như setOnItemClickListener, đối số có tên arg2 được dùng để xác định được vị trí của phần tử nằm trong ArrayList.

lv31 (1)


Trường hợp 4 : Sử dụng ListView nhưng dưới dạng ListActivity

 - Thay vì kế thừa từ Activity, ta sẽ cho kế thừa từ ListActivity.

- Và dĩ nhiên cách đặt Id cho ListView cũng có sự khác biệt.

- Bạn xem giao diện bên dưới:

- Xem cách làm XML layout (activity_main.xml):

- Bạn nhìn vào dòng lệnh: Android:id="@Android:id/list", bạn phải viết giống như thế này. Bởi vì nó là id được định nghĩa sẵn bên trong Android.

- Tiếp tục nhìn vào dòng lệnh:Android:id="@Android:id/empty", cũng là có sẵn của Android. Nó có tác dụng tự động thông báo khi ListView của bạn không có bất kỳ một phần tử nào cả.

- Xem class MainActivity.java:

public class MainActivity extends ListActivity {

TextView selection;

String arr[]={"Intel","SamSung","Nokia","Simen","AMD",
"KIC","ECD"};
ArrayAdapter<String >adapter=null;

@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Thiết lập Data Source cho Adapter

 adapter=newArrayAdapter<String>(this,Android.R.layout.simple_list_item_1,arr);
//Gán Adapter vào ListView

//Nhớ là phải đặt id cho ListView theo đúng quy tắc

  setListAdapter(adapter);
  selection=(TextView) findViewById(R.id.selection);

}
@Override
protected void onListItemClick(ListView l, View v,

intposition, longid) {

// TODO Auto-generated method stub

     super.onListItemClick(l, v, position, id);

        String txt="vị trí = "+position +"; giá trị

         ="+arr[position];

       selection.setText(txt);
 }
}

 

 lv31 (2)

- Bạn nhìn vào dòng lệnh số 1: bạn thấy đấy, ta cho kế thừa từ ListActivity chứ không phải Activity. (Android đã viết class ListActivity kế thừa từ Activity rồi). Tức là ListActivity cũng chính là Activity.

- Bạn nhìn vào dòng lệnh số 21: setListAdapter(adapter);

     Ở đây ta hoàn toàn không đưa control ListView ra. Mà ta chỉ cần gọi hàm setListAdapter thì ListView cũng tự động cập nhập dữ liệu. Bạn phải làm chính xác 2 nơi thì mới được như vậy:

  1. Kết thừa từ ListActivity,
  2. Đặt id cho ListView theo đúng quy tắc Android:id="@Android:id/list"