TUT ANDROID 015: ANDROID CUSTOM LISTVIEW TUTORIAL (PART 2)

Trong ví dụ này mình sẽ giới thiệu một cách khác để tạo custom listview  đó là sử dụng ViewHolder. Đây là cách viết custom listview có độ custom rất cao và tối ưu về mặt hiệu năng. Ngoài ra mình cũng giới thiệu với các bạn cách bắt sự kiện vào các thành phần con của layout item khác với sự kiện onItemClick của listview cũng như việc custom backgroud sử dụng file xml

Để làm ví dụ này các bạn các bạn cần down load một số ảnh mình sử dụng trong bài theo link sau

drawable

Bước 1: Mở file res-> values ->strings.xml

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

<resources>

<string name="app_name">ListViewCustomTutorial</string>
 <string name="action_settings">Settings</string>
 <string name="hello_world">Hello world!</string>
 <string name="name">Name</string>
 <string name="address">Address</string>
 <string name="imageIcon">Icon Image </string>
 <string name="imageInfo">Information Image </string>
 <string name="imageNext">Next Image </string>

</resources>

Bước 2: Mở file res-> layout ->activity_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" >

<ListView
 android:id="@+id/lvSt"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent" />

</RelativeLayout>

Bước 3: tạo folder drawable sau đó tạo file background.xml

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

<shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="rectangle" >

<corners android:radius="2dp" />

<padding
 android:bottom="2dp"
 android:left="2dp"
 android:right="2dp"
 android:top="2dp" />

<gradient
 android:angle="90"
 android:endColor="#7388C1"
 android:startColor="#BFCAE6" />

</shape>

Bước 4: tạo file res->drawable-> bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:drawable="@drawable/background" android:state_pressed="true"></item>
 <item android:drawable="@drawable/back_groud_po" android:state_pressed="false"></item>

</selector>

Bước 5: tạo file res-> layout ->layoutitem.xml (đây là file giao diện của 1 item listview)

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="@android:color/white"
 android:paddingBottom="2dp"
 android:paddingLeft="3dp"
 android:paddingRight="3dp"
 android:paddingTop="2dp" >

<LinearLayout
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="@drawable/bg"
 android:orientation="horizontal"
 android:paddingBottom="2dp"
 android:paddingLeft="3dp"
 android:paddingRight="3dp"
 android:paddingTop="2dp"
 android:weightSum="10" >

<ImageView
 android:id="@+id/ivIcon"
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_weight="1.5"
 android:contentDescription="@string/imageIcon"
 android:src="@drawable/ic_launcher" />

<LinearLayout
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_marginLeft="2dp"
 android:layout_weight="6"
 android:orientation="vertical" >

<TextView
 android:id="@+id/tvName"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/name" />

<TextView
 android:id="@+id/tvAddress"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/address" />
 </LinearLayout>

<LinearLayout
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_marginLeft="5dp"
 android:layout_weight="2.5"
 android:orientation="horizontal" >

<ImageView
 android:id="@+id/ivInfo"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="2dp"
 android:contentDescription="@string/imageInfo"
 android:src="@drawable/get_info" />

<ImageView
 android:id="@+id/ivNext"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:contentDescription="@string/imageNext"
 android:src="@drawable/right_grey" />
 </LinearLayout>
 </LinearLayout>

</RelativeLayout>

Bước 6: tạo file res->menu-> context_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

<item
 android:id="@+id/view"
 android:title="View"/>
 <item
 android:id="@+id/edit"
 android:title="Edit"/>
 <item
 android:id="@+id/delete"
 android:title="Delte"/>

</menu>

Note: trong ví dụ này mình bắt đầu tạo các packet và các class riêng trong các packet để cho thuận tiện việc quản lý src code các bạn cũng nên tập làm quen với việc này

Nếu các bạn gặp khó khăn trong việc tạo packet và folder thì các bạn có thể tham khảo qua theo link dưới đây:

http://blankapham.com/thu-thuat-trong-android-va-eclipse/

Bước 7: tạo packet TruongBS.fet.hut.Util sau đó tạo class MyLog.java

package TruongBS.fet.hut.Util;

import android.util.Log;

public class MyLog {
 public static final boolean writeLog = true;

public static void LogD(String Tag, String Mess) {
 if (writeLog) {
 Log.d(Tag, Mess);
 }
 }

public static void LogE(String Tag, String Mess) {
 if (writeLog) {
 Log.e(Tag, Mess);
 }
 }

public static void LogI(String Tag, String Mess) {
 if (writeLog) {
 Log.i(Tag, Mess);
 }
 }

public static void LogW(String Tag, String Mess) {
 if (writeLog) {
 Log.w(Tag, Mess);
 }
 }

}

Bước 8: packet TruongBS.fet.hut.Data sau đó tạo class  StudentData.java

package TruongBS.fet.hut.Data;

public class StudentData {
 public int stt;
 public String Name;
 public String Address;

 public StudentData() {
 super();
 }

public StudentData(int icon, String name, String address) {
 super();
 this.stt = icon;
 Name = name;
 Address = address;
 }
 @Override
 public String toString() {
 return "StudentData [stt=" + stt + ", Name=" + Name + ", Address="
 + Address + "]";
 }

public int getStt() {
 return stt;
 }

public void setStt(int stt) {
 this.stt = stt;
 }

public String getName() {
 return Name;
 }

public void setName(String name) {
 Name = name;
 }

public String getAddress() {
 return Address;
 }

public void setAddress(String address) {
 Address = address;
 }

}

Bước 9: tạo packet TruongBS.fet.hut.Adapter sau đó tạo class  StudentListAdapter.java

package TruongBS.fet.hut.Adapter;

import java.util.ArrayList;

import TruongBS.fet.hut.Data.StudentData;
import TruongBS.fet.hut.Util.MyLog;
import TruongBS.fet.hut.listviewcustomtutorial.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class StudentListAdapter extends BaseAdapter {

private Context mContext;
 private ArrayList<StudentData> arr;

public StudentListAdapter(Context mContext, ArrayList<StudentData> arr) {
 super();
 this.mContext = mContext;
 this.arr = arr;

}

@Override
 public int getCount() {
 // TODO Auto-generated method stub
 int rtValue = 0;
 if (arr != null) {
 rtValue = arr.size();
 }
 return rtValue;
 }

@Override
 public Object getItem(int arg0) {
 // TODO Auto-generated method stub
 return arr.get(arg0);
 }

@Override
 public long getItemId(int arg0) {
 // TODO Auto-generated method stub
 return arg0;
 }

@Override
 public View getView(int pos, View convertView, ViewGroup parent) {
 // TODO Auto-generated method stub
 ViewHolder holder;
 // init View
 // neu convertView null ban khoi tao convertView
 // nguoc lai ban co the tai su dung convertView chi can update noi dung
 // ma k can phai cap phat them 1 hang moi
 if (convertView == null) {

 // set layout cho convertView
 LayoutInflater mInflater = LayoutInflater.from(mContext);
 convertView = mInflater.inflate(R.layout.layoutitem, parent, false);

 // init va setup ViewHolder
 holder = new ViewHolder();
 holder.ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
 holder.ivInfo = (ImageView) convertView.findViewById(R.id.ivInfo);
 holder.ivNext = (ImageView) convertView.findViewById(R.id.ivNext);
 holder.tvAddress = (TextView) convertView
 .findViewById(R.id.tvAddress);
 holder.tvName = (TextView) convertView.findViewById(R.id.tvName);

 // set holder cho view
 convertView.setTag(holder);
 } else {
 // khi convertView not null chung ta k can phai findViewById
 // khi su dung viewHolder
 holder = (ViewHolder) convertView.getTag();
 }

// lay data insert vao view
 final StudentData data = arr.get(pos);
 if (data != null) {
 holder.tvAddress.setText(data.getAddress());
 holder.tvName.setText(data.getName());
 // holder.ivIcon.setImageBitmap(bm)
 }

// lang nghe su kien icon info click

holder.ivInfo.setOnClickListener(new OnClickListener() {

@Override
 public void onClick(View arg0) {
 // TODO Auto-generated method stub
 // trong vi du nay de don gian minh chi log data ra logcat
 // trong truong hop thuc te cac ban co the xu ly tuy theo yeu cau cua app
 MyLog.LogD("debug", "Name: " + data.getName() + " Address "
 + data.getAddress());

}
 });

return convertView;
 }

// xay dung lop noi ViewHolder
 public class ViewHolder {
 // cac thuoc tinh cua ViewHolder thuong tuong duong voi cac View trong layoutitem
 ImageView ivIcon, ivNext, ivInfo;
 TextView tvName, tvAddress;

}

}

Bước 10: mở file MainActivity

package TruongBS.fet.hut.listviewcustomtutorial;

import java.util.ArrayList;

import TruongBS.fet.hut.Adapter.StudentListAdapter;
import TruongBS.fet.hut.Data.StudentData;
import TruongBS.fet.hut.Util.MyLog;
import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
 public static final String TAG = "MainActivity";

private ListView lvSt;
 private ArrayList<StudentData> arrStudent;
 private StudentListAdapter adapter;
 private int posSt = -1;

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 lvSt = (ListView) findViewById(R.id.lvSt);

// lay data vao mang
 arrStudent = new ArrayList<StudentData>();

LoadData();

// Khoi tao Adater

adapter = new StudentListAdapter(MainActivity.this, arrStudent);

// setAdater cho ListView
 lvSt.setAdapter(adapter);

// bat su kien tuong tac voi listview

// dang ky tao context menu khi long click vao item cua lv
 registerForContextMenu(lvSt);

// lang nghe su kien khi nguoi dung click vao item
 lvSt.setOnItemClickListener(new OnItemClickListener() {

@Override
 public void onItemClick(AdapterView<?> par, View v, int pos, long id) {
 // TODO Auto-generated method stub
 Toast.makeText(
 MainActivity.this,
 arrStudent.get(pos).getName() + " "
 + arrStudent.get(pos).getAddress(),
 Toast.LENGTH_LONG).show();

}
 });

// lang nghe su kien long click vao item list view
 // luu lai vi tri long click de xu ly data voi con context menu
 lvSt.setOnItemLongClickListener(new OnItemLongClickListener() {

@Override
 public boolean onItemLongClick(AdapterView<?> parent, View v,
 int pos, long id) {
 // Luu lai vi tri Long Click de xu ly
 posSt = pos;
 return false;
 }
 });

}

@Override
 public void onCreateContextMenu(ContextMenu menu, View v,
 ContextMenuInfo menuInfo) {
 // TODO Auto-generated method stub

menu.setHeaderIcon(R.drawable.ic_launcher);
 menu.setHeaderTitle("Edit Item");

super.onCreateContextMenu(menu, v, menuInfo);
 MenuInflater inflater = getMenuInflater();
 inflater.inflate(R.menu.context_menu, menu);

}

// xu ly su kien khi nguoi dung tuong tac voi context menu
 @Override
 public boolean onContextItemSelected(MenuItem item) {
 // TODO Auto-generated method stub
 switch (item.getItemId()) {
 case R.id.delete:
 MyLog.LogD(TAG, "delete");
 // xoa phan tu vua chon
 // remove phan tu ra khoi mang
 arrStudent.remove(posSt);
 // update lai listview
 adapter.notifyDataSetChanged();
 break;
 case R.id.edit:
 MyLog.LogD(TAG, "edit");
 // edit lai gia tri cua item listview
 StudentData stEdit = new StudentData(100, "Edit Name",
 "Hai Duong Viet nam");
 arrStudent.set(posSt, stEdit);
 // update lai listview
 adapter.notifyDataSetChanged();
 break;
 case R.id.view:
 MyLog.LogD(TAG, "view");
 break;

default:
 break;
 }
 return super.onContextItemSelected(item);
 }

private void LoadData() {
 StudentData st1 = new StudentData(1, "Truong1", "HN VN");
 arrStudent.add(st1);

StudentData st2 = new StudentData(2, "Truong2", "HN VN");
 arrStudent.add(st2);

StudentData st3 = new StudentData(3, "Truong3", "HN VN");
 arrStudent.add(st3);

StudentData st4 = new StudentData(4, "Truong4", "HN VN");
 arrStudent.add(st4);

StudentData st5 = new StudentData(5, "Truong5", "HN VN");
 arrStudent.add(st5);

StudentData st6 = new StudentData(6, "Truong6", "HN VN");
 arrStudent.add(st6);

StudentData st7 = new StudentData(7, "Truong7", "HN VN");
 arrStudent.add(st7);

StudentData st8 = new StudentData(8, "Truong8", "HN VN");
 arrStudent.add(st8);

StudentData st9 = new StudentData(9, "Truong9", "HN VN");
 arrStudent.add(st9);

StudentData st10 = new StudentData(10, "Truong10", "HN VN");
 arrStudent.add(st10);

StudentData st11 = new StudentData(11, "Truong11", "HN VN");
 arrStudent.add(st11);

StudentData st12 = new StudentData(12, "Truong12", "HN VN");
 arrStudent.add(st12);

StudentData st13 = new StudentData(13, "Truong13", "HN VN");
 arrStudent.add(st13);

}

}

Note:Các bạn có thể theo dõi kết quả thực hiện chương trình trên logcat và màn hình. Các bạn có thể down full src theo link dưới đây

ListViewCustomTutorial

Kết quả thực hiện chương trình

khi click vào item ListView

1

Khi LongClick vào item ListView

2

khi click vào icon info (chữ i màu xanh) mình show data ra logcat

3

Comments
  1. 5 năm ago
    • 5 năm ago
  2. 5 năm ago
  3. 5 năm ago
  4. 5 năm ago
  5. 4 năm ago

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *