功能說明:
通過使用ListView製作一個水果選擇選單,選單中有多種水果,選單每種水果以水果選擇框, 水果圖片, 水果名稱的形式展現在ListView中的每個Item中。
1. 通過水果多選框可以選擇想要的水果。
2. 通過點選每條Item的任意地方也可以選擇水果。
3. ListView最頂端設定有頂部全選按鈕,通過點選按鈕可以全部選中水果。
4. ListView最低端設定有底部反選按鈕,通過點選按鈕可以反選水果。
這只是一個簡單的小練習,介面比較簡單粗略,僅用來練習使用,大神們不要嫌棄……嘿嘿
Frist.顯示列表的實現
做什麼都是一步一步來的,首先我們要先構建顯示列表,這就要用到我們在前一節所用到的自定義Adapter,通過自定義Adapter來構建顯示列表。
回想一下自定義Adapter的步驟:
- M,即Model。構建資料。首先我們要先建立顯示在水果選單上的水果資料。定義一個Fruit類。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
public class FruitAdapter extends BaseAdapter{ private List<Fruit> mFruit;//水果資料 private LayoutInflater mInflater;//LayoutInflater 載入佈局 //自定義構造器,接收資料和載入佈局的LayoutInflater物件。 public FruitAdapter(List<Fruit> 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中的佈局:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<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類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class MainActivity extends Activity { private List<Fruit> 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<Fruit>(); //有點偷懶,這裡水果為了增加數量就迴圈新增了,不在一一初始化 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); } } } |
結果:
Two.選擇框選擇水果功能的實現
第一步我們已經完成了基本的顯示功能。讓我們來新增第二個功能。通過點選水果圖片前面的選擇框來中水果。這就用到了CheckBox的點選事件。我們通過監聽選擇框的狀態來斷定選擇的水果。
對自定義Adapter 修改如下(在getView()方法中新增店家事件。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
public class FruitAdapter extends BaseAdapter{ private List<Fruit> mFruit; private LayoutInflater mInflater; private boolean[] mManagerCheckBox;//管理圖片前選擇框的狀態。 public FruitAdapter(List<Fruit> 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; } } |
Three.點選Item任意處選擇水果功能的實現
這個功能是很常見的,舉例來說,我們逛淘寶,商品的展示就是用ListView控制元件來實現的,我們有時候想要進入某個商品的具體介面只需點選Item的任意一個位置就可以。我們現在就要實現這個功能。
實現這個功能前我們首先要了解一個知識點,當在一個Button上放置一個CheckBox,RadioButton或者其他按鈕時,Button的點選就會被其上面的CheckBox,RadioButton或者其他按鈕給“吃掉”。當我們點選螢幕時,是螢幕首先接收到這個點選事件,然後他會將這個點選事件通過硬體等一系列傳送後報給View,然後View再將點選事件報給在頂端的CheckBox,RadioButton或者其他按鈕,當頂端的CheckBox,RadioButton或者其他按鈕接收到以後,一看不是自己的點選事件,就會將其給吃掉,不做任何反應,以至於點選底端的Button並沒有反應。
解決此問題首先要讓頂端的CheckBox,RadioButton或者其他按鈕“不吃掉”底端按鈕的點選,這是需要在CheckBox佈局檔案中新增如下語句:
1 |
android:focusable="false" |
在Activity新增ListView的點選事件,在onCreate中新增如下:
1 2 3 4 5 6 7 |
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中新增如下方法:
1 2 3 4 5 6 7 |
/* 接收Activity傳來的position,當position變化時呼叫。 */ public void itemChangge(int position){ mManagerCheckBox[position] = !mManagerCheckBox[position]; notifyDataSetChanged(); } |
結果:
Four.頂部按鈕全選的實現
這裡用到了ListView的一個功能:新增Header,在ListView的頂端新增布局。這裡我們實現的功能是新增頂部按鈕,所以我們只需要在頂端佈局中新增一個按鈕即可。
頂部佈局:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="utf-8"?> <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中新增全選操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* 設定全選的方法 */ public void itemAllChecked(){ for (int i = 0; i <mManagerCheckBox.length ; i++) { mManagerCheckBox[i] = true; notifyDataSetChanged(); } } /* 設定全不選的方法 */ public void itemNoneChecked(){ for (int i = 0; i <mManagerCheckBox.length ; i++) { mManagerCheckBox[i] = false; notifyDataSetChanged(); } } |
Activity中新增:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class MainActivity extends Activity { private List<Fruit> 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() { //此處省略…… } } |
Four.底部按鈕反選的實現
這個和頂部按鈕全選是先是相同的,只是實現的功能不同,此處不再贅述,直接上程式碼。
底部佈局:
1 2 3 4 5 6 7 8 9 10 |
<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中新增全選操作:
1 2 3 4 5 6 7 8 9 10 |
/* 設定取反的操作 */ public void itemNegationChecked(){ for (int i = 0; i <mManagerCheckBox.length ; i++) { mManagerCheckBox[i] = !mManagerCheckBox[i]; notifyDataSetChanged(); } } |
Activity中新增:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
public class MainActivity extends Activity { private List<Fruit> 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() { //此處省略…… } } |
結果: