Android 网格布局像 GridLayoutManager 样式一样对齐
Android grid layout align like GridLayoutManager style
我有以下 GridLayout,它存储最多 6 个列:
<androidx.gridlayout.widget.GridLayout
android:id="@+id/pokemonTeambuilderSpritesLayout"
android:layout_width="match_parent"
android:layout_height="100dp"
app:columnCount="6"
app:rowCount="1"
app:useDefaultMargins="true" />
我在这里填充它:
List<Pokemon> pokemonList = pokemonTeam.getPokemonList();
for (Pokemon pokemon : pokemonList) {
CircularImageView ivPokemonSprite = new CircularImageView(mContext);
String pokemonId = pokemon.get_id();
int pokemonImageId = PokemonUtils.getPokemonSugimoriImageById(pokemonId, mContext);
Picasso.get().load(pokemonImageId).into(ivPokemonSprite);
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(
GridLayout.spec(GridLayout.UNDEFINED, 1f),
GridLayout.spec(GridLayout.UNDEFINED, 1f)
);
layoutParams.width = 0;
ivPokemonSprite.setLayoutParams(layoutParams);
holder.teamSpritesGridLayout.addView(ivPokemonSprite);
}
我当前输出的 6 张图片是这样的:
有 3 张图片:
有 2 张图片:
我想要的输出是:
6 张图片:
2 张图片:
4 张图片:
我希望它从左到右均匀地添加它们,如果图像没有足够的 space 来适应它自己,我希望它与其他图像“碰撞”而不是让边距它们之间(如您在示例中所见)。这就是我看到 GridLayoutManager 工作的方式。我怎样才能做到这一点?
您可以创建自定义布局来处理不同的情况。如下所示:
public class PokemonLayout extends FrameLayout {
private int height;
private int width;
private int childWidth;
public PokemonLayout(Context context) {
this(context, null);
}
public PokemonLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = MeasureSpec.getSize(widthMeasureSpec);
height = Integer.MIN_VALUE;
childWidth = Integer.MIN_VALUE;
measureChildren(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
height = Math.max(child.getMeasuredHeight(), height);
childWidth = Math.max(child.getMeasuredWidth(), childWidth);
}
setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
int count = getChildCount();
boolean overlap = count * childWidth > width;
int widthOffset = childWidth;
if(overlap) {
widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
}
for (int i = 0; i < getChildCount(); i++) {
View child = (View) getChildAt(i);
child.layout(i*widthOffset,
0,(i*widthOffset) + childWidth
, child.getMeasuredHeight());
}
}
}
3 张图片:
5 张图片:
更新 1:
将 onLayout 方法更改为将子元素定位在布局的中心
@Override
protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
int count = getChildCount();
boolean overlap = count * childWidth > width;
int widthOffset = childWidth;
int startOffest = (width - (count * childWidth)) / 2;
if(overlap) {
startOffest = 0;
widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
}
for (int i = 0; i < getChildCount(); i++) {
View child = (View) getChildAt(i);
child.layout(startOffest+ (i*widthOffset),
0,(i*widthOffset) + childWidth + startOffest
, child.getMeasuredHeight());
}
}
我有以下 GridLayout,它存储最多 6 个列:
<androidx.gridlayout.widget.GridLayout
android:id="@+id/pokemonTeambuilderSpritesLayout"
android:layout_width="match_parent"
android:layout_height="100dp"
app:columnCount="6"
app:rowCount="1"
app:useDefaultMargins="true" />
我在这里填充它:
List<Pokemon> pokemonList = pokemonTeam.getPokemonList();
for (Pokemon pokemon : pokemonList) {
CircularImageView ivPokemonSprite = new CircularImageView(mContext);
String pokemonId = pokemon.get_id();
int pokemonImageId = PokemonUtils.getPokemonSugimoriImageById(pokemonId, mContext);
Picasso.get().load(pokemonImageId).into(ivPokemonSprite);
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(
GridLayout.spec(GridLayout.UNDEFINED, 1f),
GridLayout.spec(GridLayout.UNDEFINED, 1f)
);
layoutParams.width = 0;
ivPokemonSprite.setLayoutParams(layoutParams);
holder.teamSpritesGridLayout.addView(ivPokemonSprite);
}
我当前输出的 6 张图片是这样的:
有 3 张图片:
有 2 张图片:
我想要的输出是:
6 张图片:
2 张图片:
4 张图片:
我希望它从左到右均匀地添加它们,如果图像没有足够的 space 来适应它自己,我希望它与其他图像“碰撞”而不是让边距它们之间(如您在示例中所见)。这就是我看到 GridLayoutManager 工作的方式。我怎样才能做到这一点?
您可以创建自定义布局来处理不同的情况。如下所示:
public class PokemonLayout extends FrameLayout {
private int height;
private int width;
private int childWidth;
public PokemonLayout(Context context) {
this(context, null);
}
public PokemonLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PokemonLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = MeasureSpec.getSize(widthMeasureSpec);
height = Integer.MIN_VALUE;
childWidth = Integer.MIN_VALUE;
measureChildren(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
height = Math.max(child.getMeasuredHeight(), height);
childWidth = Math.max(child.getMeasuredWidth(), childWidth);
}
setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
int count = getChildCount();
boolean overlap = count * childWidth > width;
int widthOffset = childWidth;
if(overlap) {
widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
}
for (int i = 0; i < getChildCount(); i++) {
View child = (View) getChildAt(i);
child.layout(i*widthOffset,
0,(i*widthOffset) + childWidth
, child.getMeasuredHeight());
}
}
}
3 张图片:
5 张图片:
更新 1: 将 onLayout 方法更改为将子元素定位在布局的中心
@Override
protected void onLayout(boolean changed, int leftParent, int topParent, int rightParent, int bottomParent) {
int count = getChildCount();
boolean overlap = count * childWidth > width;
int widthOffset = childWidth;
int startOffest = (width - (count * childWidth)) / 2;
if(overlap) {
startOffest = 0;
widthOffset = childWidth - (Math.abs(width - (count * childWidth)) / (count-1));
}
for (int i = 0; i < getChildCount(); i++) {
View child = (View) getChildAt(i);
child.layout(startOffest+ (i*widthOffset),
0,(i*widthOffset) + childWidth + startOffest
, child.getMeasuredHeight());
}
}