RecyclerView网格布局,宽度数量自适应

需求:

实现Item在不同屏宽度上的数量自适应,以达到界面的保真。

实验过程:

设置了两个模拟器,将demo跑到不同的模拟器,以及横竖屏进行切换看具体的效果。

模拟器屏数据:

 实验效果:

 修改原理:

RecycleView的布局由LayoutManager完成,网格布局由StaggeredGridLayoutManager控制,同时在RecycleView绘制之前需要设置好每行显示的数量,于是可以在RecycleView整个绘制之前,对Item数量进行调整,同时需要对item的宽度大小进行控制。

具体代码如下:

main.xml说明:布局文件中最主要的是app:xc_auto_item_width属性的设置

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <com.rcl.recyclerviewdemo.widget.XCAutoRecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:xc_auto_item_flag="width_auto"
        app:xc_auto_item_width="350dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

自定组件设置传递熟数据

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="XCAutoRecyclerView">
        <attr name="xc_auto_item_flag">
            <flag name="no_auto" value="0" />
            <flag name="all_auto" value="1" />
            <flag name="width_auto" value="2" />
            <flag name="height_auto" value="3" />
        </attr>
        <attr name="xc_auto_item_width" format="dimension" />
        <attr name="xc_auto_item_min_width" format="dimension" />
        <attr name="xc_auto_item_max_width" format="dimension" />
    </declare-styleable>
</resources>

 具体组件自定义逻辑

public class XCAutoRecyclerView extends RecyclerView {
    private static final String TAG = "XCAutoRecyclerView";
    /**
     * 不需要处理自适应,默认情况
     */
    private static final int XC_AUTO_TYPE_NO = 0;
    /**
     * 宽高全部自适应
     */
    private static final int XC_AUTO_TYPE_ALL = 1;
    /**
     * 宽度自适应
     */
    private static final int XC_AUTO_TYPE_WIDTH = 2;
    /**
     * 高度自适应
     */
    private static final int XC_AUTO_TYPE_HEIGHT = 3;
    /**
     * item的自适应模式
     */
    private int xcAutoItemFlag = 0;
    /**
     * item自适应的宽度
     */
    private int xcAutoItemWidth = 0;
    /**
     * item自适应的最小宽度
     */
    private int xcAutoItemMinWidth = 0;
    /**
     * item自适应的最大宽度
     */
    private float xcAutoItemMaxWidth = 0;
    private Context xcContext;

    public XCAutoRecyclerView(@NonNull Context context) {
        super(context);
        xcContext = context;
    }

    public XCAutoRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initParams(context, attrs);
    }

    public XCAutoRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initParams(context, attrs);
    }

    /**
     * 获取xml中属性值
     */
    private void initParams(Context context, AttributeSet attrs) {
        xcContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XCAutoRecyclerView);
        if (typedArray != null) {
            xcAutoItemFlag = typedArray.getInt(R.styleable.XCAutoRecyclerView_xc_auto_item_flag, XC_AUTO_TYPE_NO);
            xcAutoItemWidth = px2dp(typedArray.getDimension(R.styleable.XCAutoRecyclerView_xc_auto_item_width, 0));
            xcAutoItemMinWidth = px2dp(typedArray.getDimension(R.styleable.XCAutoRecyclerView_xc_auto_item_min_width, 0));
            xcAutoItemMaxWidth = px2dp(typedArray.getDimension(R.styleable.XCAutoRecyclerView_xc_auto_item_max_width, 0));
            Log.i("jamie", "xcAutoItemFlag:" + xcAutoItemFlag + "---xcAutoItemWidth:" + xcAutoItemWidth + "---xcAutoItemMinWidth:" + xcAutoItemMinWidth + "---xcAutoItemMaxWidth:" + xcAutoItemMaxWidth);
            typedArray.recycle();
        }
    }
    /**
     * 在测量前,更改对应配置
     */
    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        LayoutManager xcLayout = getLayoutManager();
        if (xcLayout != null && xcLayout instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager xcStaggeredGridLayoutManager = (StaggeredGridLayoutManager) xcLayout;
            setLayoutManager(doAotoItemShow(xcStaggeredGridLayoutManager, widthSpec, heightSpec));
        }
        super.onMeasure(widthSpec, heightSpec);
    }
    /**
     * 计算出显示数量,并进行更改
     */
    private LayoutManager doAotoItemShow(StaggeredGridLayoutManager xcLayout, int widthSpec, int heightSpec) {
        int width = LayoutManager.chooseSize(widthSpec, getPaddingLeft() + getPaddingRight(), ViewCompat.getMinimumWidth(this));
        Log.i("jamie", "width:" + width);
        if (xcAutoItemFlag == XC_AUTO_TYPE_ALL || xcAutoItemFlag == XC_AUTO_TYPE_WIDTH) {
            int itemNumber = width / xcAutoItemWidth;
            xcLayout.setSpanCount(itemNumber == 0 ? 1 : itemNumber);
        }
        return xcLayout;
    }
    /**
     * 将px值转换为dp值
     */
    public int px2dp(float pxValue) {
        final float scale = xcContext.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值