天天看點

Android ListView點選Item展開隐藏項,單個展開,多個展開一、單項展開

版權聲明:^_^ 尊重原創,共享知識,轉載請注明"_程式猿大人_"http://blog.csdn.net/a_running_wolf

我做了一些修改

   手機螢幕畢竟有限,當我們要顯示較多資料時便不得不舍去一些次要資訊,将主要資訊優先顯示,也使顯示效果更加簡潔美觀。遇到類似的需求,我們使用最多的就是 ListView ,而如果每次點選一個 Item 都要跳轉到下一頁檢視詳情,檢視另一個還要傳回清單重新進入另一條詳情,使得操作繁瑣體驗降低。此時可隐藏和展開 Item 的 ListView 便應運而生,這不是一個新的控件,隻是我們靈活使用造出來的用法,下邊我就來實作 ListView 點選 Item 展開隐藏項,包括清單單項展開、多項展開、複雜布局展開的實作。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、單項展開

   OneExpandActivity 中就是模拟一些資料,使用 OneExpandAdapter 擴充卡加載:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

private void requestData() {
    ArrayList<HashMap<String, String>> datas = new ArrayList<HashMap<String,String>>();
    for(int i = 1; i <= 10; i++){
        HashMap<String, String> item = new HashMap<String, String>();
        item.put("phoneType", "HTC-M" + i + "");
        item.put("discount", "9");
        item.put("price", (2000 + i) + "");
        item.put("time", "2016020" + i);
        item.put("num", (300 - i) + "");
        datas.add(item);
    }

    ListView lvProduct = (ListView) findViewById(R.id.lv_products);
    OneExpandAdapter adapter = new OneExpandAdapter(this, datas);
    lvProduct.setAdapter(adapter);
}      

-------------------------------------------------------------------------------------------------------------------------------

Activity 的布局檔案就不看了,隻有一個 ListView。我們看 OneExpandAdapter.java:先看 Adapter 用到的布局樣式:

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  1. version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@drawable/shape2"  
  6.     android:orientation="vertical" >  
  7.     <LinearLayout  
  8.         android:id="@+id/layout_showArea"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:orientation="horizontal"  
  12.         android:padding="10dp" >  
  13.         <TextView  
  14.             android:id="@+id/tv_phoneType"  
  15.             android:layout_width="wrap_content"  
  16.             android:layout_height="wrap_content"  
  17.             android:text="HTC M8"  
  18.             android:textColor="#162834"  
  19.             android:textSize="25sp" />  
  20.         <TextView  
  21.             android:id="@+id/tv_discount"  
  22.             android:layout_width="wrap_content"  
  23.             android:layout_height="wrap_content"  
  24.             android:layout_marginLeft="12dp"  
  25.             android:text="9"  
  26.             android:textColor="#F75252"  
  27.             android:textSize="15sp" />  
  28.         <TextView  
  29.             android:layout_width="wrap_content"  
  30.             android:layout_height="wrap_content"  
  31.             android:text="折"  
  32.             android:textColor="#F75252"  
  33.             android:textSize="15sp" />  
  34.         <TextView  
  35.             android:id="@+id/tv_price"  
  36.             android:layout_width="wrap_content"  
  37.             android:layout_height="wrap_content"  
  38.             android:layout_marginLeft="100dp"  
  39.             android:text="2000"  
  40.             android:textColor="#F75252"  
  41.             android:textSize="20sp" />  
  42.         <TextView  
  43.             android:layout_width="wrap_content"  
  44.             android:layout_height="wrap_content"  
  45.             android:text="¥"  
  46.             android:textColor="#767171"  
  47.             android:textSize="15sp" />  
  48.     </LinearLayout>  
  49.     <RelativeLayout  
  50.         android:id="@+id/layout_hideArea"  
  51.         android:layout_width="match_parent"  
  52.         android:layout_height="wrap_content"  
  53.         android:padding="10dp" >  
  54.         <TextView  
  55.             android:id="@+id/tv_timeNote"  
  56.             android:layout_width="wrap_content"  
  57.             android:layout_height="wrap_content"  
  58.             android:layout_alignBottom="@+id/tv_time"  
  59.             android:text="活動截止時間:"  
  60.             android:textColor="#162834"  
  61.             android:textSize="12sp" />  
  62.         <TextView  
  63.             android:id="@+id/tv_time"  
  64.             android:layout_width="wrap_content"  
  65.             android:layout_height="wrap_content"  
  66.             android:layout_toRightOf="@id/tv_timeNote"  
  67.             android:text="2016.02.10"  
  68.             android:textColor="#F09BED"  
  69.             android:textSize="15sp" />  
  70.         <TextView  
  71.             android:id="@+id/tv_numNote"  
  72.             android:layout_width="wrap_content"  
  73.             android:layout_height="wrap_content"  
  74.             android:layout_below="@id/tv_timeNote"  
  75.             android:layout_marginTop="10dp"  
  76.             android:text="庫存剩餘:"  
  77.             android:textColor="#162834"  
  78.             android:textSize="12sp" />  
  79.         <TextView  
  80.             android:id="@+id/tv_num"  
  81.             android:layout_width="wrap_content"  
  82.             android:layout_height="wrap_content"  
  83.             android:layout_alignBottom="@id/tv_numNote"  
  84.             android:layout_below="@id/tv_time"  
  85.             android:layout_toRightOf="@id/tv_numNote"  
  86.             android:gravity="bottom"  
  87.             android:text="888"  
  88.             android:textColor="#F09BED"  
  89.             android:textSize="15sp" />  
  90.         <ImageView  
  91.             android:id="@+id/img_icon"  
  92.             android:layout_width="50dp"  
  93.             android:layout_height="50dp"  
  94.             android:layout_alignParentRight="true"  
  95.             android:src="@drawable/red_packet" />  
  96.         <Button  
  97.             android:id="@+id/btn_buy"  
  98.             android:layout_width="wrap_content"  
  99.             android:layout_height="wrap_content"  
  100.             android:layout_below="@id/tv_num"  
  101.             android:padding="4dp"  
  102.             android:textSize="24sp"  
  103.             android:layout_alignParentBottom="true"  
  104.             android:layout_centerHorizontal="true"  
  105.             android:background="@drawable/select_btn"  
  106.             android:text="立即搶購" />  
  107.     </RelativeLayout>  
  108. </LinearLayout>  

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 看 Adapter 的代碼(總體都還是正常用法,本次用到的邏輯都有注釋):

  1. public class OneExpandAdapter extends BaseAdapter {  
  2.     private Context context;  
  3.     private ArrayList<HashMap<String, String>> list;  
  4.     private int currentItem = -1; //用于記錄點選的 Item 的 position,是控制 item 展開的核心  
  5.     public OneExpandAdapter(Context context,  
  6.             ArrayList<HashMap<String, String>> list) {  
  7.         super();  
  8.         this.context = context;  
  9.         this.list = list;  
  10.     }  
  11.     @Override  
  12.     public int getCount() {  
  13.         return list.size();  
  14.     }  
  15.     @Override  
  16.     public Object getItem(int position) {  
  17.         return list.get(position);  
  18.     }  
  19.     @Override  
  20.     public long getItemId(int position) {  
  21.         return position;  
  22.     }  
  23.     @Override  
  24.     public View getView(final int position, View convertView, ViewGroup parent) {  
  25.         ViewHolder holder = null;  
  26.         if (convertView == null) {  
  27.             convertView = LayoutInflater.from(context).inflate(  
  28.                     R.layout.item_2, parent, false);  
  29.             holder = new ViewHolder();  
  30.             holder.showArea = (LinearLayout) convertView.findViewById(R.id.layout_showArea);  
  31.             holder.tvPhoneType = (TextView) convertView  
  32.                     .findViewById(R.id.tv_phoneType);  
  33.             holder.tvDiscount = (TextView) convertView  
  34.                     .findViewById(R.id.tv_discount);  
  35.             holder.tvPrice = (TextView) convertView  
  36.                     .findViewById(R.id.tv_price);  
  37.             holder.tvTime = (TextView) convertView  
  38.                     .findViewById(R.id.tv_time);  
  39.             holder.tvNum = (TextView) convertView  
  40.                     .findViewById(R.id.tv_num);  
  41.             holder.btnBuy = (Button) convertView  
  42.                     .findViewById(R.id.btn_buy);  
  43.             holder.hideArea = (RelativeLayout) convertView.findViewById(R.id.layout_hideArea);  
  44.             convertView.setTag(holder);  
  45.         } else {  
  46.             holder = (ViewHolder) convertView.getTag();  
  47.         }  
  48.         HashMap<String, String> item = list.get(position);  
  49.         // 注意:我們在此給響應點選事件的區域(我的例子裡是 showArea 的線性布局)添加Tag,為了記錄點選的 position,我們正好用 position 設定 Tag  
  50.         holder.showArea.setTag(position);  
  51.         holder.tvPhoneType.setText(item.get("phoneType"));  
  52.         holder.tvDiscount.setText(item.get("discount"));  
  53.         holder.tvPrice.setText(item.get("price"));  
  54.         holder.tvTime.setText(item.get("time"));  
  55.         holder.tvNum.setText(item.get("num"));  
  56.         //根據 currentItem 記錄的點選位置來設定"對應Item"的可見性(在list依次加載清單資料時,每加載一個時都看一下是不是需改變可見性的那一條)  
  57.         if (currentItem == position) {  
  58.             holder.hideArea.setVisibility(View.VISIBLE);  
  59.         } else {  
  60.             holder.hideArea.setVisibility(View.GONE);  
  61.         }  
  62.         holder.showArea.setOnClickListener(new OnClickListener() {  
  63.             @Override  
  64.             public void onClick(View view) {  
  65.                 //用 currentItem 記錄點選位置  
  66.                 int tag = (Integer) view.getTag();  
  67.                 if (tag == currentItem) { //再次點選  
  68.                     currentItem = -1; //給 currentItem 一個無效值  
  69.                 } else {  
  70.                     currentItem = tag;  
  71.                 }  
  72.                 //通知adapter資料改變需要重新加載  
  73.                 notifyDataSetChanged(); //必須有的一步  
  74.             }  
  75.         });  
  76.         holder.tvPhoneType.setOnClickListener(new OnClickListener() {  
  77.             @Override  
  78.             public void onClick(View view) {  
  79.                 Toast.makeText(context, "hehe", Toast.LENGTH_SHORT).show();  
  80.             }  
  81.         });  
  82.         return convertView;  
  83.     }  
  84.     private static class ViewHolder {  
  85.         private LinearLayout showArea;  
  86.         private TextView tvPhoneType;  
  87.         private TextView tvDiscount;  
  88.         private TextView tvPrice;  
  89.         private TextView tvTime;  
  90.         private TextView tvNum;  
  91.         private Button btnBuy;  
  92.         private RelativeLayout hideArea;  
  93.     }  
  94. }  

我們隻是 給特定元件 setTag(int position),根據點選的 View 記錄下這個 position,在 getView() 中判斷目前加載 View 是 position 是不是和記錄的 position 相等來進行特定元件的可見性設定 即可。

        這裡我們需要明白:我們平時對 ListView 做的最多的操作就是 setOnItemClickListener,這個操作一般都是在 Activity 中進行的,此時響應區域是 Item 整體,不管你點選 Item 的哪個角落都會響應。而對于每個 Item 中子控件的事件監聽(差別于整個Item,比如說 Item 中的按鈕、輸入框等等)都是在擴充卡類中添加,此時隻有點選添加監聽的子控件區域才會響應,相當于每個 Item 中的該控件都添加了監聽。OnClick 的響應優先級:子控件(元控件)> 父布局(但是不像 onTouch 事件有 Boolean 傳回值那樣,OnClick 事件是沒有傳回值的,即是“阻斷式式響應”,不會再響應它所歸屬的上層控件)。

        就不一一的列代碼了,多項展開,表格展開的下載下傳位址:http://download.csdn.net/detail/zhanghuaiwang/9912624