约束布局 - 宽度最大的两个视图 [英] constraint layout - Two views with largest width

查看:37
本文介绍了约束布局 - 宽度最大的两个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建如下布局(使用约束布局):

在不同的语言中,Button1 可能比 button2 大.我该怎么做?

我只能在包含两个按钮的约束中使用 LinearLayout 来实现这一点,但我试图只使用一个布局.

谢谢

解决方案

更新

我想提一下,Remq 的答案有效并解决了我在下面提到的自引用问题,其中视图的宽度由屏障的位置决定,该屏障使用与引用的 id 相同的视图.关键似乎是两个视图的 app:layout_constraintWidth_min="wrap" 规范.我不清楚为什么这会起作用,或者它会继续起作用,但我想记下它

更新 #2

我又看了看为什么 Remq 的答案有效.我的经验是,如果没有为视图指定 app:layout_constraintWidth_min="wrap",两个视图都会折叠为零宽度.一旦视图测量为零宽度,app:layout_constraintWidth_min=wrap" 再次增长它们,以便包装内容.这只是我的猜测,并没有证据表明这是正在发生的事情,但这是有道理的.



我在 Stack Overflow 上多次看到类似这个问题的问题.这些问题从来没有令人满意的答案 IMO(包括我已经回答过的问题).困难在于存在依赖性问题,因为一个视图取决于另一个视图的宽度,而另一个视图取决于第一个视图的宽度.我们陷入了参考的窘境.(以编程方式强制宽度始终是一种选择,但似乎不可取.)

另一种可能更好的方法是使用自定义ConstraintHelper,它会检查引用视图的大小并将所有视图的宽度调整为最大的宽度.

自定义 ConstraintHelper 放置在布局的 XML 中并引用受影响的视图,如以下示例布局:

activity_main

I want to create a layout (using constraint layout) like the following:

In different languages Button1 may be larger than button2. How can I do this?

I've only been able to achieve this using a LinearLayout inside the constraint that contains the two buttons, but I'm trying to use only a layout.

Thanks

解决方案

Update

I want to mention that Remq's answer works and gets around the self-reference problem I noted below where a view's width is determined by the location of a barrier that uses the same view as a referenced id. The key seems to be the specification of app:layout_constraintWidth_min="wrap" for both views. It is unclear to me why this works, or that it will continue to work, but I wanted to make note of it

Update #2

I took another look at why Remq's answer works. My experience is that without specifying app:layout_constraintWidth_min="wrap" for the views, both views collapse to zero width. Once the views measure out as zero width, app:layout_constraintWidth_min="wrap" grows them again so the contents are wrapped. This is just what I surmise and have no proof that this is what is going on, but it makes sense.



I have seen questions akin to this one on Stack Overflow a number of times. These questions never have a satisfactory answer IMO (including ones that I have answered.) The difficulty is that there is a dependency problem since one view depends on the width of another but that other view depends on the width of the first. We fall into a referential quandary. (Forcing widths programmatically is always an option but seems undesirable.)

Another and, probably, better approach is to use a custom ConstraintHelper that will inspect the sizes of the referenced views and adjust the width of all views to the width of the largest.

The custom ConstraintHelper is placed in the XML for the layout and references the effected views as in the following sample layout:

activity_main

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:gravity="center"
        android:text="Button1"
        app:layout_constraintBottom_toTopOf="@+id/button2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Button2 may be larger"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button1" />

    <com.example.constraintlayoutlayer.GreatestWidthHelper
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="button1,button2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

The custom ConstraintHelper looks like this:

GreatestWidthHelper

class GreatestWidthHelper @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {

    override fun updatePostMeasure(container: ConstraintLayout) {
        var maxWidth = 0

        // Find the greatest width of the referenced widgets.
        for (i in 0 until this.mCount) {
            val id = this.mIds[i]
            val child = container.getViewById(id)
            val widget = container.getViewWidget(child)
            if (widget.width > maxWidth) {
                maxWidth = widget.width
            }
        }

        // Set the width of all referenced view to the width of the view with the greatest width.
        for (i in 0 until this.mCount) {
            val id = this.mIds[i]
            val child = container.getViewById(id)
            val widget = container.getViewWidget(child)
            if (widget.width != maxWidth) {
                widget.width = maxWidth

                // Fix the gravity.
                if (child is TextView && child.gravity != Gravity.NO_GRAVITY) {
                    // Just toggle the gravity to make it right.
                    child.gravity = child.gravity.let { gravity ->
                        child.gravity = Gravity.NO_GRAVITY
                        gravity
                    }
                }
            }
        }
    }
}

The layout displays as shown below.

这篇关于约束布局 - 宽度最大的两个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