通过使用ListView制作一个水果选择菜单,菜单中有多种水果,菜单每种水果以水果选择框, 水果图片, 水果名称的形式展现在ListView中的每个Item中。
1. 通过水果多选框可以选择想要的水果。
2. 通过点击每条Item的任意地方也可以选择水果。
3. ListView最顶端设置有顶部全选按钮,通过点击按钮可以全部选中水果。
4. ListView最低端设置有底部反选按钮,通过点击按钮可以反选水果。
这只是一个简单的小练习,界面比较简单粗略,仅用来练习使用,大神们不要嫌弃……嘿嘿
做什么都是一步一步来的,首先我们要先构建显示列表,这就要用到我们在前一节所用到的自定义Adapter,通过自定义Adapter来构建显示列表。
回想一下自定义Adapter的步骤:
public class Fruit {
private boolean mCheckBoxchecked;//是否选中水果。
private int mImage;//水果图片
private String mFruitName;//水果名称
//自定义构造器,通过构造器来对水果初始化。
public Fruit(int mImage, String mFruitName) {
this.mImage = mImage;
this.mFruitName = mFruitName;
}
public boolean ismCheckBoxchecked() {
return mCheckBoxchecked;
}
public void setmCheckBoxchecked(boolean mCheckBoxchecked) {
this.mCheckBoxchecked = mCheckBoxchecked;
}
public int getmImage() {
return mImage;
}
public void setmImage(int mImage) {
this.mImage = mImage;
}
public String getmFruitName() {
return mFruitName;
}
public void setmFruitName(String mFruitName) {
this.mFruitName = mFruitName;
}
}
V,即View。构建数据显示的视图。我们是以什么样的形式来显示Fruit的。然后自定义一个Adapter,通过自定义的Adapter将水果数据添加到View视图中。
这里我们用下图方式来构建View视图,也就是水果显示的方式。布局文件就不在贴出,在最后会给出源代码。
自定义的Adapter:
public class FruitAdapter extends BaseAdapter{
private List mFruit;//水果数据
private LayoutInflater mInflater;//LayoutInflater 加载布局
//自定义构造器,接收数据和加载布局的LayoutInflater对象。
public FruitAdapter(List mFruit, LayoutInflater mInflater) {
this.mFruit = mFruit;
this.mInflater = mInflater;
}
@Override
public int getCount() {
return mFruit.size();//获得Item的数量
}
@Override
public Object getItem(int position) {
return position;//获得Item的位置
}
@Override
public long getItemId(int position) {
return position;//获得Item的Id,我们这里依然返回位置。
}
@Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
//ViewHolder创建对象。
ViewHolder viewHolder = new ViewHolder();
//获得该Item下的水果对象。
Fruit fruit =mFruit.get(position);
if(convertView == null){
convertView = mInflater.inflate(R.layout.item_list_fruit, null);
viewHolder.checkBoxSelect = (CheckBox) convertView.findViewById(R.id.checkbox_select);
viewHolder.imageViewFruit = (ImageView) convertView.findViewById(R.id.imageview_fruit);
viewHolder.textViewFruitName = (TextView) convertView.findViewById(R.id.textview_fruitname);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageViewFruit.setImageResource(fruit.getmImage());
viewHolder.textViewFruitName.setText(fruit.getmFruitName());
return convertView;
}
class ViewHolder{
ImageView imageViewFruit;
TextView textViewFruitName;
}
}
- C,即Control。控制总体,首先初始化数据,然后将自己设置好的View添加到ListView中。
Activity中的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/lisview_fruit"
android:layout_width="match_parent"
android:layout_height="match_parent">
ListView>
RelativeLayout>
Activity类:
public class MainActivity extends Activity {
private List mFruit;
private ListView mListViewFruit;
private FruitAdapter mAdapter;
private LayoutInflater mInflater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得ListView的对象
mListViewFruit = (ListView) findViewById(R.id.lisview_fruit);
//获得布局加载对象
mInflater = getLayoutInflater();
//初始化数据
initData();
//创建自定义Adapter的对象
mAdapter = new FruitAdapter(mFruit, mInflater);
mListViewFruit.setAdapter(mAdapter);
}
//初始化数据。
private void initData() {
mFruit = new ArrayList();
//有点偷懒,这里水果为了增加数量就循环添加了,不在一一初始化
for (int i = 0; i < 5; i++) {
Fruit apple = new Fruit(R.mipmap.apple, "苹果");
Fruit banana = new Fruit(R.mipmap.banana, "香蕉");
Fruit grape = new Fruit(R.mipmap.grape, "葡萄");
Fruit watermelon = new Fruit(R.mipmap.watermelon, "西瓜");
Fruit pineapple = new Fruit(R.mipmap.pineapple, "菠萝");
mFruit.add(apple);
mFruit.add(banana);
mFruit.add(grape);
mFruit.add(watermelon);
mFruit.add(pineapple);
}
}
}
结果:
第一步我们已经完成了基本的显示功能。让我们来添加第二个功能。通过点击水果图片前面的选择框来中水果。这就用到了CheckBox的点击事件。我们通过监听选择框的状态来断定选择的水果。
对自定义Adapter 修改如下(在getView()方法中添加店家事件。)
public class FruitAdapter extends BaseAdapter{
private List mFruit;
private LayoutInflater mInflater;
private boolean[] mManagerCheckBox;//管理图片前选择框的状态。
public FruitAdapter(List mFruit, LayoutInflater mInflater) {
this.mFruit = mFruit;
this.mInflater = mInflater;
//初始化CheckBox的管理器,其长度为数据的数量。默认初始化值为false。
mManagerCheckBox=new boolean[mFruit.size()];
}
@Override
public int getCount() {
return mFruit.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
ViewHolder viewHolder = new ViewHolder();
Fruit fruit =mFruit.get(position);
if(convertView == null){
convertView = mInflater.inflate(R.layout.item_list_fruit, null);
viewHolder.checkBoxSelect = (CheckBox) convertView.findViewById(R.id.checkbox_select);
viewHolder.imageViewFruit = (ImageView) convertView.findViewById(R.id.imageview_fruit);
viewHolder.textViewFruitName = (TextView) convertView.findViewById(R.id.textview_fruitname);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageViewFruit.setImageResource(fruit.getmImage());
viewHolder.textViewFruitName.setText(fruit.getmFruitName());
//添加点击事件
viewHolder.checkBoxSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
/*
对CheckBox进行赋值
*/
mManagerCheckBox[position] = isChecked;
Log.d("data", "" + mFruit.get(position).getmFruitName() + "---------" + mManagerCheckBox[position] + "选中");
notifyDataSetChanged();
}
});
viewHolder.checkBoxSelect.setChecked(mManagerCheckBox[position]);
return convertView;
}
class ViewHolder{
CheckBox checkBoxSelect;
ImageView imageViewFruit;
TextView textViewFruitName;
}
}
这个功能是很常见的,举例来说,我们逛淘宝,商品的展示就是用ListView控件来实现的,我们有时候想要进入某个商品的具体界面只需点击Item的任意一个位置就可以。我们现在就要实现这个功能。
实现这个功能前我们首先要了解一个知识点,当在一个Button上放置一个CheckBox,RadioButton或者其他按钮时,Button的点击就会被其上面的CheckBox,RadioButton或者其他按钮给“吃掉”。当我们点击屏幕时,是屏幕首先接收到这个点击事件,然后他会将这个点击事件通过硬件等一系列传送后报给View,然后View再将点击事件报给在顶端的CheckBox,RadioButton或者其他按钮,当顶端的CheckBox,RadioButton或者其他按钮接收到以后,一看不是自己的点击事件,就会将其给吃掉,不做任何反应,以至于点击底端的Button并没有反应。
解决此问题首先要让顶端的CheckBox,RadioButton或者其他按钮“不吃掉”底端按钮的点击,这是需要在CheckBox布局文件中添加如下语句:
android:focusable="false"
在Activity添加ListView的点击事件,在onCreate中添加如下:
mListViewFruit.setAdapter(mAdapter);
mListViewFruit.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
mAdapter.itemChangge(position-1);
}
});
将ListView的点击与CheckBox相关联,在自定义Adapter中添加如下方法:
/*
接收Activity传来的position,当position变化时调用。
*/
public void itemChangge(int position){
mManagerCheckBox[position] = !mManagerCheckBox[position];
notifyDataSetChanged();
}
结果:
这里用到了ListView的一个功能:添加Header,在ListView的顶端添加布局。这里我们实现的功能是添加顶部按钮,所以我们只需要在顶端布局中添加一个按钮即可。
顶部布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CheckBox
android:id="@+id/checkbox_all_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选" />
LinearLayout>
自定义Adapter中添加全选操作:
/*
设置全选的方法
*/
public void itemAllChecked(){
for (int i = 0; i true;
notifyDataSetChanged();
}
}
/*
设置全不选的方法
*/
public void itemNoneChecked(){
for (int i = 0; i false;
notifyDataSetChanged();
}
}
Activity中添加:
public class MainActivity extends Activity {
private List mFruit;
private ListView mListViewFruit;
private FruitAdapter mAdapter;
private LayoutInflater mInflater;
//顶部按钮
private View mHeaderAllChecked;
private CheckBox mCheckBoxAllChecked;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListViewFruit = (ListView) findViewById(R.id.lisview_fruit);
mInflater = getLayoutInflater();
initData();
/*
设置全选按钮
*/
mHeaderAllChecked =mInflater.inflate(R.layout.fruit_header, null);
mCheckBoxAllChecked = (CheckBox) mHeaderAllChecked.findViewById(R.id.checkbox_all_checked);
mCheckBoxAllChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
mAdapter.itemAllChecked();
} else {
mAdapter.itemNoneChecked();
}
}
});
mListViewFruit.addHeaderView(mHeaderAllChecked);
mAdapter = new FruitAdapter(mFruit, mInflater);
mListViewFruit.setAdapter(mAdapter);
mListViewFruit.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
mAdapter.itemChangge(position-1);
}
});
}
private void initData() {
//此处省略……
}
}
这个和顶部按钮全选是先是相同的,只是实现的功能不同,此处不再赘述,直接上代码。
底部布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_negation_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="反选"/>
LinearLayout>
自定义Adapter中添加全选操作:
/*
设置取反的操作
*/
public void itemNegationChecked(){
for (int i = 0; i
Activity中添加:
public class MainActivity extends Activity {
private List mFruit;
private ListView mListViewFruit;
private FruitAdapter mAdapter;
private LayoutInflater mInflater;
//顶部按钮
private View mHeaderAllChecked;
private CheckBox mCheckBoxAllChecked;
//底部按钮
private View mFooterNegationChecked;
private Button mButtonNegation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListViewFruit = (ListView) findViewById(R.id.lisview_fruit);
mInflater = getLayoutInflater();
initData();
/*
设置全选按钮
*/
mHeaderAllChecked =mInflater.inflate(R.layout.fruit_header, null);
mCheckBoxAllChecked = (CheckBox) mHeaderAllChecked.findViewById(R.id.checkbox_all_checked);
mCheckBoxAllChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
mAdapter.itemAllChecked();
} else {
mAdapter.itemNoneChecked();
}
}
});
mListViewFruit.addHeaderView(mHeaderAllChecked);
/*
设置取反按钮
*/
mFooterNegationChecked = mInflater.inflate(R.layout.item_footer,null);
mButtonNegation = (Button) mFooterNegationChecked.findViewById(R.id.button_negation_checked);
mButtonNegation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mAdapter.itemNegationChecked();
}
});
mListViewFruit.addFooterView(mFooterNegationChecked);
mAdapter = new FruitAdapter(mFruit, mInflater);
mListViewFruit.setAdapter(mAdapter);
mListViewFruit.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
mAdapter.itemChangge(position-1);
}
});
}
private void initData() {
//此处省略……
}
}
结果: