美文网首页
拒绝RecyclerView嵌套RecyclerView,实现复

拒绝RecyclerView嵌套RecyclerView,实现复

作者: LemZ | 来源:发表于2019-01-23 19:17 被阅读0次

    原创内容,转载请注明出处:https://www.jianshu.com/p/3e71a15b11cc

    前言

    很尴尬,前段时间比较忙,加上自己又比较懒,很久没来逛逛了,现在有点时间,来记录一下。
    直入主题,相信做软件开发的朋友们,经常会遇到一些复杂列表的需求,比如电商类应用的购物车或者订单界面,需要列表显示商铺名称及对应商铺下的商品,如下图:


    购物车.png 订单.png

    很容易想到通过RecyclerView嵌套RecyclerView实现多级列表,但这样实现会引发很多问题,滑动卡顿,焦点冲突,我有遇到过反复滑动后,页面无法正常滑动至顶部,自动回到滑动前位置(ps:设置子recyclerView不抢占焦点,recyclerView.setFocusable(false) 可解决),所以遇到类似需求,尽量不要使用RecyclerView嵌套去实现,提升用户体验。

    处理思路

    既然RecyclerView嵌套RecylerView存在这么多问题,那我只用一个RecyclerView去实现可不可以?当然可以!
    一般碰到这种复杂列表,后台返回数据结构也会分为两层,就拿上图的订单界面举例,会返回一个订单数组,然后每个数组里面包含创建时间、订单状态、商品等字段,商品又是一个数组,包含每个商品的详细信息,我们获取到后台返回数据后,需要自己处理数据结构,将商品里的字段移到与创建时间字段平级,再通过recyclerView的加载多布局,实现显示效果。

    实现方式

    首先 定义一个数据处理类OrderDataHelper,专门用来修改数据结构,根据页面定义所需的数据模型,这里我分为头部信息、商品信息、底部金额信息,代码如下:

    /**
     * 描述:  订单数据处理帮助类
     * 作者:  LemZ
     * 创建时间:  2018-05-29 09:39
     */
    
    public class OrderDataHelper {
    
        /**
         * List<Object>有三种数据类型:
         * 1、OrderHeaderInfo 表示每个订单的头部信息(订单号、订单状态、店铺名称)
         * 2、orderProductInfo 表示订单中的商品
         * 3、OrderPayInfo 表示订单的支付信息(金额、订单状态)
         *
         * @param resultList
         * @return
         */
        public static List<Object> getDataAfterHandle(List<OrderListBean> resultList) {
    
            List<Object> dataList = new ArrayList<Object>();
            //遍历每一张大订单
            for (OrderListBean orderListBean : resultList) {
                //订单编号 订单状态
                OrderHeaderInfo orderHeadInfo = new OrderHeaderInfo();
                orderHeadInfo.setOrderCode(orderListBean.getOrderCode());
                orderHeadInfo.setOrderStatus(orderListBean.getOrderStatus());
                orderHeadInfo.setId(orderListBean.getId());
                orderHeadInfo.setCreateTime(orderListBean.getCreateTime());
    
                List<OrderProductInfo> orderProductList;
                //订单商品
                orderProductList = orderListBean.getOrderProducts();
    
                //订单支付的金额和邮费金额
                OrderPayInfo orderPayInfo = new OrderPayInfo();
                orderPayInfo.setPostageAmount(orderListBean.getPostageAmount());
                orderPayInfo.setTotalAmount(orderListBean.getTotalAmount());
                orderPayInfo.setId(orderListBean.getId());
                orderPayInfo.setGoodsCount(orderListBean.getOrderProducts().size());
         
                dataList.add(orderHeadInfo);
                if(orderProductList != null){
                     for(int i = 0; i < orderProductList.size(); i++){
                          dataList.add(orderProductList.get(i));
                     }
                }
                dataList.add(orderPayInfo);
            }
            return dataList;
        }
    }
    
    

    ,将处理后数组 赋予适配器,刷新显示界面

    dataList = OrderDataHelper.getDataAfterHandle(data.getList());  //定义的全局List<Object> dataList
    mAdapter.refresh(dataList,isLoadMore);
    

    适配器添加多布局显示处理:

    /**
     * 描述:
     * 作者:  LemZ
     * 创建时间:  2018-05-28 17:01
     */
    
    public class OrderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    
        private int ITEM_HEADER = 1, ITEM_CONTENT = 2, ITEM_FOOTER = 3;
        private List<Object> dataList;
        private Context context;
    
        public final void refresh(List<Object> data,boolean isLoadMore) {
            if (!isLoadMore)
                dataList.clear();
            dataList.addAll(data);
            notifyDataSetChanged();
        }
    
        public OrderAdapter(Context context,List<Object> list) {
            this.context = context;
            this.dataList = list != null ? list : new ArrayList<>();
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view;
            if (viewType == ITEM_HEADER){
                view = LayoutInflater.from(context).inflate(R.layout.item_order_header, parent, false);
                return new HeadViewHolder(view);
            }else if (viewType == ITEM_CONTENT){
                view = LayoutInflater.from(context).inflate(R.layout.item_order_content, parent, false);
                return new ContentViewHolder(view);
            }else if(viewType == ITEM_FOOTER){
                view = LayoutInflater.from(context).inflate(R.layout.item_order_footer, parent, false);
                return new FootViewHolder(view);
            }
            return null;
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
            /**头部*/
            if (getItemViewType(position) == ITEM_HEADER) {
                final HeadViewHolder headerHolder = (HeadViewHolder) viewHolder;
                OrderHeaderInfo orderHeadInfo = (OrderHeaderInfo)dataList.get(position);
    
                showText(headerHolder.tv_order_create_time,orderHeadInfo.getCreateTime())
                showText(headerHolder.tv_order_status,orderHeadInfo.getOrderStatus())
            }
            /**商品信息*/
            else if (getItemViewType(position) == ITEM_CONTENT) {
                final ContentViewHolder contentHolder = (ContentViewHolder) viewHolder;
                final OrderProductInfo orderProductInfo= (OrderProductInfo)dataList.get(position);
    
                showText(contentHolder.tv_good_name,orderProductInfo.getProductName());
    
                contentHolder.tv_product_price.setText("¥"+NumberUitls.kp2Num(orderProductInfo.getProductPrice()));
                contentHolder.tv_product_count.setText("x"+orderProductInfo.getProductCount());
    
                showText(contentHolder.tv_good_spec,orderProductInfo.getProductSpec());
                
                Glide.with(context).load(orderProductInfo.getProductPic())
                        .dontAnimate()
                        .error(R.mipmap.ic_default)
                        .placeholder(R.mipmap.ic_default)
                        .into(contentHolder.iv_good);
            }
    
            /**尾部*/
            else if (getItemViewType(position) == ITEM_FOOTER) {
                final FootViewHolder footHolder = (FootViewHolder) viewHolder;
                OrderPayInfo orderPayInfo = (OrderPayInfo)dataList.get(position);
    
                footHolder.tv_postage_amount.setText("¥"+NumberUitls.kp2Num(orderPayInfo.getPostageAmount()));
                footHolder.tv_order_amount.setText("¥"+NumberUitls.kp2Num(orderPayInfo.getTotalAmount()));
                footHolder.linear_fold_status.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        changeFold(orderPayInfo,footHolder,footHolder.tv_fold_status,footHolder.iv_arrow);
                    }
                });
                footHolder.tv_goods_num.setText("共"+orderPayInfo.getGoodsCount()+"件商品,");
    
            }
    
        }
    
        @Override
        public int getItemCount() {
            return dataList == null?0:dataList.size();
        }
    
        @Override
        public int getItemViewType(int position) {
            if (dataList.get(position) instanceof OrderHeaderInfo){
                return ITEM_HEADER;
            }else if (dataList.get(position) instanceof orderProductInfo){
                return ITEM_CONTENT;
            }else if(dataList.get(position) instanceof OrderPayInfo){
                return ITEM_FOOTER;
            }
            return ITEM_CONTENT;
        }
    
        public class HeadViewHolder extends RecyclerView.ViewHolder{
            TextView tv_order_create_time;
            TextView tv_order_status;
    
            public HeadViewHolder(View itemView) {
                super(itemView);
                tv_order_create_time = (TextView)itemView.findViewById(R.id.tv_order_create_time);
                tv_order_status = (TextView)itemView.findViewById(R.id.tv_order_status);
            }
        }
    
        public class ContentViewHolder extends RecyclerView.ViewHolder{
            TextView tv_good_name;
            TextView tv_product_price;
            TextView tv_product_count;
            ImageView iv_good;
            TextView tv_good_spec;
    
            public ContentViewHolder(View itemView) {
                super(itemView);
                tv_good_name = (TextView)itemView.findViewById(R.id.tv_good_name);
                tv_product_price = (TextView)itemView.findViewById(R.id.tv_product_price);
                tv_product_count = (TextView)itemView.findViewById(R.id.tv_product_count);
                iv_good = (ImageView)itemView.findViewById(R.id.iv_good);
                tv_good_spec = (TextView)itemView.findViewById(R.id.tv_good_spec);
            }
        }
    
        public class FootViewHolder extends RecyclerView.ViewHolder{
            LinearLayout linear_fold_status;
            TextView tv_fold_status;
            TextView tv_postage_amount;
            TextView tv_goods_num;
            TextView tv_order_amount;
            ImageView iv_arrow;
    
            public FootViewHolder(View itemView) {
                super(itemView);
                linear_fold_status = (LinearLayout)itemView.findViewById(R.id.linear_fold_status);
                tv_fold_status = (TextView)itemView.findViewById(R.id.tv_fold_status);
                tv_postage_amount = (TextView)itemView.findViewById(R.id.tv_postage_amount);
                tv_goods_num = (TextView)itemView.findViewById(R.id.tv_goods_num);
                tv_order_amount = (TextView)itemView.findViewById(R.id.tv_order_amount);
                iv_arrow = (ImageView)itemView.findViewById(R.id.iv_arrow);
            }
        }
    
    /**
    字符串为空判断
    */
    private void showText(TextView tv, String str){
            if(!TextUtil.isEmpty(str)){
                  tv.setText(str);
            }else {
                  tv.setText("");
            }
        }
    
    }
    

    总结

    这样就实现了一个RecyclerView显示复杂布局的效果,试试?滑动流畅得飞起!
    (原本计划再写一篇ScrollView嵌套,想想还是简单分享下思路好了。很多朋友可能会选择使用NestedScrollView嵌套RecyclerView,设置recyclerView.setNestedScrollingEnabled(false);避免卡顿,这样依然会存在问题,如RecyclerView自动获取焦点,进入页面只显示RecyclerView部分。通常遇到这种自定义布局与列表共存的界面,我会采用RecyclerView添加header、footer布局的方式去实现,滑动更流畅!在这里也推荐一个非常强大的适配器框架https://www.jianshu.com/p/b343fcff51b0/,轻松实现添加头尾部)
    本文如有不足之处,欢迎各位指出,我会及时更正 ^ ^

    相关文章

      网友评论

          本文标题:拒绝RecyclerView嵌套RecyclerView,实现复

          本文链接:https://www.haomeiwen.com/subject/lrendqtx.html