Android学习----自定义Adapter实现ListView

 前言:

  对于ListView而言,自定义的Adapter对于显示复杂的界面有很大的灵活性 。使用自定义的Adapter需要继承BaseAdapter,然后重写getCount(),getView(),getItem,getItemId()4个方法。adapter在绘制listview时是先根据getCount()获得底层数据的个数来判断绘制item的个数,然后通过getView绘制单个item。

 

ListView实现的效果如下:

技术分享

 

详细步骤:

  1.新建Activity,在对应的布局文件中放置listview,textview和图片按钮;

  2.新建一个布局文件,布局文件中包含图片,两个textview,一个checkbox

  3.自定义MyAdapter继承BaseAdapter重写4个方法;

  4.给listview绑定适配器,给按钮添加点击事件。

 

具体实现:

布局文件:(item.xml)

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent" >
 4 
 5     <ImageView
 6         android:id="@+id/img"
 7         android:layout_width="wrap_content"
 8         android:layout_height="wrap_content"
 9         android:layout_alignParentLeft="true"
10         android:layout_alignParentTop="true" />
11 
12     <TextView
13         android:id="@+id/title"
14         android:layout_width="wrap_content"
15         android:layout_height="wrap_content"
16         android:layout_alignParentTop="true"
17         android:layout_toRightOf="@+id/img"
18         android:textSize="20sp"
19         android:text="" />
20 
21     <TextView
22         android:id="@+id/info"
23         android:layout_width="wrap_content"
24         android:layout_height="wrap_content"
25         android:layout_alignBottom="@+id/img"
26         android:layout_toRightOf="@+id/img"
27         android:textSize="12sp"
28         android:text="" />
29      <!--注意checkBox中focusable="false",如果不设置的话,listview的item点击事件没有用,因为item此时不能获取焦点-->
30     <CheckBox
31         android:id="@+id/cb"
32         android:layout_width="wrap_content"
33         android:layout_height="wrap_content"
34         android:layout_alignParentRight="true"
35         android:layout_alignParentTop="true"
36         android:focusable="false"
37         
38         android:text="" />
39 
40 </RelativeLayout>

layout_main.xml

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context=".MainActivity" >
10 
11     <TextView
12         android:id="@+id/title"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:layout_alignParentTop="true"
16         android:layout_centerHorizontal="true"
17         android:layout_toLeftOf="@id/title"
18         android:text="@string/title" />
19 
20     <ListView
21         android:id="@+id/listView1"
22         android:layout_width="match_parent"
23         android:layout_height="wrap_content"
24         android:layout_alignParentLeft="true"
25         android:layout_below="@+id/imageButton1" >
26     </ListView>
27 
28     <ImageButton
29         android:id="@+id/imageButton1"
30         android:layout_width="wrap_content"
31         android:layout_height="wrap_content"
32         android:layout_alignParentTop="true"
33         android:layout_alignRight="@+id/listView1"
34        android:visibility="invisible"
35         android:src="@drawable/delete" />
36 
37 </RelativeLayout>

 

