Android Listview: Custom ListView and onClick Event on ListView
Android ListView:
Android ListView can definitely be called one of the most commonly used controls in Android, and almost all applications will use it. Since the screen space of mobile phones is relatively limited, there is not much content that can be displayed on the screen at one time. When there is a large amount of data to be displayed in the sequence, you can use Android Listview to achieve it. Android Listview allows users to Refers to the way of sliding up and down to scroll the data outside the screen to the screen, while the original data on the screen will scroll out of the screen. I believe you are actually using this control every day, such as viewing the mobile contact list, flipping through the latest news on Weibo, and so on. However, compared to the several controls introduced earlier, the usage of Android Listview is relatively more complicated, so we will use it separately Use one section to explain the Android Listview in great detail.
Simple usage of Android Listview:
First, create a new ListViewTest project, and let ADT automatically help us create a good activity. Then modify The code in activity_main.xml is as follows:
1 2 3 4 5 6 7 8 9 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView> </LinearLayout> |
Adding the Android Listview control to the layout is quite simple. First, specify an id for the ListView, and then set the width Both the height and the height are set to match_parent, so the Android Listview occupies the entire layout space. Next, modify the code in MainActivity as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MainActivity extends Activity { private String[] data = { "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ArrayAdapter<String> adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_1, data); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); } } |
Since Android Listview is used to display large amounts of data, we should provide the data first. These data can be downloaded from the Internet, or read from the database, should be decided according to the specific application scenario. Here we Simply use a data array to test, which contains the names of many fruits.
However, the data in the array cannot be directly passed to the Android Listview, we also need to use an adapter to complete. There are many adapter implementation classes in Android, and I think the best one is ArrayAdapter. It can pass Use generics to specify the data type to be adapted, and then pass in the data to be adapted in the constructor. ArrayAdapter There are multiple constructor overloads, and you should choose the most suitable one according to the actual situation. Because of the data we provided Both are strings, so specify the generic of ArrayAdapter as String, and then in the constructor of ArrayAdapter Pass in the current context, the id of the ListView subitem layout, and the data to be adapted in turn. Note that we used android.R.layout.simple_list_item_1 as the id of the layout of the ListView child items, this is an Android built-in cloth Bureau file, there is only one TextView, which can be used to simply display a paragraph of text. In this way, the adapter object is constructed. Finally, you need to call the setAdapter() method of Android Listview to pass in the built adapter object. The association between ListView and data is established. Now run the program, the effect is shown in Figure 1.
You can view the data off the screen by scrolling.
Customize the Android Listview interface:
The Android Listview that can only display a piece of text is too monotonous. Let’s do the ListView interface now. Customization, so that it can display richer content. First, you need to prepare a set of pictures, corresponding to each kind of fruit provided above, and we will let these fruit names later There is a pattern next to the scale. Then define an entity class as the adaptation type of the ListView adapter. Create a new class Fruit, the code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class Fruit { private String name; private int imageId; public Fruit(String name, int imageId) { this.name = name; this.imageId = imageId; } public String getName() { return name; } public int getImageId() { return imageId; } } |
There are only two fields in the Fruit class, the name represents the name of the fruit, and imageId represents the resource id of the image corresponding to the fruit. Then we need to specify a custom layout for the children of ListView, create a new one in the layout directory fruit_item.xml, the code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dip" /> </LinearLayout> |
There are only two fields in the Fruit class, the name represents the name of the fruit, and imageId represents the resource id of the image corresponding to the fruit. Then we need to specify a custom layout for the children of ListView, create a new one in the layout directory fruit_item.xml, the code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class FruitAdapter extends ArrayAdapter<Fruit> { private int resourceId; public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) { super(context, textViewResourceId, objects); resourceId = textViewResourceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view = LayoutInflater.from(getContext()).inflate(resourceId, null); ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } } |
FruitAdapter rewrites a set of constructors of the parent class used to layout the id and number of the context, ListView children It is passed in. In addition, the getView() method is rewritten. This method is used when each child item is scrolled to the screen Will be called. In the getView method, first get the Fruit instance of the current item through the getItem() method, and then use LayoutInflater to load the layout we passed in for this child, and then call the findViewById() method of View respectively Get the instances of ImageView and TextView, and call their setImageResource() and setText() methods respectively Method to set the displayed picture and text, and finally return the layout, so that our custom adapter is complete. Now modify the code in MainActivity as follows:
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 |
public class MainActivity extends Activity { private List<Fruit> fruitList = new ArrayList<Fruit>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();// Initialize fruit data FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); } private void initFruits() { Fruit apple = new Fruit("Apple", R.drawable.apple_pic); fruitList.add(apple); Fruit banana = new Fruit("Banana", R.drawable.banana_pic); fruitList.add(banana); Fruit orange = new Fruit("Orange", R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear = new Fruit("Pear", R.drawable.pear_pic); fruitList.add(pear); Fruit grape = new Fruit("Grape", R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango = new Fruit("Mango", R.drawable.mango_pic); fruitList.add(mango); } } |
As you can see, an initFruits() method is added here to initialize all fruit data. In the Fruit category, The name of the fruit and the corresponding image id are passed in in the constructor, and then the created object is added to the fruit list. Then we created a FruitAdapter object in the onCreate() method and passed the FruitAdapter as an adapter to ListView. This completes the task of customizing the Android Listview interface. Now re-run the program, the effect is shown in Figure 2.
Although our customized interface is still very simple at present, I believe that you have learned the trick, just modify With the content in fruit_item.xml, various complex interfaces can be customized.
Improve the efficiency of Android Listview:
The reason why the Android Listview control is difficult to use is that it has many details that can be optimized, among which the operating efficiency It’s a very important point. At present, the operating efficiency of our Android Listview is very low, because in the getView() of the FruitAdapter In the method, the layout is reloaded every time, which becomes a performance bottleneck when the Android Listview scrolls quickly. Observe carefully, there is also a convertView parameter in the getView() method, which is used to load the previously loaded The layout is cached so that it can be reused later. Modify the code in FruitAdapter as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class FruitAdapter extends ArrayAdapter<Fruit> { …… @Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, null); } else { view = convertView; } ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } } |
As you can see, now we have made a judgment in the getView() method. If the convertView is empty, use LayoutInflater to load the layout, if it is not empty, directly reuse the convertView. This greatly improves The operating efficiency of Android Listview can also show better performance when scrolling fast. However, currently, our code can still be optimized, although it will no longer be repeated to load the layout. But every time in the getView() method, the findViewById() method of View is still called to obtain an instance of the control. We can use a ViewHolder to optimize this part of the performance and modify the code in the FruitAdapter as follows Shown:
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 |
public class FruitAdapter extends ArrayAdapter<Fruit> { …… @Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, null); viewHolder = new ViewHolder(); viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image); viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name); view.setTag(viewHolder); //Store ViewHolder in View } else { view = convertView; viewHolder = (ViewHolder) view.getTag();// Get ViewHolder again } viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName()); return view; } class ViewHolder { ImageView fruitImage; TextView fruitName; } } |
We have added an internal class ViewHolder, which is used to cache control instances. When convertView is empty When, create a ViewHolder object, and store the control instances in the ViewHolder, and then call View The setTag() method stores the ViewHolder object in the View. Called when convertView is not empty The getTag() method of View takes out the ViewHolder again. In this way, all control instances are cached in ViewHolder Here, there is no need to get the control instance through the findViewById() method every time. After these two steps of optimization, the operating efficiency of our ListView is already very good.
 Click event of Android Listview:
Having said that, the scrolling of the ListView only satisfies our visual effect after all, but if the child cannot be clicked, this control has no practical use. Therefore, in this article, we will learn How can Android Listview responds to user click events.
Modify the code in MainActivity as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class MainActivity extends Activity { private List<Fruit> fruitList = new ArrayList<Fruit>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Fruit fruit = fruitList.get(position); Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show(); } }); } …… } |
As you can see, we used the setOnItemClickListener() method to register a listener for ListView, When the user clicks on any child item in the ListView, the onItemClick() method will be called back. In this method, you can Judge which sub-item the user clicked through the position parameter, and then get the corresponding fruit, and pass Toast Display the name of the fruit. Re-run the program and click on the watermelon, the effect is shown in Figure 3.
Related Article:
Android Intent
LinearLayout