【问题标题】:MATCH_PARENT if sibling view is larger, WRAP_CONTENT if sibling view is smallerMATCH_PARENT 如果兄弟视图较大,WRAP_CONTENT 如果兄弟视图较小
【发布时间】:2017-08-02 14:11:07
【问题描述】:

我在一个布局中有两个视图。 我将分别称他们为View AView B

┌──────┐
│┌─┐┌─┐│
││A││B││
│└─┘└─┘│
└──────┘

父布局的高度(包括View AView B)是WRAP_CONTENT

这里,View B 的高度是WRAP_CONTENT。也就是说,它的高度可以根据其内容进行更改。

我想做的是

  1. 如果View A 的内容短于View B 的内容,则将View A 的高度设置为View B 的高度。
  2. 如果View A 的内容高于View B 的内容,则将View A 的高度设置为其自身内容的高度。

所以,

①如果View B的内容较高,则将View A的高度设置为View B的高度。

       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││ ││      ││A││ ││
I want ││A││B││, not │└─┘│B││.
       ││ ││ ││      │   │ ││
       │└─┘└─┘│      │   └─┘│
       └──────┘      └──────┘

②如果View B的内容较短,那么View A的高度就是View A自己内容的高度。

       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││B││      ││A││B││
I want ││A│└─┘│, not │└─┘└─┘│.
       ││ │   │      └──────┘
       │└─┘   │
       └──────┘

如果父级是LinearLayout (Horizontal),则将View A 的高度设置为WRAP_CONTENT 违反案例1,将View A 的高度设置为MATCH_PARENT 违反案例2。

如果父级是RelativeLayout,将View A 设置为对齐其父级的顶部和底部违反RelativeLayout 的条件: Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM.

我该如何解决这个问题?

【问题讨论】:

    标签: android android-layout


    【解决方案1】:

    有不同的方法来解决这个问题,例如通过创建您自己的自定义ViewGroup,可能基于水平LinearLayout。但是,我认为最直接的解决方案是在运行时动态设置需求。

    考虑以下布局,在水平 LinearLayout 中只有两个 TextViews:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/container"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#f00"
        android:padding="10dp" >
    
        <TextView
            android:id="@+id/first"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#0f0"
            android:padding="5dp"
            android:text="One line" />
    
        <TextView
            android:id="@+id/second"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00f"
            android:padding="5dp"
            android:text="Two\nlines"
            android:textColor="#fff" />
    
    </LinearLayout>
    

    两者都包裹了它们的高度,这基本上符合您的第一个要求。

    现在要求 2:出于演示目的,我将第二个 TextView 的文本分成两行,以使其比第一行高。要使第一个 TextView 匹配它的高度,您所要做的就是:

    LinearLayout container = (LinearLayout) findViewById(R.id.container);
    final TextView first = (TextView) findViewById(R.id.first);
    final TextView second = (TextView) findViewById(R.id.second);
    
    container.post(new Runnable() {
        @Override public void run() {
            int h1 = first.getMeasuredHeight();
            int h2 = second.getMeasuredHeight();
            if (h1 < h2) first.getLayoutParams().height = h2;
    
        }
    });
    

    “诀窍”是发布到视图的队列中,确保在测量孩子并具有有效高度之前不会执行逻辑。对于需求 2,只有在第二个视图更高时才需要更改第一个视图的高度,这正是 run() 方法中的部分所做的。

    【讨论】:

    • 难道没有 xml 方法可以做到这一点吗?否则我将不得不在我的适配器中执行此操作,因为我想在动态填充的列表中执行此类操作。
    • @BartBurg:自定义ViewGroup 可能是最佳解决方案。扩展 LinearLayout 将是一个好的开始,并且 - 根据您的具体用例 - 您可能需要做的只是覆盖 onMeasure() 以考虑上述标准。
    • 它会导致动画效果,这可能是不受欢迎的。非常感谢自定义 ViewGroup 示例。
    • @HenriquedeSousa:你有没有机会在容器视图中设置或使用android:animateLayoutChanges="true" 或使用setLayoutTransition()(另见here)?没有这些,动态变化的高度应该不会很明显。尽管如此,上面的解决方案并不理想,自定义ViewGroup 确实是要走的路。如果我能找到时间,我会尽快完成。
    【解决方案2】:

    您需要使用布局参数以编程方式设置视图的尺寸。假设您使用 LinearLayout 来保存视图,这就是您要做的:

    //the views are called a and b
    LinearLayout.LayoutParams aParams = a.getLayoutParams();
    LinearLayout.LayoutParams bParams = b.getLayoutParams();
    int aWidth = aParams.width;
    int aHeight = aParams.height;
    int bWidth = bParams.width;
    int bHeight = bParams.height;
    if (aHeight >= bHeight) {
        // do nothing
    }
    else {
        a.setLayoutParams(new LinearLayout.LayoutParams(aWidth, bHeight));
    }
    

    当您设置它们的高度时,在此修改之前将它们保留为 xml 中的 wrap_content。

    【讨论】:

      【解决方案3】:

      这很容易解决,只需要 axml。

      保持父布局的高度为wrap_content,并将每个子视图的高度设置为match_parent。这将导致父布局的高度环绕到最高的子视图,并且每个子视图的高度都拉伸到父视图。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-24
        • 1970-01-01
        • 2014-02-05
        • 1970-01-01
        • 2019-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多