【问题标题】:Android grid layout align like GridLayoutManager styleAndroid 网格布局对齐方式类似于 GridLayoutManager 样式
【发布时间】:2020-12-01 07:48:24
【问题描述】:

我有以下 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 张图片:

我希望它从左到右统一添加它们,如果图像没有足够的空间来容纳自己,我希望它与其他图像“碰撞​​”而不是在它们之间留出边距(你可以见示例)。这就是我看到 GridLayoutManager 工作的方式。我怎样才能做到这一点?

【问题讨论】:

    标签: android grid-layout android-gridlayout gridlayoutmanager


    【解决方案1】:

    您可以创建自定义布局来处理您的不同情况。如下所示:

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

    【讨论】:

    • 工作就像一个魅力,令人印象深刻!
    • 额外问题:如何使这种布局使每行的元素居中?
    • 你应该做一些计算,例如计算 3 个项目的宽度,从布局宽度中减去它,然后将结果除以 2。然后将此结果用作在 FrameLayout 上布局子项的偏移量。 child.layout(offset + (i*widthOffset), .....如果重叠为真,偏移量应为零
    • 我不太懂英语,你能编辑你的答案吗:)?
    • 非常感谢朋友,如果可以的话,我会接受这个答案两次,哈哈
    猜你喜欢
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多