先上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;
这几个字段是必要的其他的可以根据需求自己去定。