轉載本專欄博客,請註明出處:道龍的博客html
最近在公司參與的項目中有一個界面須要作局部UI更新處理,把其化煩爲簡爲Demoi形式寫在這裏。咱們仍是運行該Demo,知道ListView局部刷新的使用場景:(受時間限制,本篇就介紹這麼多功能,下一篇會在這個Demo中加入更多的功能)java
能夠看到,點擊每一個Item的時候,ListView上的CheckBox會選中或取消選中。這裏面用到知識點就是ListView的局部刷新,局部的意思就是脫離ListView,在每一個Item位置進行更新UI操做。那麼就從頭一步步的學習如何實現這個功能:eclipse
模擬數據源,把最基本的功能先跑起來:ide
佈局、自定義樣式、自定義選擇器都很簡單,過多的代碼就再也不寫了,文章只貼出業務邏輯重要的代碼(文章最後會給出源代碼可自行下載;因爲實習公司使用的IDE仍是Eclipse,本篇是基於eclipse寫的)
佈局
主活動中代碼也很常規簡單:學習
public class MainActivity extends Activity { private ListView mListView; List<ItemBean> mDatas = new ArrayList<ItemBean>(); private MyAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.listview); initData(); adapter = new MyAdapter(); mListView.setAdapter(adapter); } /**模擬數據*/ private void initData() { ItemBean mItemBean = null; for (int i = 0; i < 40; i++) { //集合添加20個對象 mItemBean = new ItemBean(); mItemBean.setText("學習ListView局部刷新"+i); mItemBean.setResIcon(R.drawable.directory_icon); mDatas.add(mItemBean); } } private class MyAdapter extends BaseAdapter{ @Override public int getCount() { if(mDatas != null){ return mDatas.size(); } return 0; } @Override public Object getItem(int position) { if(mDatas != null){ return mDatas.get(position); } return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ holder = new ViewHolder(); convertView = View.inflate(getApplicationContext(), R.layout.file_item, null); holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon); holder.tvText = (TextView) convertView.findViewById(R.id.tv_name); holder.ivOption = (ImageView) convertView.findViewById(R.id.iv_option); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } //拿到數據 ItemBean mItem = (ItemBean) getItem(position); //設置數據 holder.ivIcon.setImageResource(mItem.getResIcon()); holder.tvText.setText(mItem.getText()); return convertView; } class ViewHolder{ ImageView ivIcon; TextView tvText; ImageView ivOption; } } }此時運行程序:
接下來就對上邊的常規代碼作一下修飾了:測試
咱們長按item的時候,但願整個佈局改變一下進入編輯模式,讓複選框圖標展現,對應位置上ImageView圖標消失,就能夠這麼寫。spa
首先寫一個方法,來控制佈局的改變:.net
private boolean isEdit; /**開始編輯模式*/ private void startEditMode() { isEdit = true;//標誌位置爲true //進入編輯模式,要改變IListView的界面 adapter.notifyDataSetChanged(); } /**結束編輯模式*/ private void stopEditMode(){ isEdit = false; }
而後加入長按item的點擊事件:code
mListView.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { startEditMode(); return true;//返回true後,mListView.setOnItemClickListener就不會再去調用 } });
定義一個item局部刷新的方法:
/**定義一個item局部刷新的方法*/ public void updateItemView(View ItemView){ CheckBox itemCb = (CheckBox) ItemView.findViewById(R.id.cb_checkbox); if(itemCb.isChecked()){ //點擊item,從選中狀態調到未選中狀態 itemCb.setChecked(false); }else{ itemCb.setChecked(true); } }
mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(isEdit){ //若是是編輯模式 adapter.updateItemView(view); }else{ //不是編輯模式,點擊item作其餘邏輯處理 Toast.makeText(getApplicationContext(), "當前item"+position, 0).show(); } } });目前咱們僅僅是實現了界面的刷新,可是cb的選中與取消要記錄起來,點擊了哪一個item也要記錄起來,這樣才能作接下來的操做,選中cb執行什麼樣的任務,所以咱們須要使用javabean,記錄每次點擊選中cb的操做:
具體的局部刷新修改後的方法以下:
/**定義一個item局部刷新的方法*///position,爲了拿到當前item的對象,記錄狀態 public void updateItemView(View ItemView,int position){ position = position - mListView.getHeaderViewsCount(); ItemBean itemBean = mDatas.get(position); CheckBox itemCb = (CheckBox) ItemView.findViewById(R.id.cb_checkbox); if(itemCb.isChecked()){ //點擊item,從選中狀態調到未選中狀態 itemCb.setChecked(false); //記錄當前item未選中狀態 itemBean.setChecked(false); }else{ itemCb.setChecked(true); //記錄當前item選中狀態 itemBean.setChecked(true); } //經過集合把選中的item的對象itemBean記錄起來 List<ItemBean> selectDatas = new ArrayList<ItemBean>(); for (ItemBean info : mDatas) { if(info.isChecked()){//當前的item是選中的 selectDatas.add(info); } } /**測試局部刷新*/ for (ItemBean itemBean2 : selectDatas) { System.out.println(itemBean2.getText()); } }而後該方法確定要被調用咯,在哪裏調用?點擊item的時候嘛,那就在註冊item的點擊事件稍做修改就能夠了:
mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(isEdit){ //若是是編輯模式 adapter.updateItemView(view,position); }else{ //不是編輯模式,點擊item作其餘邏輯處理 Toast.makeText(getApplicationContext(), "當前item"+position, 0).show(); } } });
可是這個時候仍是有許多問題的,好比第二頁的數據會複用第一頁的數據,那就先解決這個bug。
只須要在getView裏面,對item上邊的cb從新複製就能夠了。
if(isEdit){//是編輯模式 // Ui層面進入編輯模式 holder.checkBox.setVisibility(View.VISIBLE); holder.ivOption.setVisibility(View.GONE); /**解決複用問題,對每個item上的cb都從新賦值*/ if (mItem.isChecked()) { holder.checkBox.setChecked(true); } else { holder.checkBox.setChecked(false); } }else{ holder.checkBox.setVisibility(View.GONE); holder.ivOption.setVisibility(View.VISIBLE); }
接下來的邏輯稍微複雜,就是經過當前狀態,來修改頂端的標題欄狀態。
首先,長按進入編輯模式的時候,要顯示當前選中多少個。須要一個標誌位mSelectedCount。進入編輯模式,顯示標題:
//修改標題欄 mTextView.setText(String.format("已選擇了%d個", mSelectedCount));
if(itemCb.isChecked()){ //點擊item,從選中狀態調到未選中狀態 itemCb.setChecked(false); //記錄當前item未選中狀態 itemBean.setChecked(false); mSelectedCount --; }else{ itemCb.setChecked(true); //記錄當前item選中狀態 itemBean.setChecked(true); mSelectedCount ++; }因爲邏輯稍微複雜,也不是要介紹局部刷新這個技術點的範圍了,就再也不繼續往下寫了。我把Demo所有代碼,打包上傳了。能夠直接去下載,學習。看看一下後邊的複雜邏輯是如何實現的:
明天或者後天加入更多功能後,再把資源上傳吧,今天就到這裏了~