Use of RecyclerView

Explanation: The comments in the following code are for illustration only and are not needed in practice.

The appearance of this control of RecyclerView is very convenient for daily development. I think it can directly replace listview and gridview, and it is very convenient to write waterfall flow.

In fact, the use of RecyclerView distinguishes its arrangement by the layout manager, which are:

LinearLayoutManager: Linear layout manager

StaggeredGridLayoutManager: Staggered grid layout manager (a way of waterfall flow)

GridLayoutManager: grid layout manager

First, let's introduce the way of waterfall flow:Enter image description

As can be seen from the above figure, each item contains pictures and text, and the pictures are loaded asynchronously, so the problem arises. If the code is written according to the conventional process, the pictures will appear in various ways when sliding. problems, such as sliding and flickering, picture dislocation, and top picture movement. The code to solve the problem by finding is as follows:

            StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,                 StaggeredGridLayoutManager.VERTICAL);
            //RecyclerView滑动过程中不断请求layout的Request,不断调整item见的间隙,并且是在item尺寸显示前预处理,因此解决RecyclerView滑动到顶部时仍会出现移动问题
            layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

            RecyclerView  scene_recyclerview = (RecyclerView) view.findViewById(R.id.scene_recyclerview);
            scene_recyclerview.addItemDecoration(new RecycleViewItemDecoration(20));
            scene_recyclerview.setLayoutManager(layoutManager);
            scene_recyclerview.setItemViewCacheSize(0);//去掉缓存
            findSceneList = new ArrayList<>()
            SceneRecyclerViewAdapter  recyclerViewAdapter = new SceneRecyclerViewAdapter(getContext(), findSceneList);
            scene_recyclerview.setAdapter(recyclerViewAdapter);
            scene_recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {

                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
//                    网上说的这种方式是没有效果的,所以注释不用
//                    layoutManager.invalidateSpanAssignments();//避免顶部出现空白区域,其实就是重新绘制了一遍
                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    /**
                      *通过下面的方式,判断是否滑动到顶部还是滑动到底部的监听
                       */
                    StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
                    int[] firstVisibleItem = null;
                    firstVisibleItem = staggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItem);
                    if (firstVisibleItem != null && (firstVisibleItem[0] == 0 || firstVisibleItem[0] == 1)) {
                        //表明此时滑动到顶部了
                    }

                    int[] lastVisibleItem = null;
                    lastVisibleItem = staggeredGridLayoutManager.findLastVisibleItemPositions(lastVisibleItem);
                    if (lastVisibleItem != null && (lastVisibleItem[0] == findSceneList.size() || lastVisibleItem[0] == findSceneList.size() - 1)
                            && (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())) {//这种方式表明只有滑动到已有数据的最底部才开始加载数据
                        //表明此时滑动到底部了
                        pageIndex++;
                        getSceneList();
                    }

//                    if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange()) {
//                        //这种方式会造成第一次打开所有场景页面数据请求两遍
//                        //滑动到底部
//                        pageIndex++;
//                        getSceneList();
//                    }
                }
            });

RecycleViewItemDecoration This class is used to adjust the spacing of items in the waterfall flow.

/**
 * RecyclerView的item的间距
 * 设置为2列,如果是3列或者其它列,那么左右值不同
 */

public class RecycleViewItemDecoration extends RecyclerView.ItemDecoration {
    private int space = 0;
    private int pos;

    public RecycleViewItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        pos = parent.getChildAdapterPosition(view);//该View在整个RecyclerView中的位置
        if (parent.getChildAdapterPosition(view) == 0 || parent.getChildAdapterPosition(view) == 1) {
            outRect.top = space;
        }
        outRect.bottom = space;
        outRect.left = space;
        outRect.right = space;
        //两列的左边一列
//        if (pos % 2 == 0) {
//            outRect.left = space;
//            outRect.right = space/2;
//        }
//        //两列的右边一列
//        if (pos % 2 == 1) {
//            outRect.left = space/2;
//            outRect.right = space/10;
//        }
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        c.drawColor(ContextCompat.getColor(parent.getContext(), R.color.base_bg_color));//绘制item间隔的颜色
    }
}

The click event that monitors the item image is placed in the adapter SceneRecyclerViewAdapter.

public class SceneRecyclerViewAdapter extends RecyclerView.Adapter<SceneRecyclerViewAdapter.MyViewHolder> {
    private Context context;
    private ArrayList<FindSceneBean> findSceneList;//数据源
    private ImageLoad imageLoad;
    private int itemWidth;

    public SceneRecyclerViewAdapter(Context context, ArrayList<FindSceneBean> findSceneList) {
        this.context = context;
        this.findSceneList = findSceneList;
        imageLoad = new ImageLoad(context);
        itemWidth = (Util.getScreenWidth(context) - 62)/2;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.scene_recyclerview_item, null);
        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
//这里是重新设置一下图片的宽度,
        holder.goodsImage.measure(0, 0);
//        double ratio = (itemWidth * 1.0)/holder.goodsImage.getMeasuredWidth();
        ViewGroup.LayoutParams params = holder.goodsImage.getLayoutParams();
        params.width = itemWidth;
//        params.height = (int) (holder.goodsImage.getMeasuredHeight() * ratio);
        holder.goodsImage.setLayoutParams(params);

        //这里要先添加一下默认图片
        holder.goodsImage.setImageDrawable(context.getDrawable(R.drawable.home_page_vice_pic));
        if (!Util.isTextNull(findSceneList.get(position).OrginImageUrl)) {
            imageLoad.loadImage(holder.goodsImage, findSceneList.get(position).OrginImageUrl);
        }
        holder.title.setText(findSceneList.get(position).Description);
        holder.falNumTv.setText(findSceneList.get(position).LikeNum + "");
        final FindSceneBean findSceneBean = findSceneList.get(position);
        if (findSceneBean != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //点击监听
                }
            });
        }
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public int getItemCount() {
        return findSceneList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        TextView title;//标题
        TextView falNumTv;//收藏数
        ImageView goodsImage;//商品图片
        ImageView falImage;//收藏数的图标

        public MyViewHolder(View itemView) {
            super(itemView);
            title = (TextView) itemView.findViewById(R.id.scene_item_title);
            falNumTv = (TextView) itemView.findViewById(R.id.scene_item_falNumTv);
            goodsImage = (ImageView) itemView.findViewById(R.id.scene_item_goodsImage);
            falImage = (ImageView) itemView.findViewById(R.id.scene_item_falImage);
        }
    }
}

The above is the way RecyclerView uses to write waterfall flow, and then the way RecyclerView uses to write similar gridview.

Enter image descriptionFirst of all, it should be noted that there is no problem of loading as many pictures in the waterfall flow when writing the table layout, so there is no need to adjust the picture loading.

            GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
            //RecyclerView滑动过程中不断请求layout的Request,不断调整item见的间隙,并且是在item尺寸显示前预处理,因此解决RecyclerView滑动到顶部时仍会出现移动问题
//            layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

            commodity_gridview = (RecyclerView) view.findViewById(R.id.commodity_gridview);
            commodity_gridview.addItemDecoration(new RecycleViewItemDecoration(20));
            commodity_gridview.setLayoutManager(layoutManager);
            commodity_gridview.setItemViewCacheSize(0);
            commoGridViewRequestList = new ArrayList<>();
            commoGridViewList = new ArrayList<>();
            commoGridViewAdapter = new CommoGridViewAdapter(getContext(), commoGridViewList);
            commodity_gridview.setAdapter(commoGridViewAdapter);
            commodity_gridview.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    GridLayoutManager gridLayoutManager = (GridLayoutManager) recyclerView.getLayoutManager();
                    int firstVisibleItem = gridLayoutManager.findFirstVisibleItemPosition();
                    if (firstVisibleItem == 0) {
                        //表明此时滑动到顶部了
                    }

                    int lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition();
                    if ((lastVisibleItem == commoGridViewList.size() - 1)
                            && (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())) {
                        //表明此时滑动到底部了
                        pageIndex++;
                        getGoodsList();
                    }
                }
            });

Code for the adapter CommoGridViewAdapter:

public class CommoGridViewAdapter extends RecyclerView.Adapter<CommoGridViewAdapter.MyHolder> {
    private Context context;
    private ArrayList<CommoGridViewBean> commoGridViewList;
    private ImageLoad imageLoad;

    public CommoGridViewAdapter(Context context, ArrayList<CommoGridViewBean> commoGridViewList) {
        this.context = context;
        this.commoGridViewList = commoGridViewList;
        imageLoad = new ImageLoad(context);
    }

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.recommend_good_adapter_layout, null);
        view.setBackgroundColor(ContextCompat.getColor(context, R.color.white));
        MyHolder myViewHolder = new MyHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyHolder holder, int position) {
        try {
            final CommoGridViewBean commoGridViewBean = commoGridViewList.get(position);
            if (commoGridViewBean != null) {
                if (!Util.isTextNull(commoGridViewBean.ThumbImageUrl)) {
                    imageLoad.loadImage(holder.desc_dispaly, commoGridViewBean.ThumbImageUrl);
                }
                holder.tv_name.setText(commoGridViewBean.Title);
                holder.tv_price.setText(Util.getNewRMBSymbolPrice(commoGridViewBean.Price));

                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //点击事件
                    }
                });
            }
        } catch (Exception e) {
            LogUtil.e(getClass(), "onBindViewHolder", e);
        }
    }

    @Override
    public int getItemCount() {
        return commoGridViewList.size();
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    class MyHolder extends RecyclerView.ViewHolder {
        ImageView desc_dispaly;
        TextView tv_name;
        TextView tv_price;

        public MyHolder(View itemView) {
            super(itemView);
            desc_dispaly = (ImageView) itemView.findViewById(R.id.recomm_img);
            tv_name = (TextView) itemView.findViewById(R.id.recomm_title);
            tv_price = (TextView) itemView.findViewById(R.id.recomm_price);
        }
    }
}

Personal experience: RecyclerView is very convenient and can achieve a good display effect. However, it is easy to cause problems when loading pictures asynchronously, and specific problems should be analyzed in detail. The spacing of items needs to be rewritten, but the degree of availability has also improved, which can be said to have advantages and disadvantages.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324467246&siteId=291194637