Android RecyclerView 向上偏移解决、添加自定义分割线,瀑布流,ScrollView嵌套RecyclerView滑动卡顿

本文深入解析Android中的RecyclerView组件,探讨其相较于ListView和GridView的优势,包括更高效的数据展示、灵活的布局管理和动画效果。同时,文章提供了针对RecyclerView卡顿、滚动性能优化的方法,以及如何实现瀑布流、自定义分割线等高级功能。

 向上偏移解决

android:focusableInTouchMode="true"
android:focusable="true"
android:fillViewport="true"

 

卡顿解决方法

recyclerViewwg.setHasFixedSize(true);
recyclerViewwg.setNestedScrollingEnabled(false);

删除条目:

lists.remove(i); notifyItemRemoved(i); notifyDataSetChanged();

 mRecyclerview.invalidate();====mRecyAdapter.notifyDataSetChanged();

 

概述

RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。
据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。

那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

  • 你想要控制其显示的方式,请通过布局管理器LayoutManager
  • 你想要控制Item间的间隔(可绘制),请通过ItemDecoration
  • 你想要控制Item增删的动画,请通过ItemAnimator
  • 你想要控制点击、长按事件,请自己写(擦,这点尼玛。)

一.RecyclerView介绍

RecyclerView 是Android 5.0版本中新出现的东西,用来替代ListView和GridView的。

二.RecyclerView架构

RecyclerView使用布局管理器LayoutManager和适配器Adapter的适配器模式去实现架构,不关心数据的来源。耦合性非常的底,用户可以根据自己的用户界面去实现相应的效果

三.RecyclerView的优点

  • 1.RecyclerView内部已经强制使用VIewHolder,优化了对Item中View的复用。

  • 2.提供了一个较为灵活的布局管理类,LayoutManager,用来控制RecyclerView是线性展示还是垂直展示,以及可以设置成瀑布流。并且提供了ItemDecoration这个类,来灵活的让用户来设置分割线。

  • 3.用ItemAnimator可以对item进行布局的删减动画效果。

 

设置布局管理器:

1、竖向listview

rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

2、横向listview

rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));

3、竖向gridView

rv.setLayoutManager(new GridLayoutManager(this, 5));

4、横向gridview

rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
rv.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));

5、瀑布流

rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
rv.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL));

瀑布流实现效果

 

 实现方法

item类型设置

for (int a=0;a<8;a++){
    TuijianMainEntity tuijianEntity =new TuijianMainEntity();
    tuijianEntity.setUname("网吧"+a);
    if (a>0){
        if (iflong){
            tuijianEntity.setIflong(iflong);
            intlonglg++;
            if (intlonglg==2){
                iflong=!iflong;
                intlonglg=0;
            }
        }else {
            tuijianEntity.setIflong(iflong);
            intlonglg++;
            if (intlonglg==2){
                iflong=!iflong;
                intlonglg=0;
            }
        }

    }
    barEntityList.add(tuijianEntity);
}

设置左右间隙

if (position%2==0){
    holder.itemView.setPadding(12,28,12,0);

}else {
    holder.itemView.setPadding(12,28,12,0);
}

设置图片高度

        if (entityList.get(position).isIflong()){
            int h = (int)Math.floor(heightlg*4/7)-130;
            int igh = h-210;
//            setViewLayoutParams(holder.myli,h);
            setigLayoutParams(holder.myig,igh);
        }else {
            int h = (int)Math.floor(heightlg*3/7)-80;
            int igh = h-160;
//            setViewLayoutParams(holder.myli,h);
            setigLayoutParams(holder.myig,igh);
        }

item_layout 自适应高度wrap_content

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="@color/bg_list"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/myli"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:background="@drawable/kongwhitebg">

 

需在adapter随机设置高度

rvAdapter.setType(3);
private int type = 0;

public RvAdapter(Context context, List<Integer> datas) {
    this.context = context;
    this.datas = datas;
    for (int i : datas) {
        int height = (int) (Math.random() * 100 + 300);
        heights.add(height);
    }
}

public void setType(int type) {
    this.type = type;
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
    RecyclerView.LayoutParams layoutParams;
    if (type == 0) {
        layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    } else if (type == 1) {
        layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    } else {
        layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heights.get(position));
        layoutParams.setMargins(2, 2, 2, 2);
    }

设置Item增加、移除动画:

rv.setItemAnimator(new DefaultItemAnimator());

实现添加分割线:

1、添加默认分割线

