ListView嵌套Button

来源:互联网 发布:银河铁道之夜 知乎 编辑:程序博客网 时间:2024/06/01 08:10

最近,好不容易吧listview嵌套button的例子调通了。

原来想做CheckBoxPreference嵌套Button的,但是各种各样的问题让我好纠结,把这个问题解决了,又出现另一个问题,把另一个问题解决了,第一个问题又跑出来的。好像进入了个死循环。

逼于无奈,暂时先用ListView顶替吧。下图是我的实现效果:


例子很简单,ListView的标准配置,一个类和两个布局文件

首先是最简单的layout.xml文件,就是在跟layout里面,放一个listview:


<ListView    android:id="@+id/lv"    android:layout_width="match_parent"    android:layout_height="wrap_content" ></ListView>


接下来是listview_item.xml文件:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal"    android:background="@android:drawable/list_selector_background" >    <TextView        android:id="@+id/lv_item_tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_vertical|center_horizontal"        android:textAppearance="?android:attr/textAppearanceMedium"        android:layout_weight="2" />    <Button        android:id="@+id/lv_item_bt"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_vertical"        android:background="@android:drawable/btn_default_small"        android:text="BUY" />    <CheckBox        android:id="@+id/lv_item_cb"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_vertical"        android:layout_weight="1"        android:clickable="false" /></LinearLayout>

必须注意的地方,是CheckBox里面的android:clickable="false"。
如果没有android:clickable="false",listviewitem的checkbox时,点击事件会被checkbox拦截。但点击listviewitem时,依然有响应;

最后就是强大的MainActivity类,其中包括继承BaseAdapter的Adapter,以及两个用于记录的内部类Item和ViewHolder;代码如下:


public class MainActivity extends Activity {private static final String TAG = "MainActivity";private ListView lv;private BaseAdapter adapter;private List<Item> list;private ArrayList<String> data = new ArrayList<String>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.listview);lv = (ListView) findViewById(R.id.lv);for (int i = 0; i < 20; i++)data.add("aa" + i + "------" + i);// 若同时设setOnItemClickListener和getview中设置的onclicklistener,// onclicklistener会拦截setOnItemClickListener// 这里点击时,button会被覆盖;在getview中设置的onclick却不会覆盖;// lv.setOnItemClickListener(new OnItemClickListener() {// @Override// public void onItemClick(AdapterView<?> arg0, View view, int position,// long arg3) {// }// });init();initAdapter();}// 数据初始化private void init() {if (list == null)list = new ArrayList<Item>();elselist.clear();for (String s : data) {list.add(new Item(s, false));}}// 刷新适配器public void initAdapter() {if (adapter == null) {adapter = new MyAdapter();lv.setAdapter(adapter);} else {adapter.notifyDataSetChanged();}}private class MyAdapter extends BaseAdapter {@Overridepublic int getCount() {return list.size();}@Overridepublic Item getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView,final ViewGroup parent) {ViewHolder holder;if (convertView == null|| (holder = (ViewHolder) convertView.getTag()) == null) {convertView = View.inflate(MainActivity.this,R.layout.listview_item, null);holder = new ViewHolder();holder.tv = (TextView) convertView.findViewById(R.id.lv_item_tv);holder.bt = (Button) convertView.findViewById(R.id.lv_item_bt);holder.bt.setFocusable(false);holder.cb = (CheckBox) convertView.findViewById(R.id.lv_item_cb);convertView.setTag(holder);}Item item = getItem(position);holder.tv.setText(item.name);holder.cb.setChecked(item.isCheck);final CheckBox box = holder.cb;convertView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Log.d(TAG, ("itemview onclicked!! pos: " + position));Item onClickitem = list.get(position);box.setChecked(!box.isChecked());onClickitem.isCheck = box.isChecked();}});holder.bt.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Log.d(TAG, ("button onclicked!! pos: " + position) + '\n'+ "item name: " + list.get(position).name);}});return convertView;}}private class Item {String name;boolean isCheck = false;Item(String name, boolean isBuy) {this.name = name;this.isCheck = isBuy;}}private class ViewHolder {TextView tv;Button bt;CheckBox cb;}}

首先把初始化所有数据,记录每一个listviewitem的属性,并保存到List中。
然后把重写BaseAdapter的adapter设置到ListView,adapter的getView会把保存到List中的item刷到界面(其中Item类的name对应ListViewItem的TextView,isCheck对应CheckBox);


值得一提的是,如代码注释所说,如果设置ListView的ItemOnClickListener的话,点击item时button的样式变为按下状态样式;而在adapter的getView中的view设置OnClickListener,解决了这个问题;