天天看點

Android UI 之 RecyclerView 基礎用法

基礎用法

添加依賴

// RecyclerAdapter
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
    // glide
    implementation 'com.github.bumptech.glide:glide:4.8.0';
           
  1. 效果圖
    Android UI 之 RecyclerView 基礎用法
  2. 布局檔案

    activity_fruit.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.FruitActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_fruit"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
           

item_fruit

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <ImageView
        android:id="@+id/iv_fruit"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_gravity="center_vertical"
        android:src="@mipmap/ic_apple"/>

    <TextView
        android:id="@+id/tv_fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"/>

</LinearLayout>
           
  1. 分隔線
public class RecyclerViewDivider extends RecyclerView.ItemDecoration {
    private static final String TAG = "RecyclerViewDivider";

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private static final int DIVIDER_COLOR = Color.parseColor("#efefef");

    private Paint mPaint;
    private Drawable mDivider;
    private int mDividerHeight = 1;

    //The direction of the list:LinearLayoutManager.VERTICAL or LinearLayoutManager.HORIZONTAL
    private int mOrientation;
    private int mLeftOffset;
    private int mRightOffset;
    private boolean mIsShowLastDivider;
    private int mDividerColor;
    private int mStart = 0;
    private int mEnd = 0;


    public RecyclerViewDivider(Context context) {
        this(context, LinearLayoutManager.VERTICAL, 1, DIVIDER_COLOR);
    }

