异构网格布局

36

我正在尝试实现以下布局:

目标布局

我猜 GridLayout 适合我的需求,但是经过两个小时的努力,我甚至无法创建一个类似的布局...该布局错误地调整大小,它超出了手机屏幕,而且它也不能跨越指定的行和列。

这里我选择了一个按钮,以便您可以看到它如何超出边界:

失败

这是相关的xml代码:https://gist.github.com/2834492

我已经使用嵌套线性布局达到了类似的布局,但是很难根据不同的屏幕尺寸进行正确的调整大小


更新-大致线性布局实现:

XML代码:https://gist.github.com/cdoger/2835887 然而,问题是它无法正确地调整大小,这里是一些具有不同屏幕配置的屏幕截图:

enter image description here

enter image description here

enter image description here


简述:能否有人展示一个类似于第一张图片的GridLayout异构布局实现?


我之前创建了一个快速且简单的示例,可能对你有所帮助。不过,正如@Skies已经指出的那样:我不知道有没有基于XML的方法来正确缩放“瓦片”,但是,我并没有花时间仔细查看。从听起来的情况来看,你已经比我当时花费更长的时间在这方面上了。 - MH.
我在最初搜索答案时看到了你的回答。然而,我仍然无法创建像第一张图片中那样的布局。我相当确定如果GridLayout实现没有错误或其他问题,它应该可以通过xml完成。 - C.d.
如果我没记错的话,使用基于XML的方法遇到的主要问题是GridLayout没有提供类似“权重”的东西。你可以通过设置gravity属性告诉单元格填充剩余空间,但不能用它来均匀分配空间。至少在我花费的短时间内,我无法找到一种在不使用运行时设备参数的情况下创建两个等大小列以填充屏幕宽度的方法。我会继续关注这个问题 - 我很想看看其他人能想出什么办法。 - MH.
为什么你的GridLayout中没有指定“rowCount”? - IgorGanapolsky
6个回答

19
您遇到的问题是由于不正确使用GridLayout导致的。GridLayout是用于以网格形式显示其子项的,您正在尝试在不扩展GridLayout的情况下覆盖它。虽然您想要的可能可以在代码中实现(利用numcolumns和columnsize),但如果没有大量的代码,它对于多个屏幕大小将无法使用。
唯一适当的解决方案是明智地同时使用LinearLayout和RelativeLayout。LinearLayout不应仅用于放置项目(仅水平或垂直)。这在您尝试处理底部四个按钮时特别明显。虽然可以使用LinearLayout很容易地完成上面的按钮,但RelativeLayout是您需要的底部四个按钮。
注意:RelativeLayout对于那些使用不多的人可能有点棘手。一些陷阱包括:子项重叠,子项移出屏幕,高度和宽度渲染不正确应用。如果您需要示例,请告诉我,我会编辑我的答案。
最终注意事项: 我非常支持以独特的方式利用当前的框架对象,并真正希望提供所请求的解决方案。然而,该解决方案不可行,因为限制了问题的约束条件。
(修订)解决方案1: 经过昨晚的仔细思考,可以使用纯LinearLayout来实现此目标。虽然我不喜欢这个解决方案,但它应该适用于多屏幕,并且不需要我进行任何调整。应谨慎使用过多的LinearLayout,因为根据Google的开发人员,它可能会导致由于layout_weight属性而加载缓慢的UI。当我回家时,将提供一种利用RelativeLayout的第二种解决方案。现在已经测试,可以在所有屏幕大小和方向上提供所需的布局参数。
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">
        <LinearLayout 
            android:layout_width="match_parent" 
            android:layout_height="0dp" 
            android:layout_weight="1" 
            android:orientation="horizontal"> 
            <Button 
                android:id="@+id/Button01" 
                android:layout_width="0" 
                android:layout_height="match_parent" 
                android:layout_weight="1" 
                android:text="Button" />     
            <Button 
                android:id="@+id/Button02" 
                android:layout_width="0" 
                android:layout_height="match_parent" 
                android:layout_weight="1" 
                android:text="Button" />     
        </LinearLayout> 
        <Button 
            android:id="@+id/button3" 
            android:layout_width="match_parent" 
            android:layout_height="0dp"
            android:layout_weight="1" 
            android:text="Button" />   
        <LinearLayout 
            android:layout_width="match_parent" 
            android:layout_height="0dp" 
            android:layout_weight="1.00"
            android:orientation="horizontal">  
            <Button 
                android:id="@+id/button1" 
                android:layout_width="0dp" 
                android:layout_height="match_parent" 
                android:layout_weight="1" 
                android:text="Button" />   
            <Button 
                android:id="@+id/button2" 
                android:layout_width="0dp" 
                android:layout_height="match_parent" 
                android:layout_weight="1" 
                android:text="Button" />     
        </LinearLayout>
    </LinearLayout>    
    <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="0dp" 
        android:layout_weight="1" 
        android:orientation="horizontal">     
        <LinearLayout 
            android:layout_width="0dp" 
            android:layout_height="match_parent" 
            android:layout_weight="1" 
            android:orientation="vertical" >    
            <Button 
                android:id="@+id/button4" 
                android:layout_width="match_parent" 
                android:layout_height="0dp"
                android:layout_weight="1" 
                android:text="Button" />     
            <Button 
                android:id="@+id/button5" 
                android:layout_width="match_parent" 
                android:layout_height="0dp" 
                android:layout_weight="2" 
                android:text="Button" />     
        </LinearLayout>     
        <LinearLayout 
            android:layout_width="0dp" 
            android:layout_height="match_parent" 
            android:layout_weight="1" 
            android:orientation="vertical" > 
            <Button 
                android:id="@+id/button6" 
                android:layout_width="match_parent" 
                android:layout_height="0dp" 
                android:layout_weight="2" 
                android:text="Button" /> 
            <Button 
                android:id="@+id/button7" 
                android:layout_width="match_parent" 
                android:layout_height="0dp" 
                android:layout_weight="1" 
                android:text="Button" /> 
        </LinearLayout> 
    </LinearLayout> 
