您的位置:首页 > 移动开发 > Android开发

Android ListView点击Item展开隐藏项,单个展开,多个展开

2017-07-27 15:14 453 查看
版权声明:^_^ 尊重原创,共享知识,转载请注明"_程序猿大人_"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 用到的布局样式:

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

version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

20000

    android:layout_width="match_parent"  

    android:layout_height="match_parent"  

    android:background="@drawable/shape2"  

    android:orientation="vertical" >  

  

    <LinearLayout  

        android:id="@+id/layout_showArea"  

        android:layout_width="match_parent"  

        android:layout_height="wrap_content"  

        android:orientation="horizontal"  

        android:padding="10dp" >  

  

        <TextView  

            android:id="@+id/tv_phoneType"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:text="HTC M8"  

            android:textColor="#162834"  

            android:textSize="25sp" />  

  

        <TextView  

            android:id="@+id/tv_discount"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_marginLeft="12dp"  

            android:text="9"  

            android:textColor="#F75252"  

            android:textSize="15sp" />  

  

        <TextView  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:text="折"  

            android:textColor="#F75252"  

            android:textSize="15sp" />  

  

        <TextView  

            android:id="@+id/tv_price"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_marginLeft="100dp"  

            android:text="2000"  

            android:textColor="#F75252"  

            android:textSize="20sp" />  

  

        <TextView  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:text="¥"  

            android:textColor="#767171"  

            android:textSize="15sp" />  

    </LinearLayout>  

  

    <RelativeLayout  

        android:id="@+id/layout_hideArea"  

        android:layout_width="match_parent"  

        android:layout_height="wrap_content"  

        android:padding="10dp" >  

  

        <TextView  

            android:id="@+id/tv_timeNote"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_alignBottom="@+id/tv_time"  

            android:text="活动截止时间:"  

            android:textColor="#162834"  

            android:textSize="12sp" />  

  

        <TextView  

            android:id="@+id/tv_time"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_toRightOf="@id/tv_timeNote"  

            android:text="2016.02.10"  

            android:textColor="#F09BED"  

            android:textSize="15sp" />  

  

        <TextView  

            android:id="@+id/tv_numNote"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_below="@id/tv_timeNote"  

            android:layout_marginTop="10dp"  

            android:text="库存剩余:"  

            android:textColor="#162834"  

            android:textSize="12sp" />  

  

        <TextView  

            android:id="@+id/tv_num"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_alignBottom="@id/tv_numNote"  

            android:layout_below="@id/tv_time"  

            android:layout_toRightOf="@id/tv_numNote"  

            android:gravity="bottom"  

            android:text="888"  

            android:textColor="#F09BED"  

            android:textSize="15sp" />  

  

        <ImageView  

            android:id="@+id/img_icon"  

            android:layout_width="50dp"  

            android:layout_height="50dp"  

            android:layout_alignParentRight="true"  

            android:src="@drawable/red_packet" />  

  

        <Button  

            android:id="@+id/btn_buy"  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_below="@id/tv_num"  

            android:padding="4dp"  

            android:textSize="24sp"  

            android:layout_alignParentBottom="true"  

            android:layout_centerHorizontal="true"  

            android:background="@drawable/select_btn"  

            android:text="立即抢购" />  

    </RelativeLayout>  

</LinearLayout>  

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

 看 Adapter 的代码(总体都还是常规用法,本次用到的逻辑都有注释):

/** 

 * 点击item展开隐藏部分,再次点击收起 

 * 只可展开一条记录 

 *  

 * @author WangJ 

 * @date 2016.01.31 

 */  

public class OneExpandAdapter extends BaseAdapter {  

    private Context context;  

    private ArrayList<HashMap<String, String>> list;  

    private int currentItem = -1; //用于记录点击的 Item 的 position,是控制 item 展开的核心  

  

    public OneExpandAdapter(Context context,  

            ArrayList<HashMap<String, String>> list) {  

        super();  

        this.context = context;  

        this.list = list;  

    }  

  

    @Override  

    public int getCount() {  

        return list.size();  

    }  

  

    @Override  

    public Object getItem(int position) {  

        return list.get(position);  

    }  

  

    @Override  

    public long getItemId(int position) {  

        return position;  

    }  

  

    @Override  

    public View getView(final int position, View convertView, ViewGroup parent) {  

        ViewHolder holder = null;  

        if (convertView == null) {  

            convertView = LayoutInflater.from(context).inflate(  

                    R.layout.item_2, parent, false);  

            holder = new ViewHolder();  

            holder.showArea = (LinearLayout) convertView.findViewById(R.id.layout_showArea);  

            holder.tvPhoneType = (TextView) convertView  

                    .findViewById(R.id.tv_phoneType);  

            holder.tvDiscount = (TextView) convertView  

                    .findViewById(R.id.tv_discount);  

            holder.tvPrice = (TextView) convertView  

                    .findViewById(R.id.tv_price);  

            holder.tvTime = (TextView) convertView  

                    .findViewById(R.id.tv_time);  

            holder.tvNum = (TextView) convertView  

                    .findViewById(R.id.tv_num);  

            holder.btnBuy = (Button) convertView  

                    .findViewById(R.id.btn_buy);  

            holder.hideArea = (RelativeLayout) convertView.findViewById(R.id.layout_hideArea);  

              

            convertView.setTag(holder);  

        } else {  

            holder = (ViewHolder) convertView.getTag();  

        }  

  

        HashMap<String, String> item = list.get(position);  

          

        // 注意:我们在此给响应点击事件的区域(我的例子里是 showArea 的线性布局)添加Tag,为了记录点击的 position,我们正好用 position 设置 Tag  

        holder.showArea.setTag(position);  

          

        holder.tvPhoneType.setText(item.get("phoneType"));  

        holder.tvDiscount.setText(item.get("discount"));  

        holder.tvPrice.setText(item.get("price"));  

        holder.tvTime.setText(item.get("time"));  

        holder.tvNum.setText(item.get("num"));  

  

        //根据 currentItem 记录的点击位置来设置"对应Item"的可见性(在list依次加载列表数据时,每加载一个时都看一下是不是需改变可见性的那一条)  

        if (currentItem == position) {  

            holder.hideArea.setVisibility(View.VISIBLE);  

        } else {  

            holder.hideArea.setVisibility(View.GONE);  

        }  

  

        holder.showArea.setOnClickListener(new OnClickListener() {  

  

            @Override  

            public void onClick(View view) {  

                //用 currentItem 记录点击位置  

                int tag = (Integer) view.getTag();  

                if (tag == currentItem) { //再次点击  

                    currentItem = -1; //给 currentItem 一个无效值  

                } else {  

                    currentItem = tag;  

                }  

                //通知adapter数据改变需要重新加载  

                notifyDataSetChanged(); //必须有的一步  

            }  

        });  

        holder.tvPhoneType.setOnClickListener(new OnClickListener() {  

              

            @Override  

            public void onClick(View view) {  

                Toast.makeText(context, "hehe", Toast.LENGTH_SHORT).show();  

            }  

        });  

        return convertView;  

    }  

  

    private static class ViewHolder {  

        private LinearLayout showArea;  

  

        private TextView tvPhoneType;  

        private TextView tvDiscount;  

        private TextView tvPrice;  

        private TextView tvTime;  

        private TextView tvNum;  

        private Button btnBuy;  

  

        private RelativeLayout hideArea;  

    }  

}  
我们只是给特定组件 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息