最近,好不容易吧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>();
@Override
protected 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>();
else
list.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 {
@Override
public int getCount() {
return list.size();
}
@Override
public Item getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public 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() {
@Override
public 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() {
@Override
public 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,解决了这个问题;