</LinearLayout> 

解决方案1说明

LinearLayout的关键在于将你的约束定义为单独的布局,并将其他布局嵌套其中。随着对更多维度应用约束,必须添加更多的LinearLayout来封装其他布局。对于您的情况,保持比例关系非常重要,因此必须添加两个以上的父级。当您不得不使用除整数值以外的任何内容时,这是添加另一层的重要指标。计算变得太困难了。从那里开始,将其相对简单地分成列。

解决方案2(失败)

虽然我能够利用RelativeLayout和"struts"实现理想的结果,但我只能用高度为2按钮倍数的布局才能这样做。这样的技巧很棒,因为布局的层级大大降低,所以我将努力寻找纯XML解决方案,并在实现时在此发布答案。与此同时,上面的LinearLayout应该完全符合您的需求。


顺便说一下,它是GridLayout而不是GridView,我猜这是一个打字错误。我按照你的建议管理了所需的布局,我会在有时间的时候放上代码。我用纯代码而不是xml完成了它。 - C.d.
你说得对。我不知道为什么一直打GridView的字。:( -1. 不管怎样,我会在MST下午2点之前为您提供一个纯XML解决方案。 - Fuzzical Logic
只是为了确保我理解正确...前五个按钮必须占据屏幕的一半,而下面的四个按钮则占据另一半? - Fuzzical Logic
没错,在我的解决方案中,我将屏幕分成了6个单位高度和2个单位宽度的块,在运行时测量屏幕并相应地生成布局。 - C.d.

16

我阅读了这个帖子,意识到我想要比线性布局更平的解决方案。经过一些研究,我最终制作了自己的布局。它受GridLayout的启发,但有所不同。

请注意,如果您要复制粘贴代码,您需要在某些地方更改包名称。

此布局具有4个布局参数,供子项使用以定位自身。这些是layout_left、layout_top、layout_right和layout_bottom。ICGridLayout本身有两个属性:layout_spacing和columns。

Columns告诉布局您想要包含多少列。然后它将计算与宽度/列相同高度的单元格的大小。这将是布局的宽度/列。

spacing是您希望每个子项之间的间距。

layout_left | top | right | bottom属性是每个侧面的坐标。布局不进行任何计算,以避免发生碰撞等情况。它只是把孩子放在他们想要的地方。

如果您想要更小的正方形,您只需增加columns属性即可。

请记住,这是一个快速原型,我将继续改进它,当我感觉它准备好时,我会将其上传到Github并在此处发表评论。

我的所有代码应该产生以下结果:Layout when using my provided code

*****编辑***** 增加了孩子的度量调用,第一次忘记了。 结束编辑 ICGridLayout.java:

package com.risch.evertsson.iclib.layout;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import com.risch.evertsson.iclib.R;

/**
 * Created by johanrisch on 6/13/13.
 */
public class ICGridLayout extends ViewGroup {
    private int mColumns = 4;
    private float mSpacing;

    public ICGridLayout(Context context) {
        super(context);
    }

    public ICGridLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public ICGridLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        TypedArray a = getContext().obtainStyledAttributes(
                attrs,
                R.styleable.ICGridLayout_Layout);
        this.mColumns = a.getInt(R.styleable.ICGridLayout_Layout_columns, 3);
        this.mSpacing = a.getDimension(R.styleable.ICGridLayout_Layout_layout_spacing, 0);
        a.recycle();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
            int width = (int) (r - l);
            int side = width / mColumns;
            int children = getChildCount();
            View child = null;
            for (int i = 0; i < children; i++) {
                child = getChildAt(i);
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                int left = (int) (lp.left * side + mSpacing / 2);
                int right = (int) (lp.right * side - mSpacing / 2);
                int top = (int) (lp.top * side + mSpacing / 2);
                int bottom = (int) (lp.bottom * side - mSpacing / 2);
                child.layout(left, top, right, bottom);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureVertical(widthMeasureSpec, heightMeasureSpec);

    }

    private void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int width = 0;
        int height = 0;


        if (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.EXACTLY) {
            width = MeasureSpec.getSize(widthMeasureSpec);
        } else {
            throw new RuntimeException("widthMeasureSpec must be AT_MOST or " +
                    "EXACTLY not UNSPECIFIED when orientation == VERTICAL");
        }


        View child = null;
        int row = 0;
        int side = width / mColumns;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            child = getChildAt(i);

            LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (lp.bottom > row) {
                row = lp.bottom;
            }



            int childHeight = (lp.bottom - lp.top)*side;
            int childWidth = (lp.right-lp.left)*side;
            int heightSpec = MeasureSpec.makeMeasureSpec(childHeight, LayoutParams.MATCH_PARENT);
            int widthSpec = MeasureSpec.makeMeasureSpec(childWidth, LayoutParams.MATCH_PARENT);

            child.measure(widthSpec, heightSpec);
        }
        height = row * side;
        // TODO: Figure out a good way to use the heightMeasureSpec...

        setMeasuredDimension(width, height);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new ICGridLayout.LayoutParams(getContext(), attrs);
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof ICGridLayout.LayoutParams;
    }

    @Override
    protected ViewGroup.LayoutParams
            generateLayoutParams(ViewGroup.LayoutParams p) {
        return new ICGridLayout.LayoutParams(p);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }

    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
        int right = 1;
        int bottom = 1;
        int top = 0;
        int left = 0;
        int width = -1;
        int height = -1;

        public LayoutParams() {
            super(MATCH_PARENT, MATCH_PARENT);
            top = 0;
            left = 1;
        }

        public LayoutParams(int width, int height) {
            super(width, height);
            top = 0;
            left = 1;
        }

        public LayoutParams(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.obtainStyledAttributes(
                    attrs,
                    R.styleable.ICGridLayout_Layout);
            left = a.getInt(R.styleable.ICGridLayout_Layout_layout_left, 0);
            top = a.getInt(R.styleable.ICGridLayout_Layout_layout_top, 0);
            right = a.getInt(R.styleable.ICGridLayout_Layout_layout_right, left + 1);
            bottom = a.getInt(R.styleable.ICGridLayout_Layout_layout_bottom, top + 1);
            height = a.getInt(R.styleable.ICGridLayout_Layout_layout_row_span, -1);
            width = a.getInt(R.styleable.ICGridLayout_Layout_layout_col_span, -1);
            if (height != -1) {
                bottom = top + height;
            }
            if (width != -1) {
                right = left + width;
            }

            a.recycle();
        }

        public LayoutParams(ViewGroup.LayoutParams params) {
            super(params);
        }

    }

}

ICGridLayout.java非常直观,它获取子项提供的值并对其进行布局。

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ICGridLayout_Layout">
        <attr name="columns" format="integer"/>
        <attr name="layout_left" format="integer"/>
        <attr name="layout_top" format="integer"/>
        <attr name="layout_right" format="integer"/>
        <attr name="layout_bottom" format="integer"/>
        <attr name="layout_col_span" format="integer"/>
        <attr name="layout_row_span" format="integer"/>
        <attr name="layout_spacing" format="dimension"/>
    </declare-styleable>

</resources>

example_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.rischit.projectlogger"
    android:id="@+id/scroller"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.risch.evertsson.iclib.layout.ICGridLayout
        android:id="@+id/ICGridLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_spacing="4dp"
        app:columns="4" >


        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="1"
            app:layout_left="0"
            app:layout_right="4"
            app:layout_top="0"
            android:background="#ff0000"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="3"
            app:layout_left="3"
            app:layout_right="4"
            app:layout_top="1"
            android:background="#00ff00"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="4"
            app:layout_left="0"
            app:layout_right="3"
            app:layout_top="1"
            android:background="#0000ff"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="4"
            app:layout_left="3"
            app:layout_right="4"
            app:layout_top="3"
            android:background="#ffff00"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="6"
            app:layout_left="0"
            app:layout_right="1"
            app:layout_top="4"
            android:background="#ff00ff"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_bottom="6"
            app:layout_left="1"
            app:layout_right="4"
            app:layout_top="4"
            android:background="#ffffff"
            android:text="TextView" />
    </com.risch.evertsson.iclib.layout.ICGridLayout>

