Home  >  Article  >  php教程  >  Listview and adapter usage

Listview and adapter usage

高洛峰
高洛峰Original
2016-12-13 16:21:561306browse

A ListView usually has two responsibilities.

(1) Populate data into the layout.

(2) Process the user’s selection and click operations.

The first point is easy to understand, ListView implements this function. The second point is not difficult to do. Readers will find that it is very simple in the following studies.

The creation of a ListView requires 3 elements.

(1) View for each column in ListView.

(2) Fill in the data or pictures of the View, etc.

(3) Adapter to connect data to ListView.

In other words, to use ListView, you must first understand what an adapter is. The adapter is a bridge connecting data and AdapterView (ListView is a typical AdapterView, and we will learn about others later). It can effectively realize the separation setting of data and AdapterView, making the binding of AdapterView and data easier and making modifications easier. Convenience

Android provides many Adapters. Table 4-5 lists some commonly used ones.

Table 4-5 Commonly used adapters

Adapter

Meaning

ArrayAdapter

Used to bind a Array, supports generic operations

SimpleAdapter

Used to bind the data corresponding to the control defined in xml

SimpleCursorAdapter

Used to bind the data obtained from the cursor

BaseAdapter

Universal basic adapter

In fact, there are many adapters. It should be noted that various Adapters only have different conversion methods and capabilities. Next, we will use different Adapters to bind data to ListView (SimpleCursorAdapter will not be discussed for now, but will be introduced later when we talk about SQLite).

4.12.1 ListView uses ArrayAdapter

ArrayAdapter can be used to implement simple ListView data binding. By default, ArrayAdapter binds the toString value of each object to the predefined TextView control in the layout. The use of ArrayAdapter is very simple.

Example:

Project directory: EX_04_12

Add a ListView control to the layout file.

http://schemas.android.com/apk/res/android" android:layout_width="fill_parent "
android:layout_height="fill_parent" >

Then initialize it in Activity.

publicclass MyListView extends Activity {

privatestaticfinal String[] strs = new String[] {
"first", "second", "third", "fourth", "fifth"
};//Define a String array to use To display the contents of ListView private ListView lv;/**Called when the activity is first created.*/
@Override
publicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.main);

lv = ( ListView) findViewById(R.id.lv);//Get a reference to the ListView object/*Set Adapter for ListView to bind data*/
lv.setAdapter(new ArrayAdapter(this,
                                                                                                                                android.R.layout. simple_list_item_1, strs));

}
}

Listview and adapter usage

▲ Figure 4-29 ListView using ArrayAdapter running effect

The code is very simple, and the running effect is shown in Figure 4-29.

Analyze the steps to use.

(1) Define an array to store the contents of the items in the ListView.

(2) Create an ArrayAdapter object by implementing the constructor of ArrayAdapter.

(3) Bind the ArrayAdapter through the setAdapter() method of ListView.

What needs to be mentioned in the second step is that ArrayAdapter has multiple constructors, and the one implemented in the example is the most commonly used one. The first parameter is the context, and the second parameter is a layout resource ID containing a TextView used to fill each row of the ListView. The third parameter is the content of ListView. The second parameter can customize a layout, but this layout must have a TextView control. Usually we use the resources provided by Android. In addition to the ones used in the examples, the following are commonly used to implement ListView with RadioButton and CheckBox.

(1) Implement ListView with selection box by specifying the resource android.R.layout.simple_list_item_checked. You need to use the setChoiceMode() method to set whether the selection is multiple selection or single selection, otherwise the selection effect will not be achieved. The operation effect is shown in Figure 4-30.

The implementation code is as follows:

lv.setAdapter(new ArrayAdapter(this,
                      android.R.layout.simple_list_item_checked, strs));
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

(2) Passed Specify the resource android.R.layout.simple_list_item_multiple_choice to implement the ListView with CheckBox. Similarly, you need to use the setChoiceMode() method to set single selection or multiple selection. The operation effect is shown in Figure 4-31. : Implementation code is as follows: 代lv.setadapter (New ArrayAdapter & LT; String & GT; (this,

Android.Rayout.simple_list_ITEM_CHOCHOICE, Strs); ETCHOICEMODE (ListView.choice_mode_multiple);

(3) Specify the resource android.R.layout.simple_list_item_single_choice to implement the ListView with RadioButton. What should be noted here is that radio selection is not specified here. Whether it is multiple selection or single selection must be specified through the setChoiceMode() method. The operation effect is shown in Figure 4-32.

The implementation code is as follows:

lv.setAdapter(newArrayAdapter(this,

android.R.layout.simple_list_item_single_choice,strs));

lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);




▲Figure 4-30 ListView with selection box 32 ListView with RadioButton

As mentioned earlier, the responsibilities of ListView are not only to fill in data, Also handle user actions. Through the following code, you can bind a click listener to the ListView. After clicking, the number of clicked rows will be displayed in the title bar.

lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2,                    long arg3) {                    //点击后在标题上显示点击了第几行                     setTitle("你点击了第"+arg2+"行");
            }
        });

4.12.2 ListView uses SimpleAdapter

Many times it is necessary to display something other than text in the list, such as pictures, etc. SimpleAdapter can be used at this time. The use of SimpleAdapter is also very simple, and its function is also very powerful. You can use it to customize the content of items in ListView, such as pictures, multi-select boxes, etc. Let's look at an example to implement a ListView with an ImageView and TextView for each row. Let’s take a look at the running effect first, as shown in Figure 4-34. 带选择框的ListView    带CheckBox的ListView         Listview and adapter usage

▲Figure 4-34 ListView with icon

First add a ListView control in the layout file.

You also need to define a layout for each row in the ListView, and use RelativeLayout to implement a layout with two lines of text and a picture.

item.xml:Listview and adapter usage

android:layout_height="fill_parent" android:layout_width="fill_parent">

android:layout_height="wrap_content" android:id="@+id /ItemImage" />

android:layout_width="fill_parent" android:textSize="20sp" />

android:layout_width="fill_parent" android:layout_below="@+id/ItemTitle" />

Once the configuration is complete, just You can bind data to ListView in Java code.

publicclass MyListViewSimple extends Activity {
private ListView lv; /**Called when the activity is first created.*/ @Override
publicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.main);

lv = (ListView) findViewById(R.id.lv);/*Define a dynamic array*/                   ArrayList> listItem = new ArrayList> listItem = new ArrayList for(int i=0;i                                                                                   ItemImage", R.drawable.icon);//Add pictures map.put("ItemTitle", "This is the "+i+" row");
      map.put("ItemText", "This is the "+i+" row");
listItem.add(map);
Data sources in the group The key corresponds to new String[] {"ItemImage"
,"ItemTitle", "ItemText"},
newint[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText in the View that defines the layout ; Click(AdapterView> arg0, View arg1, int arg2 ,                                                                                                  });
}
}


The data using simpleAdapter is generally A list composed of HashMap, each section of the list corresponds to each row of the ListView. Through the constructor of SimpleAdapter, the data of each key of the HashMap is mapped to the corresponding control in the layout file. This layout file is generally defined by yourself according to your own needs. Let’s sort out the steps for using SimpleAdapter.

(1) Define the layout implemented by each row of ListView as needed.

(2) Define a list composed of HashMap and store the data in it as key-value pairs.

(3) Construct SimpleAdapter object.

(4) Bind LsitView to SimpleAdapter.

4.12.3 Optimization of ListView using BaseAdapter and ListView

In the use of ListView, sometimes it is necessary to add buttons and other controls to achieve separate operations. In other words, this ListView no longer only displays data, nor is it just this row that handles user operations, but the controls inside need to gain the user's focus. Readers can try to use SimpleAdapter to add a button to the ListView's item. They will find that it can be added, but it cannot get focus, and the click operation is covered by the ListView's Item. The most convenient way at this time is to use the flexible adapter BaseAdapter.

▲ Figure 4-35 Methods in BaseAdapter

To use BaseAdapter, you must write a class to inherit it. At the same time, BaseAdapter is an abstract class, and if you inherit it, you must implement its methods. The flexibility of BaseAdapter lies in the fact that it has to rewrite many methods. Take a look at the methods. Figure 4-35 shows the methods implemented by SpeechListAdapter inherited from BaseAdapter. The most important one is the getView() method. What do these methods do? We provide readers with answers by analyzing the principles of ListView.

当系统开始绘制ListView的时候,首先调用getCount()方法。得到它的返回值,即ListView的长度。然后系统调用getView()方法,根据这个长度逐一绘制ListView的每一行。也就是说,如果让getCount()返回1,那么只显示一行。而getItem()和getItemId()则在需要处理和取得Adapter中的数据时调用。那么getView如何使用呢?如果有10000行数据,就绘制10000次?这肯定会极大的消耗资源,导致ListView滑动非常的慢,那应该怎么做呢?通过一个例子来讲解如何在使用BaseAdapter的时候优化ListView的显示。例子中将上一节中的ImageView换成Button,并且处理Button的点击事件,其中对ListView的显示做了优化。

 

布局文件和上一例类同,读者可以在光盘的工程目录中查看,这里只给出Activity类。

publicclass MyListViewBase extends Activity {    
    private ListView lv;    /*定义一个动态数组*/     ArrayList<HashMap<String, Object>>listItem;/** Called when the activity is first created. */ 
@Override
publicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

lv = (ListView) findViewById(R.id.lv);
        MyAdapter mAdapter = new MyAdapter(this);//得到一个MyAdapter对象 lv.setAdapter(mAdapter);//为ListView绑定Adapter /*为ListView添加点击事件*/ 
lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2,                    long arg3) {
        Log.v("MyListViewBase", "你点击了ListView条目" + arg2);//在LogCat中输出信息                 
            }
        });

    }/*添加一个得到数据的方法,方便使用*/ private ArrayList<HashMap<String, Object>> getDate(){
    
    ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,     Object>>();    /*为动态数组添加数据*/     for(int i=0;i<30;i++)  
         {  
             HashMap<String, Object> map = new HashMap<String, Object>();  
             map.put("ItemTitle", "第"+i+"行");  
             map.put("ItemText", "这是第"+i+"行");  
             listItem.add(map);  
         } 
        return listItem;
    
    }/*      * 新建一个类继承BaseAdapter,实现视图与数据的绑定     */ privateclass MyAdapter extends BaseAdapter {    private LayoutInflater mInflater;//得到一个LayoutInfalter对象用来导入布局  /*构造函数*/ 
public MyAdapter(Context context) {    this.mInflater = LayoutInflater.from(context);
        }

        @Override
        publicint getCount() {            
            return getDate().size();//返回数组的长度         }

        @Override        public Object getItem(int position) {
            returnnull;
        }

        @Override
        publiclong getItemId(int position) {            return 0;
        }        /*书中详细解释该方法*/         @Override        public View getView(finalint position, View convertView, ViewGroup parent) {
             ViewHolder holder;            //观察convertView随ListView滚动情况              
Log.v("MyListViewBase", "getView " + position + " " + convertView);            if (convertView == null) {
                     convertView = mInflater.inflate(R.layout.item,    null);
                     holder = new ViewHolder();                    /*得到各个控件的对象*/                    
 holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
                    holder.text = (TextView) convertView.findViewById(R.id.ItemText);
                    holder.bt = (Button) convertView.findViewById(R.id.ItemButton);
                    convertView.setTag(holder);//绑定ViewHolder对象                    }    else{
                    holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象                   }            /*设置TextView显示的内容,即我们存放在动态数组中的数据*/             
holder.title.setText(getDate().get(position).get("ItemTitle").toString());
            holder.text.setText(getDate().get(position).get("ItemText").toString());            
            /*为Button添加点击事件*/              holder.bt.setOnClickListener(new OnClickListener() {
                
                @Override
                publicvoid onClick(View v) {
                Log.v("MyListViewBase", "你点击了按钮" + position);                                //打印Button的点击信息                     
                }
            });            
            return convertView;
        }
    
    }/*存放控件*/ publicfinalclass ViewHolder{    public TextView title;    public TextView text;    public Button   bt;
    }
}

 运行效果如图4-36所示。还需要注意的是,Button会抢夺ListView的焦点,需要将Button设置为没有焦点。设置非常简单,只需要在xml的Button标签下加入一行:android:focusable=“false”代码就可以了。在LogCat观察点击后输出的信息,如图4-37所示。

Listview and adapter usage

▲图4-36 Listview and adapter usage

Listview and adapter usage

 ▲图4-37 Listview and adapter usage

代码中getView()方法不容易理解。其实完全可以不用所谓的convertView和ViewHolder,直接导入布局并且设置控件显示的内容就可以了。但是这意味着有多少行数据就需要绘制多少行ListView,这显然是不可取的。这里采用了一种优化的方法。代码中,在getView()方法中加入了一行log输出convertView的内容。滚动ListView,输出信息如图4-38所示。

从图4-38中可以看出,当启动Activity呈现第一屏ListView的时候,convertView为零。当用户向下滚动ListView时,上面的条目变为不可见,下面出现新的条目。这时候convertView不再为空,而是创建了一系列的convertView的值。当又往下滚一屏的时候,发现第11行的容器用来容纳第22行,第12行的容器用来容纳第23行。也就是说convertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。

还可以继续优化。虽然重复利用了已经绘制的view,但是要得到其中的控件,需要在控件的容器中通过findViewById的方法来获得。如果这个容器非常复杂,这显然会增加系统资源的开销。在上面的例子中,引入了Tag的概念。或许不是最好的办法,但是它确实能使ListView变得更流畅。代码中,当convertView为空时,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象。当convertView不为空,重复利用已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对控件的层层查询,而是快速定位到控件。

Listview and adapter usage

▲图4-38 Listview and adapter usage

总结一下,这节介绍了用BaseAdapter来绑定ListView的数据。因为BaseAdapter非常灵活,使用也相对较其他控件麻烦。同时ListView的优化问题也值得读者去研究,一个流畅的ListView会带来更好的用户体验。


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn