繁体   English   中英

如何在ConstraintLayout中以编程方式相对于另一个View设置View的宽度/边距

[英]How to set width/margin of View programmatically relative another View within ConstraintLayout

我有一个ConstraintLayout。 出于本示例的目的,我们可以在其中包含三个视图。

<android.support.constraint.ConstraintLayout ...>

   <TextView
    android:id="@+id/text"
    .../>

   <TextView
    android:id="@+id/value"
    .../>

   <View
    android:id="@+id/bar"
    android:layout_width="0dp"
    android:layout_height="8dp"
    android:background="@color/bar_color"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="@+id/text"
    app:layout_constraintEnd_toStartOf="@id/value"
    />
</android.support.constraint.ConstraintLayout>

在运行时,我想将bar的宽度设置为textvalue之间的距离之间的某个value

我已经有一个介于0和100之间的值,它是两个文本视图之间的距离的百分比。

到目前为止,我已经尝试了两种方法,但是被卡住了。

尝试1

为此,我觉得我需要textvalue之间的实际距离以及一种正确设置条形宽度的方法。

我可以设置宽度bar通过执行以下操作:

val params: ConstraintLayout.LayoutParams = percentageBar.layoutParams as LayoutParams

params.matchConstraintMaxWidth = 300  // should be actual value rather than 300
percentageBar.layoutParams = params

这样可以设置条的宽度。 但是我需要一些方法来弄清楚实际数字应该是300,而不是300。诸如(百分比值*文本值距离/ 100)之类的东西。

尝试2

通过查看SO的其他答案,我发现了百分比约束。

...

<View
        android:id="@+id/bar"
        android:layout_width="0dp"
        android:layout_height="8dp"
        android:background="@color/bar_color"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/value"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@id/text"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="1.0"/>

...

然后,在代码中,我可以执行params.matchConstraintPercentWidth = item.percentageOfMaxValue.toFloat()

问题在于,当百分比值设置为较高时,它将采用父级的百分比,并超过value的起点。

我朝着正确的方向前进吗?

我希望我已经足够清楚地描述了这个问题。

提前致谢。

//更新

我推了一个简化的版本,类似于我遇到的问题。 GitHub上的BarProblem

您实际上可以从布局编辑器的“设计”选项卡中看到问题。

//更新2

问题解决了。 GitHub存储库现在包含该解决方案的代码。

对于您的情况,我的最佳解决方案是准则 这些助手是不会在您的应用程序中显示的锚点,它们就像是布局上方的一行网格,可用于将小部件附加或约束到它。

关键是我们需要等到ConstraintLayout布置好之后。 我们可以使用ViewTreeObserver.OnGlobalLayoutListener来做到这ViewTreeObserver.OnGlobalLayoutListener

解决方案示例:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        text.text = "Text"
        value.text = "Value"

        val globalLayoutListener = MainActivityGlobalListener(item_view, text, value, percentage_bar)

        item_view.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
    }
}

class MainActivityGlobalListener(private val itemView: View,
                                 private val text: View,
                                 private val value: View,
                                 private val bar: View) : ViewTreeObserver.OnGlobalLayoutListener {

    override fun onGlobalLayout() {
        Log.i("yoyo", "in onGlobalLayout")

        val width = value.x - (text.x)
        Log.i("yoyo", "Width: $width")

        val params: ConstraintLayout.LayoutParams = bar.layoutParams as ConstraintLayout.LayoutParams

        params.matchConstraintMaxWidth = (1.0 * width).toInt()  // using 0.1 here - this value is dynamic in real life scenario
        bar.layoutParams = params

        // required to prevent infinite loop
        itemView.viewTreeObserver.removeOnGlobalLayoutListener(this)
    }
}

请注意,需要删除最后一行的侦听器,以防止发生无限循环(侦听布局->设置条宽度->触发重新布局等)

如果使用Android KTX,我们可以简化为以下内容:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        text.text = "Text"
        value.text = "Value"

        item_view.doOnLayout {
            Log.i("yoyo", "in onGlobalLayout")

            val width = value.x - (text.x)
            Log.i("yoyo", "Width: $width")

            val params: ConstraintLayout.LayoutParams = percentage_bar.layoutParams as ConstraintLayout.LayoutParams

            params.matchConstraintMaxWidth = (1.0 * width).toInt()  // using 0.1 here - this value is dynamic in real life scenario
            percentage_bar.layoutParams = params
        }
    }

感谢CommonsWare的答案!

GitHub代码仓库

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM