안드로이드 - 커스텀 리스트뷰 안드로이드 이야기2012. 8. 11. 11:43
안드로이드 - 커스텀 리스트뷰
Custom List Views with icons and Listeners in Android
Customizing List Views in Android is very useful for most applications, but, there aren't many good tutorials on the web which explains how to properly customize list views (especially cases where there are Listeners with every element of ListView). So, I decided to write one.
Here's a screenshot of the what the output would look like:
Each List Item would have:
- Name, a phone and email icon.
- - Clicking on phone icon initiates a call.
- - Clicking on email icon opens mail client
Please note that my emphasis is on the functionality and not on the aesthetics =).
This tutorial is divided into the following parts:
- Designing the Layout
- Developing the Custom Adapter
- Developing the Activity
Designing the Layout
I create 2 layout XML Files.
- main.xml - For the main activity
- address_book_list_item.xml - Represents each List Items on the List View
Here's the main.xml:
1
2
3
4
5
6
7
8 |
< TEXTVIEW android:text = "@string/address_book_label" android:id = "@+id/address_book_label" ></ TEXTVIEW >
< LISTVIEW android:id = "@+id/address_book_listview" ></ LISTVIEW >
</ LINEARLAYOUT > |
As, can be seen, it has 2 elements only. A TextView for displaying the top label's text, and a ListView. I like to create separate styles instead of putting them inside the layout.xml file. Also, if you notice, I directly added ListView i.e. my activity won't extend ListActivity (as you will see later).
Here's the address_book_list_item.xml:
1
2
3
4
5
6
7
8
9
10
11
12 |
< TEXTVIEW android:text = "Name" android:id = "@+id/address_book_item_name" android:layout_alignParentLeft = "true" android:layout_alignParentTop = "true" ></ TEXTVIEW >
< IMAGEVIEW android:id = "@+id/address_book_item_email" android:layout_alignParentTop = "true" android:layout_alignParentRight = "true" android:contentDescription = "Email" android:src = "@drawable/ic_list_email" ></ IMAGEVIEW >
< IMAGEVIEW android:text = "Phone Call" android:id = "@+id/address_book_item_call" android:layout_alignParentTop = "true" android:src = "@drawable/ic_list_call" android:layout_toLeftOf = "@id/address_book_item_email" ></ IMAGEVIEW >
</ RELATIVELAYOUT > |
A Straight-forward layout with the name and icons on the right. I use RelativeLayout, as its much faster than LinearLayout as per Google's Guideline. If you are new to RelativeLayout, please check out here
Part 2: Developing the Custom Adapter
To have a custom List View, we need to create our own Adapter and override the getView method. If you don't know much about this, please check out this excellent Google I/O video. For this task, I extended my Custom Adapter from SimpleAdapter.
The data in a SimpleAdapter is an ArrayList of HashMap. The constructor of the SimpleAdapter looks like:
1
2 |
SimpleAdapter(Context context, List data, int resource, String[] from, int [] to) |
I call my Adapter as SimpleAddressBookAdapter and it's constructor has the same parameters as that of SimpleAdapter. Here's the constructor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
public SimpleAddressBookAdapter(Context context,
List data, int resource, String[] from, int [] to) {
super (context, data, resource, from, to);
// save the ArrayList and context for later usage
listMap = data;
context = context;
resource = resource;
resourceList = to;
fromList = from;
} |
In addition to calling the super class, I store all the parameters passed into an instance variable for later usage (they will be needed on getView).
According to Google's Guideline, having a static inner class for the views greatly improves performance. So, I declare a static inner class ViewHolder inside SimpleAddressBookAdapter as follows:
1
2
3
4
5
6
7
8 |
private static class ViewHolder {
TextView[] textView;
ImageView phoneIcon;
ImageView emailIcon;
int position; } |
The attributes are self-explanatory. The textView is used to map the TextView content's inside List View Item (I could have avoided using a textView array, but I used it if incase I decide to add a few textView's). Position stores the index of that List Item in the entire List View
Now here's the signature of getView:
1 |
public View getView( int position, View convertView, ViewGroup parent) |
Basically, this method will generate a View for a List Item on the ListView. Inside the getView method, I check if the convertView is null or not. If it's null, then I generate a view for that List Item, attach Listeners, and store it for later usage. The following code is used to store it:
1 |
convertView.setTag(holder); |
1 |
holder = (ViewHolder) convertView.getTag(); |
Here's the entire code of getView method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 |
public View getView( int position, View convertView, ViewGroup parent) {
// declare it final so that it could be accessed from the inner class methods
final ViewHolder holder;
if (convertView == null ) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resource, parent, false );
holder = new ViewHolder();
holder.textView = new TextView[fromList.length];
for ( int i = 0 ; i < fromList.length; i++) {
holder.textView[i] = (TextView) convertView.findViewById(resourceList[i]);
}
holder.phoneIcon = (ImageView) convertView.findViewById(R.id.address_book_item_call);
holder.emailIcon = (ImageView) convertView.findViewById(R.id.address_book_item_email);
// add a listener for phone call
holder.phoneIcon.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
String phone = SimpleAddressBookAdapter.listMap.get(holder.position).get( "phone" );
ActivityHelper.startActivity(ActivityManager.PHONE_CALL, phone);
}
});
// add listener for email
holder.emailIcon.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
String email = SimpleAddressBookAdapter.listMap.get(holder.position).get( "email" );
ActivityHelper.startActivity(ActivityManager.EMAIL, email);
}
});
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
for ( int i = 0 ; i < fromList.length; i++) {
holder.textView[i].setText(SimpleAddressBookAdapter.listMap.get(position).get(fromList[i]));
}
holder.position = position;
return convertView; } |
So, that takes care of creating a custom Adapter!
Part 3: Developing the Activity
Now, the final part consisting of developing an activity for displaying the ListView. In most examples, people usually extend ListActivity, however, I will extend Activity in my code. The reason for this is because sometimes I may need to create by own BaseActivity and I may have to create List's Activity by extend BaseActivity. I call my Activity as AddressBookActivity
Here's the onCreate method:
1
2
3
4
5
6
7
8
9
10 |
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main);
// update the current Activity
ActivityHelper.setActivity(this);
this.initAddressBookData();
this.initListView(); } |
I set the layout and initialize the data's. ActivityHelper is a helper class which keeps track of current Activity running in the Application, and it has some helper method like startActivity etc. initAddressBookData method puts some dummy values into the List. initListView initializes the List View.
Here's a peek at the initListView method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
public void initListView() {
/* get the list view from the layout */
ListView listView = (ListView) super.findViewById(R.id.address_book_listview);
/* create an adapter */
this .adapter = new SimpleAddressBookAdapter(
listView.getContext(),
this .addressList,
R.layout.address_book_list_item,
new String[] { "name" },
new int [] { R.id.address_book_item_name }
);
// set the list's adapter
listView.setAdapter( this .adapter); } |
I get the ListVIew from the XML Layout file, and i set it's adapter using listView.setAdapter.
That's about it!. Please download the zip files and go through the code.
Download from Github'안드로이드 이야기' 카테고리의 다른 글
안드로이드 - sd 카드 로딩 리스트 뷰 (0) | 2012.08.11 |
---|---|
안드로이드 - Custom Image Listview in Android (0) | 2012.08.11 |
안드로이드 - 한 줄에서 몇 줄로 되는 필요한 잡코드들 (0) | 2012.08.11 |
안드로이드 - ListActivity throws NullPointerException (0) | 2012.08.11 |
안드로이드 - [ java] 날짜 구하기 팁 (0) | 2012.08.11 |