GridLayout结合RecyclerView.Adapter实现单页栅格列表的显示

先上Github,github内也有具体用法,如果对您有用帮忙点个star

遇到一个需求是要求,就是在一页之内显示类似九宫格一样的布局,但是每个item占据大小不一样。

最终效果:
在这里插入图片描述
设计如图:
在这里插入图片描述
尝试了一些其他的布局,感觉还是GridLayout最为方便,按照行列划分布局,而且很容易实现我们这种一拖N,而且实现起来比阿里的Tangram要简单点,而且我们的界面不算复杂,不需要大材小用。而且我们这个布局也可以轻松实现九宫格布局。

废话不多说,众所周知RecyclerView.Adapter 可以创建ViewHolder并且可以将列表中的位置和ViewHolder绑定起来,这样我们就可以将GridLayout每个位置的View和position和数据绑定起来。

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.GridLayout;

import androidx.annotation.Nullable;

/**
 * @package com.mgo.uikitimpl.view.mygrid
 * @user by lvyaodong
 * @date 2020/8/20
 * @email 1126220529@qq.com
 */
public class DynamicGridLayout<D extends GridData, A extends BaseAdapter<D, BaseViewHolder<D>>> extends GridLayout {
    private static final String TAG = "DynamicGridLayout";

    private A mAdapter;
    private int mMargin = 10;
    private int mHalfMargin = mMargin / 2;

    public void setAdapter(A mAdapter) {
        this.mAdapter = mAdapter;
        loadView();
    }

    public DynamicGridLayout(Context context) {
        this(context, null);
    }

    public DynamicGridLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void loadView() {
        if (mAdapter == null) {
            Log.e(TAG, "Adapter can not be null!");
            return;
        }
        for (int i = 0; i < mAdapter.getItemCount(); i++) {
            //创建ViewHolder
            BaseViewHolder<D> viewHolder = mAdapter.createViewHolder(this, 0);
            //绑定ViewHolder
            mAdapter.onBindViewHolder(viewHolder, i);

            D data = mAdapter.getItem(i);

            viewHolder.itemView.setTag(data);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();

            params.width = 0;
            params.height = 0;

            int leftMargin = data.getStartX() == 0 ? mMargin : mHalfMargin;
            int topMargin = data.getStartY() == 0 ? mMargin : mHalfMargin;
            int rightMargin = data.getEndX() % getColumnCount() == 0 ? mMargin : mHalfMargin;
            int bottomMargin = data.getEndY() % getRowCount() == 0 ? mMargin : mHalfMargin;

            params.setMargins(dp2px(this.getContext(), leftMargin), dp2px(this.getContext(), topMargin), dp2px(this.getContext(), dp2px(this.getContext(), rightMargin)), dp2px(this.getContext(), bottomMargin));
            params.columnSpec = GridLayout.spec(data.getStartX(), data.getEndX() - data.getStartX(), (float) (data.getEndX() - data.getStartX()));
            params.rowSpec = GridLayout.spec(data.getStartY(), data.getEndY() - data.getStartY(), (float) (data.getEndY() - data.getStartY()));

            addView(viewHolder.itemView, params);
        }
    }

    private int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}

然后由于第一个图片已经超出了为他分配的高度,暂时只是将第一个位置的布局不加载,然后单独放一张图片。如果大佬们有更好的方案可以帮我优化下啊哈哈。

另外每个列表返回都要有几个位置分配字段,右上角和左下角点的坐标。

package com.mgo.uikitimpl.view.mygrid;

/**
 * @package com.mgo.uikitimpl.view.mygrid
 * @user by lvyaodong
 * @date 2020/8/19
 * @email 1126220529@qq.com
 */
public class GridData {
    private String imgUrl;
    private String text;
    private String page;
    private String tabId;
    private int startX;
    private int startY;
    private int endX;
    private int endY;

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

    public String getTabId() {
        return tabId;
    }

    public void setTabId(String tabId) {
        this.tabId = tabId;
    }

    public int getStartX() {
        return startX;
    }

    public void setStartX(int startX) {
        this.startX = startX;
    }

    public int getStartY() {
        return startY;
    }

    public void setStartY(int startY) {
        this.startY = startY;
    }

    public int getEndX() {
        return endX;
    }

    public void setEndX(int endX) {
        this.endX = endX;
    }

    public int getEndY() {
        return endY;
    }

    public void setEndY(int endY) {
        this.endY = endY;
    }
}

	private int startX;
    private int startY;
    private int endX;
    private int endY;

这几个字段是必要的其他的可以根据需求自己去定。

GridLayout用法理解

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值