android ListView进阶
ListView
1.在android 开发中很多时候都要用到ListView的这个控件的,但用这个控件的时候会遇到一些问题,如在ListView中有Button按钮,就需要将按钮的监听事件给分离出来,且将Button该为自己的定义的Button控件
这只是一个思路,在进行例子之前,对一些小的知识点进行一下复习:
2.API是开发中最好的老师,它对ListView的解释是:
3.这里就对ListView运行机制做个解释(引用别人的一段话):
listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特 别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样 return 1,就只显示一行。 系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写 getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几 行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成 View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮 为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统 要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一 个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布 局文件中将Button设置为没有焦点就OK了
4.在给按钮添加OnClickListener的时候,一开始很下意识的会想在ListView的adapter的getView方法中找到每个 Button并new一个OnClickListener分配给这个button。但是当数据量很大的时候,new出来这么多个监听器势必会对内存造成一 定的压力,而且每个Listener的功能完全一样,Listener里面所需知道的
所以自定一个MyOnClickListener(用了单例模式,这样就不会造成new了很多同一个对象了)
1 public class MyOnClickListener implements OnClickListener { 2 3 private static MyOnClickListener instance; 4 private Context context; 5 6 public MyOnClickListener() { 7 } 8 9 public static MyOnClickListener instance() { 10 if (instance == null) { 11 12 instance = new MyOnClickListener(); 13 } 14 15 return instance; 16 } 17 18 @Override 19 public void onClick(View v) { 20 MyButton button = (MyButton) v; 21 String userID = button.getUserID(); 22 Toast.makeText(context, "所获得的用户ID为:" + userID, Toast.LENGTH_SHORT) 23 .show(); 24 } 25 26 /** 27 * @return the context 28 */ 29 public Context getContext() { 30 return context; 31 } 32 33 /** 34 * @param context 35 * the context to set 36 */ 37 public void setContext(Context context) { 38 this.context = context; 39 } 40 41 }
5.因为要从外面获取参数别进行处理,而处理是交给MyOnClickListener的,而MyOnClickLister能获取到的就是Button了,这时就需要一个自己定的Button(MyButton)来获取到外部数据:
MyButton:
1 public class MyButton extends Button { 2 3 private String userID; 4 5 public MyButton(Context context) { 6 super(context); 7 } 8 9 public MyButton(Context context, AttributeSet attrs) { 10 super(context, attrs); 11 } 12 13 public MyButton(Context context, AttributeSet attrs, int defstyle) { 14 super(context, attrs, defstyle); 15 } 16 17 /** 18 * @return the userID 19 */ 20 public String getUserID() { 21 return userID; 22 } 23 24 /** 25 * @param userID 26 * the userID to set 27 */ 28 public void setUserID(String userID) { 29 this.userID = userID; 30 } 31 32 }
6.主要的两个类都完成了,现在就是很普通的一些东西了
MianActivity:
1 public class MainActivity extends Activity { 2 3 private ListView listView; 4 private List<HashMap<String, Object>> list; 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 initData(); 11 listView = (ListView)findViewById(R.id.listView); 12 MyAdapter adapter = new MyAdapter(); 13 listView.setAdapter(adapter); 14 } 15 16 private void initData() { 17 list = new ArrayList<HashMap<String, Object>>(); 18 HashMap<String, Object> map1 = new HashMap<String, Object>(); 19 map1.put("image", R.drawable.ic_launcher); 20 map1.put("userID", "1"); 21 HashMap<String, Object> map2 = new HashMap<String, Object>(); 22 map2.put("image", R.drawable.ic_launcher); 23 map2.put("userID", "2"); 24 HashMap<String, Object> map3 = new HashMap<String, Object>(); 25 map3.put("image", R.drawable.ic_launcher); 26 map3.put("userID", "3"); 27 HashMap<String, Object> map4 = new HashMap<String, Object>(); 28 map4.put("image", R.drawable.ic_launcher); 29 map4.put("userID", "4"); 30 HashMap<String, Object> map5 = new HashMap<String, Object>(); 31 map5.put("image", R.drawable.ic_launcher); 32 map5.put("userID", "5"); 33 list.add(map1); 34 list.add(map2); 35 list.add(map3); 36 list.add(map4); 37 list.add(map5); 38 39 } 40 41 public class MyAdapter extends BaseAdapter { 42 43 @Override 44 public int getCount() { 45 return list.size(); 46 } 47 48 @Override 49 public Object getItem(int position) { 50 return list.get(position); 51 } 52 53 @Override 54 public long getItemId(int position) { 55 return position; 56 } 57 58 @Override 59 public View getView(int position, View convertView, ViewGroup parent) { 60 View view = LayoutInflater.from(MainActivity.this).inflate( 61 R.layout.item, null); 62 TextView textView = (TextView) view.findViewById(R.id.userID); 63 textView.setText((CharSequence) list.get(position).get("userID")); 64 MyButton button = (MyButton) view.findViewById(R.id.button); 65 button.setUserID((String) list.get(position).get("userID")); 66 button.setOnClickListener(MyOnClickListener.instance()); 67 MyOnClickListener.instance().setContext(MainActivity.this); 68 return view; 69 } 70 71 } 72 73 @Override 74 public boolean onCreateOptionsMenu(Menu menu) { 75 getMenuInflater().inflate(R.menu.main, menu); 76 return true; 77 } 78 79 }
7.ListView中的每个item布局文件
item.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="horizontal" > 6 7 <ImageView 8 android:id="@+id/image" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:src="@drawable/ic_launcher" /> 12 13 <TextView 14 android:id="@+id/userID" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:text="用户ID" /> 18 19 <com.example.listview.MyButton 20 android:id="@+id/button" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:text="显示ID" /> 24 25 </LinearLayout>
MianActivity就不贴出来了,他里面就一个 ListView
运行后的效果是:
当点击第三个按钮的时候,弹出对应的数字:
ListView中button点击事件盖掉onItemClick解决办法在:这里可以查看到
源码下载:下载