![]() |
It is possible to listen for click and long click events on the items inside an adapter view. As an example, let's add a click event listener to the GridView.
Create a new instance of an anonymous class that implements the AdapterView.OnItemClickListener interface and pass it to the setOnItemClickListener() method of the GridView object. Android Studio automatically generates a stub for the onItemClick()) method of the interface. You'll notice that the method's parameters include an integer specifying the position of the list item. You can use this integer to find out which item in the data set the user clicked.
The following code illustrates how to display a simple message as a snackbar every time an item in the GridView is clicked.
- cheeseGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView,
- View view, int position, long rowId) {
- // Generate a message based on the position
- String message = "You clicked on " + cheeses[position];
- // Use the message to create a Snackbar
- Snackbar.make(adapterView, message, Snackbar.LENGTH_LONG)
- .show(); // Show the Snackbar
- }
- });
![]() |
An ArrayAdapter can handle only one TextView widget inside the layout of the View objects it generates. To broaden its capabilities you must extend it. Before we do that, however, let's create a slightly more complex data set.
Instead of strings, let's say our data set contains objects of the following class:
- static class Cheese {
- String name;
- String description;
- public Cheese(String name, String description) {
- this.name = name;
- this.description = description;
- }
- }
- Cheese[] cheeses = {
- new Cheese("Parmesan", "Hard, granular cheese"),
- new Cheese("Ricotta", "Italian whey cheese"),
- new Cheese("Fontina", "Italian cow's milk cheese"),
- new Cheese("Mozzarella", "Southern Italian buffalo milk cheese"),
- new Cheese("Cheddar", "Firm, cow's milk cheese"),
- };
Create a new layout XML file and name it custom_item.xml. Add a Large text and a Small text widget to it. Set the id attribute of the first widget to cheese_name and that of the second one to cheese_description. The contents of the layout XML file should now look like this:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="@dimen/activity_horizontal_margin">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="Large Text"
- android:id="@+id/cheese_name" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="Small Text"
- android:id="@+id/cheese_description" />
- </LinearLayout>
- ArrayAdapter<Cheese> cheeseAdapter =
- new ArrayAdapter<Cheese>(this, 0, cheeses) {
- @Override
- public View getView(int position,
- View convertView,
- ViewGroup parent) {
- }
- };
- Cheese currentCheese = cheeses[position];
- // Inflate only once
- if(convertView == null) {
- convertView = getLayoutInflater()
- .inflate(R.layout.custom_item, null, false);
- }
- TextView cheeseName =
- (TextView)convertView.findViewById(R.id.cheese_name);
- TextView cheeseDescription =
- (TextView)convertView.findViewById(R.id.cheese_description);
- cheeseName.setText(currentCheese.name);
- cheeseDescription.setText(currentCheese.description);
- return convertView;
The getView() method is called repeatedly by the adapter view to populate itself. Therefore, you must try to minimize the number of operations you perform in it.
In the previous step, you might have noticed that, even though we made sure that the layout of the list items is inflated only once, the findViewById() method, which consumes many CPU cycles, is called every time the getView() method is called.
To avoid this and to improve the performance of the adapter view, we need to store the results of the findViewById( method inside the convertView object. To do so, we can use a view holder object, which is nothing more than an object of a class that can store the widgets present in the layout.
Because the layout has two TextView widgets, the view holder class must also have two TextView widgets. I have named the class ViewHolder.
- static class ViewHolder{
- TextView cheeseName;
- TextView cheeseDescription;
- }
- ViewHolder viewHolder = new ViewHolder();
- viewHolder.cheeseName =
- (TextView)convertView.findViewById(R.id.cheese_name);
- viewHolder.cheeseDescription =
- (TextView)convertView.findViewById(R.id.cheese_description);
- // Store results of findViewById
- convertView.setTag(viewHolder);
- TextView cheeseName =
- ((ViewHolder)convertView.getTag()).cheeseName;
- TextView cheeseDescription =
- ((ViewHolder)convertView.getTag()).cheeseDescription;
- cheeseName.setText(currentCheese.name);
- cheeseDescription.setText(currentCheese.description);
![]() |
In this tutorial, you learned how to create an adapter and use it to populate various adapter views. You also learned how to create your own custom adapter. Although we only focused on the ArrayAdapter, ListView, and GridView classes, you can use the same techniques for other adapters and adapter views the Android SDK offers.
The Android Support Library includes the RecyclerView class. It behaves much like an adapter view, but it isn't a subclass of the AdapterView class. You should consider using it if you want to create more complex lists, especially ones that use multiple layout files for their items.
Written by Ashraff Hathibelagal
If you found this post interesting, follow and support us.
Suggest for you:
Android: From Beginner to Paid Professional
The Complete Android Developer Course - Build 14 Apps
Python For Android Hacking Crash Course: Trojan Perspective
No comments:
Post a Comment