    public RecyclerViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) {
        this(context, orientation);

        mDividerColor = dividerColor;
        mDividerHeight = dividerHeight;

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(dividerColor);
        mPaint.setStyle(Paint.Style.FILL);
    }

    public RecyclerViewDivider(Context context, int orientation) {
        if (orientation != LinearLayoutManager.VERTICAL
                && orientation != LinearLayoutManager.HORIZONTAL) {
            throw new IllegalArgumentException("Please input right parameter");
        }

        mOrientation = orientation;

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

    public RecyclerViewDivider(Context context, int orientation, int drawableId) {
        this(context, orientation);

        mDivider = ContextCompat.getDrawable(context, drawableId);
        mDividerHeight = mDivider.getIntrinsicHeight();
    }

    /**
     * Set the offset of the horizontal split line
     *
     * @param leftOffset
     * @param rightOffset
     */
    public void setHorizontaloffset(int leftOffset, int rightOffset) {
        mLeftOffset = leftOffset;
        mRightOffset = rightOffset;
    }

    /**
     * Set whether to display the last split line, not displayed by default
     *
     * @param isShowLastDivider
     */
    public void setShowLastDivider(boolean isShowLastDivider) {
        mIsShowLastDivider = isShowLastDivider;
    }

    /**
     * split line display range
     * <p>
     * fisrt = 0 + start;
     * last = childSize - 1 - end - mIsShowLastDivider ? 0 : 1
     *
     * @param start
     * @param end
     */
    public void setDividerStartAndEndOffsetCount(int start, int end) {
        mStart = start;
        mEnd = end;
    }

    public void setDividerHeight(int dividerHeight) {
        mDividerHeight = dividerHeight;
    }

    public void setDividerColor(int dividerColor) {
        mDividerColor = dividerColor;
        if (mPaint != null) {
            mPaint.setColor(mDividerColor);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.set(0, 0, 0, mDividerHeight);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (mOrientation == LinearLayoutManager.VERTICAL) {
            drawVerticalDivider(c, parent);
        } else {
            drawHorizontalDivider(c, parent);
        }
    }

    //Draw item dividing line
    private void drawVerticalDivider(Canvas canvas, RecyclerView parent) {
        // mLeftOffset 為自己設定的左邊偏移量
        final int left = parent.getPaddingLeft() + mLeftOffset;
        // mRightOffset 為設定的右邊偏移量
        final int right = parent.getMeasuredWidth() - parent.getPaddingRight() + mRightOffset;
        final int childSize = parent.getChildCount();

        if (childSize <= 0) {
            return;
        }

        // 從第一個 item 開始繪制
        int first = mStart;
        // 到第幾個 item 繪制結束
        int last = childSize - mEnd - (mIsShowLastDivider ? 0 : 1);
        Log.d(TAG, " last = " + last + " childSize =" + childSize + "left = " + left);

        if (last <= 0) {
            return;
        }

        for (int i = first; i < last; i++) {
            drawableVerticalDivider(canvas, parent, left, right, i, mDividerHeight);
        }

    }

    private void drawableVerticalDivider(Canvas canvas, RecyclerView parent, int left, int right, int i, int dividerHeight) {
        final View child = parent.getChildAt(i);

        if (child == null) {
            return;
        }

        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
        final int top = child.getBottom() + layoutParams.bottomMargin;
        final int bottom = top + dividerHeight;

        // 适配 drawable
        if (mDivider != null) {
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(canvas);
        }

        // 适配分割線
        if (mPaint != null) {
            canvas.drawRect(left, top, right, bottom, mPaint);
        }
    }

    // Draw vertical item dividing line
    private void drawHorizontalDivider(Canvas canvas, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
        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 + mDividerHeight;

            if (mDivider != null) {
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }

            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }
}
           
  1. 擴充卡
public class FruitAdapter extends BaseQuickAdapter<FruitBean, BaseViewHolder> {

    public FruitAdapter(int layoutResId, @Nullable List<FruitBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, FruitBean item) {
        ImageView image = helper.getView(R.id.iv_fruit);
        Glide.with(MyApp.getAppContext())
                .load(item.getIconId())
                .into(image);

        helper.setText(R.id.tv_fruit_name,item.getName());
    }
}
           
  1. 邏輯代碼
public class FruitActivity extends BaseActivity {
    @BindView(R.id.rv_fruit)
    RecyclerView mRecyclerView;

    private FruitAdapter mAdapter;

    @Override
    public int getLayoutId() {
        return R.layout.activity_fruit;
    }

    @Override
    public void initView() {
        mAdapter = new FruitAdapter(R.layout.item_fruit,getData());
        mAdapter.openLoadAnimation();
        RecyclerViewDivider recyclerViewDivider = new RecyclerViewDivider(this);
        recyclerViewDivider.setHorizontaloffset(DensityUtil.dip2px(this, 15), 0);
        recyclerViewDivider.setDividerColor(Color.GRAY);
        recyclerViewDivider.setDividerHeight(DensityUtil.dip2px(this, 0.5f));
        mRecyclerView.addItemDecoration(recyclerViewDivider);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(mAdapter);
    }

    private List<FruitBean> getData() {
        return Arrays.asList(new FruitBean("apple",R.mipmap.ic_apple),
                new FruitBean("banana",R.mipmap.ic_banana),
                new FruitBean("cherry",R.mipmap.ic_cherry),
                new FruitBean("grape",R.mipmap.ic_grape),
                new FruitBean("mango",R.mipmap.ic_mango),
                new FruitBean("orange",R.mipmap.ic_orange),
                new FruitBean("pear",R.mipmap.ic_pear),
                new FruitBean("pineapple",R.mipmap.ic_pineapple),
                new FruitBean("watermelon",R.mipmap.ic_watermelon),
                new FruitBean("strawberry",R.mipmap.ic_strawberry)
                );
    }
}
           
  1. 工具類
public class DensityUtil {
    private static int[] deviceWidthHeight = new int[2];
    public static int[] getDeviceInfo(Context context) {
        if ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) {
            DisplayMetrics metrics = new DisplayMetrics();
            ((Activity) context).getWindowManager().getDefaultDisplay()
                    .getMetrics(metrics);

            deviceWidthHeight[0] = metrics.widthPixels;
            deviceWidthHeight[1] = metrics.heightPixels;
        }
        return deviceWidthHeight;
    }
    /**
     *
     * @param context 上下文
     * @param dpValue dp數值
     * @return dp to  px
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);

    }
    /**
     * 擷取螢幕尺寸
     */
    @SuppressWarnings("deprecation")
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    public static Point getScreenSize(Context context){
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2){
            return new Point(display.getWidth(), display.getHeight());
        }else{
            Point point = new Point();
            display.getSize(point);
            return point;
        }
    }
    /**
     *
     * @param context    上下文
     * @param pxValue  px的數值
     * @return  px to dp
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);

    }
}