尝试让Android的LinearLayout在水平和垂直方向上拉伸

4

更新:感谢建议使用GridView,我确实相信这将提供更好的性能。然而,我最初尝试实现一个简单的GridView的努力已经导致了令人羞愧的失败。我想弄清楚我做错了什么可能是另一个话题。为了修复此实现,我使用OnWindowFocusChanged查找ANDROID_CONTENT高度,然后除以行数来设置行高。这里的主要教训是在许多关于此问题的讨论中没有提到OnCreate是设置尺寸的错误位置。 OnWindowFocusChanged发生在稍后可以进行准确测量的时间。在许多关于此主题的讨论中经常没有提到这一信息。

原始内容: 我正在开发一个Android布局,尝试设置一个有三列和四行的棋盘。 我希望将棋盘垂直和水平地拉伸以填充可用屏幕。我尝试通过按行和列嵌套LinearLayout并使用weight="1"选项,但只能使其水平拉伸。 在以下配置中,行会拉伸以填充屏幕宽度,但列被设置为"60dp"。我也尝试过GridLayout和TableLayout,但无法获得所需的结果。

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft = "10dp"
        android:paddingRight = "10dp"
        android:background="@drawable/bg" >
        <LinearLayout
            android:id="@+id/player1"
            android:layout_width="match_parent"
            android:layout_height="@dimen/positionHeight"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal"
            android:background="@drawable/square" />
        <LinearLayout
            android:id="@+id/player2"
            android:layout_width="match_parent"
            android:layout_height="@dimen/positionHeight"
            android:layout_alignParentTop="true"
            android:orientation="horizontal"
            android:background="@drawable/square" />    
        <LinearLayout 
          android:id="@+id/row0"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"  
          android:layout_below="@id/player2"
          android:layout_alignParentLeft="true" 
          android:baselineAligned="false"
          android:orientation="horizontal">
          <LinearLayout
            android:id="@+id/position0"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
          <LinearLayout
            android:id="@+id/position1"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" /> 
          <LinearLayout
            android:id="@+id/position2"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
        </LinearLayout>  
        <LinearLayout 
          android:id="@+id/row1"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" 
          android:layout_below="@id/row0"
          android:layout_alignParentLeft="true"
          android:baselineAligned="false"
          android:orientation="horizontal">    
          <LinearLayout
            android:id="@+id/position3"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" /> 
          <LinearLayout
            android:id="@+id/position4"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
          <LinearLayout
            android:id="@+id/position5"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
        </LinearLayout>      
        <LinearLayout 
          android:id="@+id/row2"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" 
          android:layout_below="@id/row1"
          android:layout_alignParentLeft="true" 
          android:baselineAligned="false"
          android:orientation="horizontal"> 
          <LinearLayout
            android:id="@+id/position6"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
          <LinearLayout
            android:id="@+id/position7"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
          <LinearLayout
            android:id="@+id/position8"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
        </LinearLayout>      
        <LinearLayout 
          android:id="@+id/row3"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" 
          android:layout_below="@id/row2"
          android:layout_alignParentLeft="true" 
          android:baselineAligned="false"
          android:orientation="horizontal">   
          <LinearLayout
            android:id="@+id/position9"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />    
          <LinearLayout
            android:id="@+id/position10"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
          <LinearLayout
            android:id="@+id/position11"
           android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="@dimen/positionHeight"
            android:orientation="horizontal"
            android:background="@drawable/square" />
        </LinearLayout>

请给我建议。

4个回答

11

我不赞同其他人说你必须使用GridLayout。尝试使用LinearLayout的方法。我为网格的每个单元格使用了通用视图,但是任何控件都可以使用。

<?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="horizontal" >

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />
    </LinearLayout>

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

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

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

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />
    </LinearLayout>

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

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/red" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

</LinearLayout>

这种方法不需要在代码中手动调整布局,一切都在XML中使用权重来处理。


你可能会看到“嵌套权重对性能不利”的lint警告,这可能是真的,但是请自行测试,我认为您不会在这种简单的布局中注意到任何性能问题。 - invertigo
1
这正是我一开始想要做的。我会尝试一下。我同意我的解决方案有些“hacky”,但它运行良好!为了学习,我需要尝试你的解决方案。是的,那个lint警告一开始吓到了我,但我还是会尝试一下。 - smirciat
我个人一直使用嵌套权重,甚至在一个布局上有50多个视图时,也没有看到任何负面影响。 - invertigo

0

你必须尝试这个。

    <ImageView
        android:id="@+id/iv_clm1"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/yellow" />

    <ImageView
        android:id="@+id/iv_clm1"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/red" />
</LinearLayout>
<!-- second Row -->
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="1"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/iv_clm1"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/red" />

    <ImageView
        android:id="@+id/iv_clm2"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/yellow" />

    <ImageView
        android:id="@+id/iv_clm3"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/red" />
</LinearLayout>


我漏掉了一些XML吗?好像顶部不在那里。 - smirciat
我想我明白你在这里做什么。当我像这样嵌套权重时,我会收到警告。在您的意见中,当只有两个级别时,这不是值得担心的事情吗? - smirciat
@smirciat 这个技巧很妙,但是你必须始终使用Griedview来进行这种视图。 - Harshid

0

正如我在上面的更新中提到的,这里的真正诀窍是在OnCreate之外设置尺寸。我将player1、player2和position[]初始化为来自xml的LinearLayout元素,然后在onWindowFocusChanged中调整它们的高度以适应。虽然不如其他人建议的GridView好,但这是我能够实际使用的东西!

得益于:
http://www.rapidsnail.com/developer/topic/2011/222/27/35613/title-bar-and-get-out-of-the-view-of-the-status-bar-display-area-height.aspx

@Override
    public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
            player1.getLayoutParams().height=content.getHeight()/6;
            player2.getLayoutParams().height=content.getHeight()/6;
            for (int i=0;i<12;i++){
                    position[i].getLayoutParams().height=content.getHeight()/6;
            }

虽然这可能有效,但在我看来相当不专业。请看我的答案,它将只使用适当的权重在XML布局中获得所需的结果。 - invertigo
正如我在你的回答中所评论的,我同意你的观点。我想强调的一点是,许多像我这样的新手 Android 开发者尝试在 Activity 的 onCreate 中设置屏幕尺寸。然而,这种做法虽然最终能够实现,但却是一个不好的选择,这一点在帮助论坛中并没有被提及得足够多。 - smirciat

0

我尝试了几个TableLayout和GridLayout的例子,但是无法使它们水平和垂直填充整个可用区域。 - smirciat
我认为你应该发布与GridLayout相关的问题,而不是太多的LinearLayouts。问题出在哪里? - Marek
请查看我的更新答案,其中包含第三个教程,它是如何使用GridView的好例子。希望它能有所帮助。 - Marek

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