Android RecyclerView(超简单)实现可展开列表——单项展开

来源:互联网 发布:pptv网络电视在线直播 编辑:程序博客网 时间:2024/06/06 04:39

        之前写过  Android -- RecyclerView(超简单)实现可展开列表  的一篇文章,通过增加、删除的方式来模拟实现展开、收起的功能,思路很简单,也比较实用,最近看到评论里有猿友提出只展开一行的需求,并且还有猿友跟着提问,索性就再专门写一篇。

        只展开一行,也就是说当有一行处于展开的情况下再点击另外一行,另外一行展开,原本展开的那一行收起。好了,需求明确了,那我们要如何实现呢?

        最简单的方法就是标记展开的item,将当前展开的item标记(也可以说是封装保存起来)。多说无用,上码:

        注意:此篇是在之前写过的那篇文章的基础上拓展的,以下代码为根据需求修改的代码,没看过原篇的建议先看这篇

       先看效果图:

       

代码改动不多,首先我们需要再定义一个类:

public class ItemData {    public DataBean dataBean;//数据类    public View view;//展开的item,一定要将view一起封装起来,否则会有问题的。    public DataBean getDataBean() {        return dataBean;    }    public void setDataBean(DataBean dataBean) {        this.dataBean = dataBean;    }    public View getView() {        return view;    }    public void setView(View view) {        this.view = view;    }}
封装

import java.util.ArrayList;import java.util.List;/** * Created by hbh on 2017/8/15. * 封装item 及 增删操作 */public class EncapsulationItem {    public static List<ItemData> lastBeanList = new ArrayList<>();    //将展开的item添加到list中    public static void addLastBeanData(ItemData beanData){        lastBeanList.add(beanData);    }    //清空list    public static void cleraListBeanData(){        lastBeanList.clear();    }}
这里用List作为容器。

import android.animation.ValueAnimator;import android.annotation.TargetApi;import android.content.Context;import android.os.Build;import android.view.View;import android.view.animation.DecelerateInterpolator;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import com.hbh.cl.expandrecyclerviewdemo.R;import com.hbh.cl.expandrecyclerviewdemo.model.DataBean;import com.hbh.cl.expandrecyclerviewdemo.util.ItemData;import com.hbh.cl.expandrecyclerviewdemo.util.EncapsulationItem;/** * Created by hbh on 2017/4/20. * 父布局ViewHolder */public class ParentViewHolder extends BaseViewHolder {    private Context mContext;    private View view;    private RelativeLayout containerLayout;    private TextView parentLeftView;    private TextView parentRightView;    private ImageView expand;    private View parentDashedView;    private ItemData itemData;    public ParentViewHolder(Context context, View itemView) {        super(itemView);        this.mContext = context;        this.view = itemView;    }    public void bindView(final DataBean dataBean, final int pos, final ItemClickListener listener){        containerLayout = (RelativeLayout) view.findViewById(R.id.container);        parentLeftView = (TextView) view.findViewById(R.id.parent_left_text);        parentRightView = (TextView) view.findViewById(R.id.parent_right_text);        expand = (ImageView) view.findViewById(R.id.expend);        parentDashedView = view.findViewById(R.id.parent_dashed_view);        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) expand                .getLayoutParams();        expand.setLayoutParams(params);        parentLeftView.setText(dataBean.getParentLeftTxt());        parentRightView.setText(dataBean.getParentRightTxt());        if (dataBean.isExpand()) {            expand.setRotation(90);            parentDashedView.setVisibility(View.INVISIBLE);        } else {            expand.setRotation(0);            parentDashedView.setVisibility(View.VISIBLE);        }        //父布局OnClick监听        containerLayout.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                if (listener != null) {                    itemData = new ItemData();                    if (EncapsulationItem.lastBeanList.size() > 0 && !EncapsulationItem.lastBeanList.get(0).getDataBean().getID().equals(dataBean.getID())) {                        //如果有展开的item,先关闭                        listener.onHideChildren(EncapsulationItem.lastBeanList.get(0).getDataBean());                        EncapsulationItem.lastBeanList.get(0).getView().findViewById(R.id.parent_dashed_view).setVisibility(View.VISIBLE);                        EncapsulationItem.lastBeanList.get(0).getDataBean().setExpand(false);                        rotationExpandIcon(90, 0, EncapsulationItem.lastBeanList.get(0).getView().findViewById(R.id.expend));                        EncapsulationItem.cleraListBeanData();//清空集合                    }                    if (dataBean.isExpand()) {                        listener.onHideChildren(dataBean);                        parentDashedView.setVisibility(View.VISIBLE);                        EncapsulationItem.cleraListBeanData();                        dataBean.setExpand(false);                        rotationExpandIcon(90, 0, expand);                    } else {                        listener.onExpandChildren(dataBean);                        itemData.setDataBean(dataBean);                        itemData.setView(view);                        EncapsulationItem.addLastBeanData(itemData);                        parentDashedView.setVisibility(View.INVISIBLE);                        dataBean.setExpand(true);                        rotationExpandIcon(0, 90, expand);                    }                }            }        });    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    private void rotationExpandIcon(float from, float to, final View view) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {            ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to);//属性动画            valueAnimator.setDuration(500);            valueAnimator.setInterpolator(new DecelerateInterpolator());            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator valueAnimator) {                    view.setRotation((Float) valueAnimator.getAnimatedValue());                }            });            valueAnimator.start();        }    }}
这段代码中主要就是改动了父布局OnClick监听那一块,当我们点击父布局展开的时候先判断有没有展开状态的item,如果有,则先关闭,并清空List。然后在后面是否展开的判断中对List操作,很简单,就是展开增加、收起清除,一看就明白。

最后建议把滚动监听给去掉,实则没什么卵用,还会因为RecyclerView的复用出现问题,当向上滚动时,底部会闪现当前展开的item,虽然不会出现什么问题。

import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import com.hbh.cl.expandrecyclerviewdemo.R;import com.hbh.cl.expandrecyclerviewdemo.model.DataBean;import java.util.List;/** * Created by hbh on 2017/4/20. * 适配器 */public class RecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {    private Context context;    private List<DataBean> dataBeanList;    private LayoutInflater mInflater;    private OnScrollListener mOnScrollListener;    public RecyclerAdapter(Context context, List<DataBean> dataBeanList) {        this.context = context;        this.dataBeanList = dataBeanList;        this.mInflater = LayoutInflater.from(context);    }    @Override    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = null;        switch (viewType){            case DataBean.PARENT_ITEM:                view = mInflater.inflate(R.layout.recycleview_item_parent, parent, false);                return new ParentViewHolder(context, view);            case DataBean.CHILD_ITEM:                view = mInflater.inflate(R.layout.recycleview_item_child, parent, false);                return new ChildViewHolder(context, view);            default:                view = mInflater.inflate(R.layout.recycleview_item_parent, parent, false);                return new ParentViewHolder(context, view);        }    }    /**     * 根据不同的类型绑定View     * @param holder     * @param position     */    @Override    public void onBindViewHolder(BaseViewHolder holder, int position) {        switch (getItemViewType(position)){            case DataBean.PARENT_ITEM:                ParentViewHolder parentViewHolder = (ParentViewHolder) holder;                parentViewHolder.bindView(dataBeanList.get(position), position, itemClickListener);                break;            case DataBean.CHILD_ITEM:                ChildViewHolder childViewHolder = (ChildViewHolder) holder;                childViewHolder.bindView(dataBeanList.get(position), position);                break;        }    }    @Override    public int getItemCount() {        return dataBeanList.size();    }    @Override    public int getItemViewType(int position) {        return dataBeanList.get(position).getType();    }    private ItemClickListener itemClickListener = new ItemClickListener() {        @Override        public void onExpandChildren(DataBean bean) {            int position = getCurrentPosition(bean.getID());//确定当前点击的item位置            DataBean children = getChildDataBean(bean);//获取要展示的子布局数据对象,注意区分onHideChildren方法中的getChildBean()。            if (children == null) {                return;            }            add(children, position + 1);//在当前的item下方插入            if (position == dataBeanList.size() - 2 && mOnScrollListener != null) { //如果点击的item为最后一个//                mOnScrollListener.scrollTo(position + 1);//向下滚动,使子布局能够完全展示            }        }        @Override        public void onHideChildren(DataBean bean) {            int position = getCurrentPosition(bean.getID());//确定当前点击的item位置            DataBean children = bean.getChildBean();//获取子布局对象            if (children == null) {                return;            }            remove(position + 1);//删除            if (mOnScrollListener != null) {//                mOnScrollListener.scrollTo(position);            }        }    };    /**     * 在父布局下方插入一条数据     * @param bean     * @param position     */    public void add(DataBean bean, int position) {        dataBeanList.add(position, bean);        notifyItemInserted(position);    }    /**     *移除子布局数据     * @param position     */    protected void remove(int position) {        dataBeanList.remove(position);        notifyItemRemoved(position);    }    /**     * 确定当前点击的item位置并返回     * @param uuid     * @return     */    protected int getCurrentPosition(String uuid) {        for (int i = 0; i < dataBeanList.size(); i++) {            if (uuid.equalsIgnoreCase(dataBeanList.get(i).getID())) {                return i;            }        }        return -1;    }    /**     * 封装子布局数据对象并返回     * 注意,此处只是重新封装一个DataBean对象,为了标注Type为子布局数据,进而展开,展示数据     * 要和onHideChildren方法里的getChildBean()区分开来     * @param bean     * @return     */    private DataBean getChildDataBean(DataBean bean){        DataBean child = new DataBean();        child.setType(1);        child.setParentLeftTxt(bean.getParentLeftTxt());        child.setParentRightTxt(bean.getParentRightTxt());        child.setChildLeftTxt(bean.getChildLeftTxt());        child.setChildRightTxt(bean.getChildRightTxt());        return child;    }    /**     * 滚动监听接口     */    public interface OnScrollListener{        void scrollTo(int pos);    }    public void setOnScrollListener(OnScrollListener onScrollListener){        this.mOnScrollListener = onScrollListener;    }}

好了,就那么多,改动很少,代码就不上传了,下载下来之前github上的代码,然后直接拷过去替换掉就可以了。

有问题,欢迎来砸。

收工。


阅读全文
1 0