ViewHolder模式充分利用ListView的視圖緩存機制,避免了每次在調用getView()方法的時候都去經過findViewById()方法實例化控件。使用ViewHolder模式,須要在自定義Adapter中定義一個內部類ViewHolder,並將佈局中的控件做爲成員變量。起始時,ListView建立的Cell條數量是當前屏幕顯示的Cell條數,在向上滾動時,新顯示的Cell是滾出屏幕的Cell的複用。與iOS的TableView的Cell優化同樣。android
1. 示例緩存
1 public class ViewHolderAdapter extends BaseAdapter 2 { 3 private List<String> mData; 4 private LayoutInflater mInflater; 5 6 public ViewHolderAdapter(Context context, List<String> data) 7 { 8 mData = data; 9 mInflater = LayoutInflater.from(context); 10 } 11 12 @Override 13 public int getCount() 14 { 15 return mData.size(); 16 } 17 18 @Override 19 public Object getItem(int position) 20 { 21 return mData.get(position); 22 } 23 24 @Override 25 public long getItemId(int position) 26 { 27 return position; 28 } 29 30 @Override 31 public View getView(int position, View convertView, ViewGroup parent) 32 { 33 ViewHolder holder = null; 34 // 判斷是否緩存 35 if (convertView == null) 36 { 37 holder = new ViewHolder(); 38 // 經過LayoutInflater實例化佈局 39 convertView = mInflater.inflate(R.layout.viewholder_item, null); 40 holder.mImgView = (ImageView) convertView.findViewById(R.id.icon); 41 holder.mTitle = (TextView) convertView.findViewById(R.id.title); 42 convertView.setTag(holder); 43 } 44 else 45 { 46 holder = (ViewHolder) convertView.getTag(); 47 } 48 49 holder.mImgView.setBackgroundResource(R.mipmap.ic_launcher); 50 holder.mTitle.setText(mData.get(position)); 51 52 return convertView; 53 } 54 55 public final class ViewHolder 56 { 57 public ImageView mImgView; 58 public TextView mTitle; 59 } 60 }
系統提供了divider(顏色)和dividerHeight(高度)這兩個屬性實例ListView項目間分隔線。ide
1 android:divider="@android:color/darker_gray" 2 android:dividerHeight="10dp"
設置透明分隔線:佈局
1 android:divider="@null"
ListView在滾動時,默認在右側顯示滾動條,能夠經過scrollbars屬性設置不顯示滾動條:優化
1 android:scrollbars="none"
經過listSelector屬性設置Cell選中後的顏色:this
1 android:listSelector="#000000"
使用系統自帶的透明色來實現:spa
1 android:listSelector="@android:color/transparent"
ListView中的數據在某些狀況下是須要變化的,固然能夠經過從新設置ListView的Adapter來更新ListView的顯示,可是,這須要從新獲取數據,至關於從新建立ListView。能夠經過如下方法實現動態更新ListView數據顯示:code
1 mData.add("test"); 2 mHolderAdapter.notifyDataSetChanged();
PS:當修改了傳遞給Adapter的映射List以後,只須要經過調用Adapter的notifyDataSetChanged()方法,經過ListView更新數據源便可完成對ListView的動態修改。blog
ListView做爲一個ViewGroup,提供了各類操縱子View的方法,最經常使用的就是經過getChildAt()方法獲取第i個子View,代碼以下所示:事件
1 for (int idx = 0; idx < mListView.getChildCount(); idx++) 2 { 3 View view = mListView.getChildAt(idx); 4 }
在列表無數據時,ListView不顯示數據或者提示,ListView提供了setEmptyView()方法,經過這個方法能夠給ListView設置一個空數據下顯示的默認提示。代碼以下所示:
1 // list view 2 mListView = (ListView) findViewById(R.id.listview); 3 mHolderAdapter = new ViewHolderAdapter(this, mData); 4 mListView.setAdapter(mHolderAdapter); 5 // 獲取在空List時,顯示的View 6 mNotDataView = (TextView) findViewById(R.id.emptyListview); 7 // 設置ListView在空數據時,顯示的View 8 mListView.setEmptyView(mNotDataView);
1. OnTouchListener是View中的監聽事件,經過監聽ACTION_DOWN、ACTION_MOVE、ACTION_UP這三個事件發生時的座標,就能夠根據座標判斷用戶滑動的方向:
1 mListView.setOnTouchListener(new View.OnTouchListener() 2 { 3 @Override 4 public boolean onTouch(View v, MotionEvent event) 5 { 6 switch (event.getAction()) 7 { 8 case MotionEvent.ACTION_DOWN: 9 { 10 // 觸摸時操做 11 Log.d(TAG, "Down"); 12 break; 13 } 14 case MotionEvent.ACTION_MOVE: 15 { 16 // 移動時操做 17 Log.d(TAG, "Move"); 18 break; 19 } 20 case MotionEvent.ACTION_UP: 21 { 22 // 手指離開屏幕時操做 23 Log.d(TAG, "Up"); 24 break; 25 } 26 } 27 return false; 28 } 29 });
2. OnScrollListener是AbsListView中的監聽事件,通常經常使用方法, 以下代碼所示:
1 mListView.setOnScrollListener(new AbsListView.OnScrollListener() 2 { 3 @Override 4 public void onScrollStateChanged(AbsListView view, int scrollState) 5 { 6 switch (scrollState) 7 { 8 case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: 9 { 10 // 滑動中止時 11 Log.d(TAG, "SCROLL_STATE_IDLE"); 12 break; 13 } 14 case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: 15 { 16 // 正在滾動 17 Log.d(TAG, "SCROLL_STATE_TOUCH_SCROLL"); 18 break; 19 } 20 case AbsListView.OnScrollListener.SCROLL_STATE_FLING: 21 { 22 // 手指拋開時,即手指用力滑動,在離開後ListView因爲慣性繼續滑動 23 Log.d(TAG, "SCROLL_STATE_FLING"); 24 break; 25 } 26 } 27 } 28 29 int lastVisibleItemPosition = 0; 30 @Override 31 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 32 { 33 // 滾動時,一直調用 34 Log.d(TAG, "onScroll"); 35 36 // 判斷滾動方向 37 if (firstVisibleItem > lastVisibleItemPosition) 38 { 39 // 向上滾動 40 Log.d(TAG, "Scroll Up"); 41 } 42 else if (firstVisibleItem < lastVisibleItemPosition) 43 { 44 // 向下滾動 45 Log.d(TAG, "Scroll Down"); 46 } 47 lastVisibleItemPosition = firstVisibleItem; 48 } 49 });
在ListView滾動時會一直回調,而方法中的後三個int類型的參數,則很是精確的顯示了當前ListView滾動的狀態,這三個參數以下所示:
在ListView中還有一些其它的方法,以下代碼所示:
1 // 獲取可視區域內最後一個Item的id 2 mListView.getLastVisiblePosition(); 3 // 獲取可視區域內的第一個Item的id 4 mListView.getFirstVisiblePosition();