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());
       }
   }