java代码:

 

  1 public class MainActivity extends Activity {
  2     ListView listview;
  3     //list中存储listview的每一行的内容,每一行的内容存储在map中,根据键可以取出对应的值
  4     List<Map<String,Object>> list;
  5     ImageButton imgbtn;
  6     //positions中保存的是当前选中的所有元素
  7     List<Map<String,Object>> positions=new ArrayList<Map<String,Object>>();
  8     MyAdapter  adapter=null;
  9     @Override
 10     protected void onCreate(Bundle savedInstanceState) {
 11         super.onCreate(savedInstanceState);
 12         setContentView(R.layout.activity_main);
 13         listview=(ListView) findViewById(R.id.listView1);
 14         imgbtn=(ImageButton) findViewById(R.id.imageButton1);
 15         list=getData();
 16         adapter =new MyAdapter(this,list);
 17         listview.setAdapter(adapter);
 18         listview.setOnItemClickListener(cl);
 19         /*
 20          * 根据选中的内容,删除listview中的显示
 21          * positions中存放的是当前所有的选中项,每次删除完毕之后,应该把它清空,不然下次删除的时候
 22          * 它还有数据,此时会出现问题。
 23          * 删除完毕之后调用adapteradapter.notifyDataSetChanged(); 刷新view
 24          */
 25         
 26         imgbtn.setOnClickListener(new OnClickListener() {            
 27             @Override
 28             public void onClick(View v) {
 29                 Toast.makeText(getApplicationContext(), "delete", Toast.LENGTH_SHORT).show();
 30                 //list.remove(int location)不能在for循环中使用
 31                 for(int i=0;i<positions.size();i++){                   
 32                     list.remove(positions.get(i));
 33                 }
 34                 //每一次删除完之后,把当前positions的元素删除
 35                 Iterator<Map<String,Object>> iterator=positions.iterator();
 36                 while(iterator.hasNext()){
 37                     iterator.next();
 38                     iterator.remove();                    
 39                 }               
 40                 adapter.notifyDataSetChanged();   
 41                 //删除之后设置按钮不显示
 42                 imgbtn.setVisibility(View.INVISIBLE);
 43             }
 44         });
 45         
 46     }
 47  
 48     //点击时确定当前选中的checkBox
 49 
 50     @Override
 51     public boolean onCreateOptionsMenu(Menu menu) {
 52         // Inflate the menu; this adds items to the action bar if it is present.
 53         getMenuInflater().inflate(R.menu.main, menu);
 54         return true;
 55     }
 56     /*
 57      * 设置item的点击事件
 58      */
 59     OnItemClickListener cl=new OnItemClickListener() {
 60         @Override
 61         public void onItemClick(AdapterView<?> parent, View view, int position,
 62                 long id) {
 63             // TODO Auto-generated method stub
 64             Toast.makeText(getApplicationContext(), (String)list.get(position).get("title"), Toast.LENGTH_SHORT).show();
 65         }
 66     };
 67     
 68      /*
 69      * 提供音乐列表中的数据,包括每行数据中的歌手图片,歌曲名称,歌曲简介
 70      */
 71     public List<Map<String,Object>> getData(){
 72         List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
 73         Map<String,Object> map=new HashMap<String,Object>();
 74         map.put("title", "真的爱你");
 75         map.put("info", "无法可修饰的一对手,带出温暖永远在背后");
 76         map.put("img", R.drawable.huangjiaju);
 77         list.add(map);
 78         
 79         map=new HashMap<String,Object>();
 80         map.put("title", "一生有你");
 81         map.put("info", "多少人曾爱慕你年轻时的容颜");
 82         map.put("img", R.drawable.shuimunianhua);
 83         list.add(map);
 84         
 85         map=new HashMap<String,Object>();
 86         map.put("title", "Moves Like Jagger");
 87         map.put("info", "Just you shoot for the stars,If it feels right");
 88         map.put("img", R.drawable.maroon5);
 89         list.add(map);
 90         
 91         return list;
 92     }
 93     
 94     
 95     
 96     //创建一个ViewHolder类,每个类对象包含ListView的Item的所有控件元素
 97     private final class ViewHolder{
 98         public ImageView img;
 99         public TextView title;
100         public TextView info;
101         public CheckBox cb;
102     }
103     //自定义adapter继承自BaseAdapter,实现两个方法
104     /*
105      * 
106      */
107     class MyAdapter extends BaseAdapter{
108         private LayoutInflater inflater;
109         private List<Map<String,Object>> list;
110         
111         /*
112          * 三种方式获取XML布局文件
113          * 1.LayoutInflater inflater=LayoutInflater.from(context);
114          * 2.LayoutInflater inflater=getLayoutInflater();
115          * 3.LayoutInflater inflater=(LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
116          */
117         public MyAdapter(Context context,List<Map<String,Object>> list){
118             inflater=LayoutInflater.from(context);
119             this.list=list;
120         }
121         @Override
122         public int getCount() {
123             // TODO Auto-generated method stub
124             return list.size();
125         }
126         /*
127          * (non-Javadoc)
128          * holder里面放置每个item的所有控件
129          * 当convertview为空时,说明之前没有创建过这个Item,实例化一个新的view,通过setTag方法把holder放在convertView中
130          * 当convertview不为空时,此时可以直接从convertView取出,使用getTag
131          * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
132          */
133         @Override
134         public View getView(int position, View convertView, ViewGroup parent) {
135             // TODO Auto-generated method stub
136             ViewHolder holder=null;
137             if(convertView==null){
138                 holder=new ViewHolder();
139                 convertView=inflater.inflate(R.layout.item, null);
140                 holder.img=(ImageView) convertView.findViewById(R.id.img);
141                 holder.title=(TextView) convertView.findViewById(R.id.title);
142                 holder.info=(TextView) convertView.findViewById(R.id.info);
143                 holder.cb=(CheckBox) convertView.findViewById(R.id.cb);
144                 convertView.setTag(holder);
145             }else{
146                 holder=(ViewHolder) convertView.getTag();
147             }
148             holder.img.setBackgroundResource((Integer) list.get(position).get("img"));
149             holder.title.setText((CharSequence) list.get(position).get("title"));
150             holder.info.setText((CharSequence) list.get(position).get("info"));
151             holder.cb.setOnCheckedChangeListener(new checkedChangeListener(position));    
152             holder.cb.setChecked(false);//特别说明:把它全部设为false,是因为每次删除完之后会出现下一个界面上显示为选中但是不能删除,只有先取消再点击才有效,这应该是界面的绘制问题(猜测)
153             return convertView;
154         }
155         /*
156          * MyAdapter中的内部类实现了OnCheckedChangeListener接口,
157          * 提供一个构造函数,此处的构造函数的作用是传递了一个position参数,
158          * 可以与getView中的position关联起来,也可以在类内部的onCheckedChanged方法中使用。
159          * onCheckedChanged方法是在checkBox的状态改变时被调用的,为了删除按钮的点击事件中
160          * 能够获取到当前选中的所有项,所以每当选中一项,就把当前项放在一个list列表中,这样
161          * 在删除按钮处理点击事件时,就可以轻松完成。
162          * 一个小小的效果:有选中项时删除按钮显示,否则按钮消失。
163          * 实现:按钮初始状态为不可见,每当选中一项则设为可见,每当取消一项,判断是否还有选中,
164          * 若没有选中项,设为不可见
165          */
166         class checkedChangeListener implements OnCheckedChangeListener{
167             int position;
168             public checkedChangeListener(int position){
169                 this.position=position;
170             }
171 
172             @Override
173             public void onCheckedChanged(CompoundButton buttonView,
174                     boolean isChecked) {
175                 /*
176                  * 当某一个checkbox被选中时,先显示点击了当前item,然后把当前元素作为对象加入positions列表当中
177                  * 设置删除按钮为可见
178                  */                
179                 if(isChecked){
180                     imgbtn.setVisibility(View.VISIBLE);
181                     Toast.makeText(getApplicationContext(), "点击了"+(String)list.get(position).get("title"),Toast.LENGTH_SHORT).show();
182                     positions.add(list.get(position));
183                 }else{
184                     /*
185                      * 当该项被取消时,先显示取消了此项,然后把当前项从列表中删除,
186                      * 每次删除完之后,判断是否还有选中项,如果没有选中项,设置删除按钮不可见
187                      */
188                     
189                     Toast.makeText(getApplicationContext(), "取消了"+(String)list.get(position).get("title"),Toast.LENGTH_SHORT).show();
190                     positions.remove(list.get(position));
191                     //判断当前是否有选中项,若没有,隐藏删除按钮
192                     if(positions.size()==0){
193                         imgbtn.setVisibility(View.INVISIBLE);
194                     }
195                 }
196             }
197         }
198 
199         /*
200          * 此处没有用到下面两个方法,故不作说明
201          * (non-Javadoc)
202          * @see android.widget.Adapter#getItem(int)
203          */
204         @Override
205         public Object getItem(int position) {
206             // TODO Auto-generated method stub
207             return null;
208         }
209 
210         @Override
211         public long getItemId(int position) {
212             // TODO Auto-generated method stub
213             return 0;
214         }
215         
216     }
217 }

    代码均已测试,无明显bug。因本人水平有限,出错之处在所难免,欢迎指正。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。