Android ConstraintLayout - 当有足够的空间时将视图定位到中心 space 并在必要时移动到边缘
Android ConstraintLayout - position view to center when there is enough space and move to edges if necessary
这是我要解决的案例:
所以,我的目标是:
- 如果有足够的 space,要让
View1
居中,这意味着 View2
没有那么宽,无法与 View1 重叠。
- 如果
View2
足够宽以至于无法将 View1
保持在中间而不重叠,那么在这种情况下将 View1
向左移动更多。
我已经尝试过的是:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_img"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/view2"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap" />
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:background="@color/black"
android:layout_height="50dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap"
app:layout_constraintWidth_percent="0.43" />
</androidx.constraintlayout.widget.ConstraintLayout>
在这些限制条件下,我告诉 View2
至少占用父级宽度的 43%,如果这还不够,那么就应用 wrap_content
。然后在 View1
中执行:
app:layout_constraintEnd_toStartOf="@+id/view2"
值 43% 只是估计值,在图片的第一种情况下,View1
几乎位于中心位置。但它在某些设备上不是很准确。
那么,是否有一种解决方案可以将 View1
准确定位在第一种情况的中心,然后在必要时将其移至左侧?
这不是 XML 所能完成的事情,AFAIK。不过,您可以使用一些代码来完成它。
更改布局,将 view2 限制在 ConstraintLayout 的右侧,将 view1 的右侧限制在 view2 的左侧。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/view1"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginEnd="8dp"
android:background="#2196F3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/view2"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view2"
android:layout_width="200dp"
android:layout_height="50dp"
android:background="#FF5722"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在,将以下代码放入主 activity。 (它可以放在其他地方,但主要的 activity 在这里用于演示目的。)此代码将操纵 view1 的右边距以将其放置在中心(如果它不与 view2 重叠)或推入在重叠的情况下向左。
val layout = findViewById<ConstraintLayout>(R.id.layout)
layout.doOnNextLayout {
val view1 = findViewById<View>(R.id.view1)
val view2 = findViewById<View>(R.id.view2)
val view1Margin =
if ((layout.width + view1.width) / 2 < view2.x) {
// view1 can be centered.
(view2.x - (layout.width + view1.width) / 2).toInt()
} else {
// view1 is pushed to left of center. 16dp is the right margin now.
(16 * resources.displayMetrics.density).toInt()
}
val lp = view1.layoutParams as ViewGroup.MarginLayoutParams
lp.rightMargin = view1Margin
view1.layoutParams = lp
}
现在当 view2 足够短时,view1 将居中:
而当view2较长时,view1会被推到一边
这是我要解决的案例:
所以,我的目标是:
- 如果有足够的 space,要让
View1
居中,这意味着View2
没有那么宽,无法与 View1 重叠。 - 如果
View2
足够宽以至于无法将View1
保持在中间而不重叠,那么在这种情况下将View1
向左移动更多。
我已经尝试过的是:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_img"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/view2"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap" />
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:background="@color/black"
android:layout_height="50dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap"
app:layout_constraintWidth_percent="0.43" />
</androidx.constraintlayout.widget.ConstraintLayout>
在这些限制条件下,我告诉 View2
至少占用父级宽度的 43%,如果这还不够,那么就应用 wrap_content
。然后在 View1
中执行:
app:layout_constraintEnd_toStartOf="@+id/view2"
值 43% 只是估计值,在图片的第一种情况下,View1
几乎位于中心位置。但它在某些设备上不是很准确。
那么,是否有一种解决方案可以将 View1
准确定位在第一种情况的中心,然后在必要时将其移至左侧?
这不是 XML 所能完成的事情,AFAIK。不过,您可以使用一些代码来完成它。
更改布局,将 view2 限制在 ConstraintLayout 的右侧,将 view1 的右侧限制在 view2 的左侧。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/view1"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginEnd="8dp"
android:background="#2196F3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/view2"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view2"
android:layout_width="200dp"
android:layout_height="50dp"
android:background="#FF5722"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在,将以下代码放入主 activity。 (它可以放在其他地方,但主要的 activity 在这里用于演示目的。)此代码将操纵 view1 的右边距以将其放置在中心(如果它不与 view2 重叠)或推入在重叠的情况下向左。
val layout = findViewById<ConstraintLayout>(R.id.layout)
layout.doOnNextLayout {
val view1 = findViewById<View>(R.id.view1)
val view2 = findViewById<View>(R.id.view2)
val view1Margin =
if ((layout.width + view1.width) / 2 < view2.x) {
// view1 can be centered.
(view2.x - (layout.width + view1.width) / 2).toInt()
} else {
// view1 is pushed to left of center. 16dp is the right margin now.
(16 * resources.displayMetrics.density).toInt()
}
val lp = view1.layoutParams as ViewGroup.MarginLayoutParams
lp.rightMargin = view1Margin
view1.layoutParams = lp
}
现在当 view2 足够短时,view1 将居中:
而当view2较长时,view1会被推到一边