//分割线
private RecyclerView.ItemDecoration itemDecoration;
        itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
//默认分割线
        mHistoryRecycle.addItemDecoration(itemDecoration);

2、添加自定义分割线

mHistoryRecycle.addItemDecoration(new RecyclerViewDivider(this, LinearLayoutManager.HORIZONTAL,
        15, R.color.video_btn_danmaku_control_color, 2, 0));

自定义类RecyclerViewDivider

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.baidu.api.Util;
import com.juejinchain.android.R;

/**
 * 作者:created by meixi
 * 邮箱:15913707499@163.com
 * 日期:2019/6/14 08
 */
public class RecyclerViewDivider extends RecyclerView.ItemDecoration {
    private Paint mPaint;
    private Drawable mDivider;
    private int mDividerSize = 2;//分割线高度,默认为1px
    private int mOffsetStart = 0;
    private int mOffsetEnd = 0;
    private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    /**
     * 默认分割线:高度为2px,颜色为灰色
     *
     * @param context
     * @param orientation 列表方向
     */
    private RecyclerViewDivider(Context context, int orientation) {
        if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
            throw new IllegalArgumentException("请输入正确的参数!");
        }
        mOrientation = orientation;

        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    /**
     * 自定义分割线
     *
     * @param context
     * @param orientation 列表方向
     * @param drawableId  分割线图片
     */
    public RecyclerViewDivider(Context context, int orientation, int drawableId) {
        this(context, orientation);
        mDivider = ContextCompat.getDrawable(context, drawableId);
        mDividerSize = mDivider.getIntrinsicHeight();
    }

    /**
     * 自定义分割线
     *
     * @param context
     * @param orientation  列表方向
     * @param dividerSize  分割线高度
     * @param dividerColor 分割线颜色
     */
    public RecyclerViewDivider(Context context, int orientation, int dividerSize, @ColorRes int dividerColor) {
        this(context, orientation);
        mDividerSize = dividerSize;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setColor(context.getResources().getColor(dividerColor));
        mPaint.setStyle(Paint.Style.FILL);
    }


    /**
     * 自定义分割线
     *
     * @param context       context
     * @param orientation   列表方向
     * @param dividerHeight 分割线高度
     * @param dividerColor  分割线颜色
     * @param offsetStart   起始偏移量
     * @param offsetEnd     结束偏移量
     */
    public RecyclerViewDivider(Context context, int orientation, int dividerHeight, @ColorRes int dividerColor, int offsetStart, int offsetEnd) {
        this(context, orientation);
        mDividerSize = dividerHeight;
        mOffsetStart = dip2px(context, offsetStart);
        mOffsetEnd = dip2px(context, offsetEnd);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (dividerColor == 0) {
            dividerColor = R.color.red_500;
        }
        mPaint.setColor(context.getResources().getColor(dividerColor));
        mPaint.setStyle(Paint.Style.FILL);
    }

    public static int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }


    //重写此方法,防止设置的波纹背景把分隔线覆盖掉。
    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        RecyclerView.ViewHolder childViewHolder = parent.getChildViewHolder(view);
        if (childViewHolder.getItemViewType() != 0) {
            outRect.set(0, 0, 0, 0);
            return;
        }
        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
            outRect.set(0, 0, 0, mDividerSize);
        } else {
            outRect.set(0, 0, mDividerSize, 0);
        }
    }

    //绘制分割线
    @Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        if (mOrientation == LinearLayoutManager.VERTICAL) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    //绘制横向 item 分割线
    private void drawHorizontal(Canvas canvas, RecyclerView parent) {
        final int left = parent.getPaddingLeft() + mOffsetStart;
        final int right = parent.getMeasuredWidth() - (parent.getPaddingRight() + mOffsetEnd);
        final int childSize = parent.getChildCount();
        for (int i = 0; i < childSize ; i++) {
            final View child = parent.getChildAt(i);

            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int top = child.getBottom() + layoutParams.bottomMargin;
            final int bottom = top + mDividerSize;
            if (mDivider != null) {
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }

    //绘制纵向 item 分割线
    private void drawVertical(Canvas canvas, RecyclerView parent) {
        final int top = parent.getPaddingTop() + mDividerSize;
        final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom() + mDividerSize;
        final int childSize = parent.getChildCount();
        for (int i = 0; i < childSize; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int left = child.getRight() + layoutParams.rightMargin;
            final int right = left + mDividerSize;
            if (mDivider != null) {
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值