</ScrollView>

-- Johan Risch

附言: 这是我第一次写的长篇回答,我尽力以正确的方式表达。如果我失败了,请告诉我,但请不要过于批评。 敬礼


10

这样做合适吗?

在此输入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.54" >
        <Button
            android:id="@+id/Button01"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1.00"
            android:text="Button" />    
        <Button
            android:id="@+id/Button02"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1.00"
            android:text="Button" />    
    </LinearLayout>
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="99dp" > 
        <Button
            android:id="@+id/button1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="Button" />  
        <Button
            android:id="@+id/button2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="Button" />    
    </LinearLayout>   
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical" >   
            <Button
                android:id="@+id/button4"
                android:layout_width="match_parent"
                android:layout_height="152dp"
                android:text="Button" />    
            <Button
                android:id="@+id/button5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Button" />    
        </LinearLayout>    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical" >
            <Button
                android:id="@+id/button6"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Button" />
            <Button
                android:id="@+id/button7"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Button" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

这看起来是一个不错的方法,但它能够适应所有屏幕尺寸的自适应调整吗?例如,我在3.2英寸的配置下尝试了一下,按钮会在2.7英寸或4.65英寸的配置下出现损坏,也没有达到预期的效果。(截图:http://goo.gl/ka1hN)我认为LinearLayout并不是很适合这种情况,对吗? - C.d.
我不知道如何在XML中实现,所以您可以尝试通过编程来完成。使用WindowManager获取屏幕大小,并使用屏幕大小的百分比影响每个部分。 - Skies
我正在尝试使用rowSpan和columnSpan选项来解决问题。 - Skies
但这不是一个 GridLayout。原帖作者明确表达了他要使用 GridLayout 的意图... - IgorGanapolsky

8

正如许多人所说,嵌套的线性布局似乎是解决这个问题的唯一方法。其中一些解决方案没有以最灵活的方式使用布局参数。下面的代码尝试以一种对宽高比变化有鲁棒性的方式来实现,详细说明在注释中。

输入图像描述 横向布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First row. -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <!-- Equal weights cause two columns of equal width. -->

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="A" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="B" />
    </LinearLayout>

    <!-- Second row. -->

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="C" />

    <!-- Third row. -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <!-- Equal weights cause two columns of equal width. -->

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="D" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="E" />
    </LinearLayout>

    <!-- Uneven fourth and fifth rows. -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:baselineAligned="false" >

        <!-- Left column. Equal weight with right column gives them equal width. -->

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical" >

            <!--
                 The use of weights below assigns all extra space to G. There
                 are other choices. LinearLayout computes sizes along its
                     axis as given, then divides the remaining extra space using
                 weights.  If a component doesn't have a weight, it keeps
                 the specified size exactly.
            -->


            <!-- Fill width of layout and use wrap height (because there's no weight). -->

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="F" />

            <!-- Fill width of layout and put all the extra space here. -->

            <Button
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:text="G" />
        </LinearLayout>

        <!-- Right column. Equal weight with left column gives them equal width. -->

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical" >

            <!-- Same as above except top button gets all the extra space. -->

            <Button
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:text="H" />

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="I" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

5
所以这是我一年后承诺的解决方案 =) 它基本上使用ViewTreeObserver来获取父布局的尺寸并相应地创建自定义视图。由于这段代码已经有一年了,ViewTreeObserver可能不是动态获取尺寸的最佳方式。
您可以在此处找到完整的源代码: https://github.com/cdoger/Android_layout 我将屏幕分成8个相等的宽度和6个相等的高度。以下是我布置视图的快照:
final RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_layout);
ViewTreeObserver vto = mainLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        final int oneUnitWidth = mainLayout.getMeasuredWidth() / 8;
        final int oneUnitHeight = mainLayout.getMeasuredHeight() / 6;
        /**
         * 1
         ***************************************************************/
        final RelativeLayout.LayoutParams otelParams = new RelativeLayout.LayoutParams(
                oneUnitWidth * 4, oneUnitHeight);
        otelParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        otelParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        // otelParams.setMargins(0, 0, 2, 0);
        View1.setLayoutParams(otelParams);
        /***************************************************************/

        /**
         * 2
         ***************************************************************/
        final RelativeLayout.LayoutParams otherParams = new RelativeLayout.LayoutParams(
                oneUnitWidth * 4, oneUnitHeight);
        otherParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        otherParams.addRule(RelativeLayout.RIGHT_OF, View1.getId());
        otherParams.setMargins(2, 0, 0, 0);
        View2.setLayoutParams(otherParams);
        /***************************************************************/
//... goes on like this

这是最终截图:

输入图像描述


1
我很好奇,即使在2016年我们有兼容的Design Support库,您是否仍需要通过ViewTreeObserver进行整个操作? - IgorGanapolsky
1
@IgorGanapolsky 很久没检查过了。如果你发现更有用和更容易的东西,我真的很想看看它 =) - C.d.
是的,问题仍然存在,您仍然需要使用ViewTreeObserver来计算单位大小。 - Ankur

3
将GridLayout嵌入到LinearLayout中,如下所示,我已经尝试过并且可行。

enter image description here

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal" >

<GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="2" >

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="start|end"
        android:layout_row="0"
        android:text="ASDFASDF" />

    <Button
        android:layout_column="1"
        android:layout_gravity="start|end"
        android:layout_row="0"
        android:text="SDAVDFBDFB" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="2"
        android:layout_gravity="fill|center"
        android:layout_row="1"
        android:text="ASDVADFBFDAFEW" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="2"
        android:text="FWEA AWFWEA" />

    <Button
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill"
        android:layout_row="2"
        android:text="BERWEfasf" />

    <Button
        android:layout_width="94dp"
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="3"
        android:text="SDFVBFAEVSAD" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="4"
        android:layout_rowSpan="2"
        android:text="GVBAERWEFSD" />

    <Button
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="3"
        android:layout_rowSpan="2"
        android:text="VSDFAVE SDFASDWA SDFASD" />

    <Button
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="5"
        android:text="FWEWEGAWEFWAE"/>
</GridLayout>

    </LinearLayout>

好的,看起来解决了边框问题,但仍然没有第一张图片中的布局。顺便说一下,我尝试了一下,按钮仍然超出了边界。 - C.d.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接