尝试使用 ConstraintLayout 复制 GridLayout 列对齐
Trying to replicate GridLayout column alignment with ConstraintLayout
我是 ConstraintLayout 的新手,我正在尝试使用 ConstraintLayout 复制 GridLayout 提供的相同网格行为。
具体来说,我想设计一个两列的网格。第一列宽度应尽可能窄,而第二列应占据所有剩余的水平 space。当然,第二列应该就在第一列的右边,或者更确切地说,在第一列的最宽视图。
我不知道如何使用 ConstraintLayout 复制最后一个要求。我不想在两列之间使用网格线,因为第一列不应具有固定宽度或百分比宽度,而应与其视图的最宽宽度一样宽。
在 https://gist.github.com/venator85/499dd82f47b3efbbed7a1e9e1ca1412d 我准备了一个布局示例和相应的预览,显示了实现我想要的内容的 GridLayout。该布局中的前两个 ConstraintLayout 尝试显示 C1 和 D1 与 B1 对齐,C2 和 D2 与 B2 对齐。当B2比A2窄时,A1和C1会重叠
有什么帮助吗?
谢谢
更新:请参阅 。
我怀疑是否有一种方法可以完全按照 XML 的方式用 ConstraintLayout
复制 GridLayout
。如果您愿意让一些代码协助布局,那么您可以使用可移动的垂直参考线将 ConstraintLayout
设置为 GridLayout
。
按照您描述的那样在两列中构建 XML 布局。左栏中每个TextView
的顶部将被限制在右栏中相应TextView
的顶部,因此左侧条目将随着右侧条目的增加或减少而上下浮动身高。
所有右侧的列视图都将被限制在左侧,以符合上述垂直准则。此指南在 XML 中的放置应该是合理的,但实际放置将在代码中进行,并将根据左侧最宽视图的宽度进行调整。
这是您提出的问题的解决方案,但不是通用解决方案。以下取决于左边每个TextView
的高度小于或等于右边对应TextView
的高度。
这是 Android Studio 布局编辑器中的布局。我把指南推到右边来演示它是如何浮动的。 (代码跟随图像。)
这是一个屏幕截图。我希望你觉得这很有用。
这里是使用 ConstraintLayout
的布局。 (自初始 post 开始更新,以便在左栏中右转。)
constrained.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constrained"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="257dp" />
<TextView
android:id="@+id/L1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:text="A1 A1 A1 A1 A1*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="B1 B1 B1 B1 B1*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R2"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="A2 A2 A2 A2*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R3"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="B2 B2 B2 B2 B2*"
app:layout_constraintHorizontal_bias="0.02"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R4"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1*"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1*"
app:layout_constraintLeft_toRightOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/R1"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2*"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/R2"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2*"
app:layout_constraintLeft_toRightOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/R3"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>
这里是调整引导线位置的Activity
MainActivity.java
package com.example.layout2;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.Guideline;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Guideline mGuideline;
private ConstraintLayout mConstraintLayout;
private TextView L1;
private TextView L2;
private TextView L3;
private TextView L4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.constrained);
mConstraintLayout = (ConstraintLayout) findViewById(R.id.constrained);
mGuideline = (Guideline) findViewById(R.id.guideline);
L1 = (TextView) findViewById(R.id.L1);
L2 = (TextView) findViewById(R.id.L2);
L3 = (TextView) findViewById(R.id.L3);
L4 = (TextView) findViewById(R.id.L4);
// We will adjust the location of the guideline after layout is completed.
mConstraintLayout.post(new Runnable() {
@Override
public void run() {
moveGuideline();
}
});
}
public void moveGuideline() {
ConstraintLayout.LayoutParams params;
params = (ConstraintLayout.LayoutParams) mGuideline.getLayoutParams();
// Find the widest TextView in the left column...
params.guideBegin = Math.max(Math.max(L1.getWidth(), L2.getWidth()),
Math.max(L3.getWidth(), L4.getWidth()));
// ... and set the guideline to the right of the widest one.
mGuideline.setLayoutParams(params);
}
}
试试这个。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="A1 A1 A1 A1 "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="C1 C1 C1 C1 "
app:layout_constraintHorizontal_bias="0.506"
app:layout_constraintLeft_toRightOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="B1 B1 B1 B1 "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/textView8"
app:layout_constraintTop_toBottomOf="@+id/textView8" />
<TextView
android:id="@+id/textView10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="D1 D1 D1 D1 "
app:layout_constraintHorizontal_bias="0.506"
app:layout_constraintLeft_toRightOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
</android.support.constraint.ConstraintLayout>
像这样。
更新
接受的答案是正确的。当我在 2017 年 3 月回答这个问题时,这是唯一的选择。两个月后,Google 引入了障碍。
我认为目前不可能只用一个 ConstraintLayout
容器来执行。我希望将来 Google 会添加类似 group_id
的内容或其他一些计算布局的方式“对齐到组”。
同时,我建议您在 ConstraintLayout
中使用 ConstraintLayout
个容器。
我是这样实现的:
为了使行像“网格”一样,我使用了“”。每个 ConstraintLayout
链中的行数必须相同,因此自动分配将正确对齐行。 (尽管如果不使用它们可以留空或隐藏)。
Google 在 ConstraintLayout
的最新版本中引入了 "barriers" 的想法,这有助于在 XML 中 100% 解决这个问题。请参阅涉及新内容的 ConstraintLayout 1.1.0 beta 1 release notes . Although, that note doesn't contain a lot of information on the new capabilities there was a talk at I/O 2017。
新的解决方案是用障碍复制 GridLayout
的网格。在左侧 TextView
的右侧放置了一个垂直屏障,在前三行下方放置了一个屏障。障碍根据每个 TextView
中存在的文本数量而变化,但始终保持 app:constraint_referenced_ids
中指定的位置。从本质上讲,障碍就像浮动指南。此解决方案不依赖任何编码来支持视频中的内容。
这是一个 video of the new layout,它显示了每个 TextView
在另一个 TextView
的内容发生变化时所需要的定位。该视频是使用 Android Studio 2.3.2 的设计工具制作的。
和 XML 使用障碍的新布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constrained"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Barrier
android:id="@+id/barrierVertical"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:barrierDirection="right"
app:constraint_referenced_ids="L1, L2, L3, L4" />
<TextView
android:id="@+id/L1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L1 *"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier1"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L1, R1" />
<TextView
android:id="@+id/L2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L2 L2*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier1"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier1"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier2"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L2, R2" />
<TextView
android:id="@+id/L3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L3 L3 L3*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier2"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3*"
app:layout_constraintLeft_toRightOf="@id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier2"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier3"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L3, R3" />
<TextView
android:id="@+id/L4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L4 L4 L4 L4 L4 L4*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier3"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/R4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier3"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>
我是 ConstraintLayout 的新手,我正在尝试使用 ConstraintLayout 复制 GridLayout 提供的相同网格行为。
具体来说,我想设计一个两列的网格。第一列宽度应尽可能窄,而第二列应占据所有剩余的水平 space。当然,第二列应该就在第一列的右边,或者更确切地说,在第一列的最宽视图。
我不知道如何使用 ConstraintLayout 复制最后一个要求。我不想在两列之间使用网格线,因为第一列不应具有固定宽度或百分比宽度,而应与其视图的最宽宽度一样宽。
在 https://gist.github.com/venator85/499dd82f47b3efbbed7a1e9e1ca1412d 我准备了一个布局示例和相应的预览,显示了实现我想要的内容的 GridLayout。该布局中的前两个 ConstraintLayout 尝试显示 C1 和 D1 与 B1 对齐,C2 和 D2 与 B2 对齐。当B2比A2窄时,A1和C1会重叠
有什么帮助吗?
谢谢
更新:请参阅
我怀疑是否有一种方法可以完全按照 XML 的方式用 ConstraintLayout
复制 GridLayout
。如果您愿意让一些代码协助布局,那么您可以使用可移动的垂直参考线将 ConstraintLayout
设置为 GridLayout
。
按照您描述的那样在两列中构建 XML 布局。左栏中每个TextView
的顶部将被限制在右栏中相应TextView
的顶部,因此左侧条目将随着右侧条目的增加或减少而上下浮动身高。
所有右侧的列视图都将被限制在左侧,以符合上述垂直准则。此指南在 XML 中的放置应该是合理的,但实际放置将在代码中进行,并将根据左侧最宽视图的宽度进行调整。
这是您提出的问题的解决方案,但不是通用解决方案。以下取决于左边每个TextView
的高度小于或等于右边对应TextView
的高度。
这是 Android Studio 布局编辑器中的布局。我把指南推到右边来演示它是如何浮动的。 (代码跟随图像。)
这是一个屏幕截图。我希望你觉得这很有用。
这里是使用 ConstraintLayout
的布局。 (自初始 post 开始更新,以便在左栏中右转。)
constrained.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constrained"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="257dp" />
<TextView
android:id="@+id/L1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:text="A1 A1 A1 A1 A1*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="B1 B1 B1 B1 B1*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R2"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="A2 A2 A2 A2*"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R3"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/L4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:text="B2 B2 B2 B2 B2*"
app:layout_constraintHorizontal_bias="0.02"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/R4"
app:layout_constraintWidth_default="wrap"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1*"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1*"
app:layout_constraintLeft_toRightOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/R1"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2*"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/R2"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2*"
app:layout_constraintLeft_toRightOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/R3"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>
这里是调整引导线位置的Activity
MainActivity.java
package com.example.layout2;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.Guideline;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Guideline mGuideline;
private ConstraintLayout mConstraintLayout;
private TextView L1;
private TextView L2;
private TextView L3;
private TextView L4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.constrained);
mConstraintLayout = (ConstraintLayout) findViewById(R.id.constrained);
mGuideline = (Guideline) findViewById(R.id.guideline);
L1 = (TextView) findViewById(R.id.L1);
L2 = (TextView) findViewById(R.id.L2);
L3 = (TextView) findViewById(R.id.L3);
L4 = (TextView) findViewById(R.id.L4);
// We will adjust the location of the guideline after layout is completed.
mConstraintLayout.post(new Runnable() {
@Override
public void run() {
moveGuideline();
}
});
}
public void moveGuideline() {
ConstraintLayout.LayoutParams params;
params = (ConstraintLayout.LayoutParams) mGuideline.getLayoutParams();
// Find the widest TextView in the left column...
params.guideBegin = Math.max(Math.max(L1.getWidth(), L2.getWidth()),
Math.max(L3.getWidth(), L4.getWidth()));
// ... and set the guideline to the right of the widest one.
mGuideline.setLayoutParams(params);
}
}
试试这个。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="A1 A1 A1 A1 "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="C1 C1 C1 C1 "
app:layout_constraintHorizontal_bias="0.506"
app:layout_constraintLeft_toRightOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="B1 B1 B1 B1 "
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/textView8"
app:layout_constraintTop_toBottomOf="@+id/textView8" />
<TextView
android:id="@+id/textView10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="D1 D1 D1 D1 "
app:layout_constraintHorizontal_bias="0.506"
app:layout_constraintLeft_toRightOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
</android.support.constraint.ConstraintLayout>
像这样。
更新
接受的答案是正确的。当我在 2017 年 3 月回答这个问题时,这是唯一的选择。两个月后,Google 引入了障碍。
我认为目前不可能只用一个 ConstraintLayout
容器来执行。我希望将来 Google 会添加类似 group_id
的内容或其他一些计算布局的方式“对齐到组”。
同时,我建议您在 ConstraintLayout
中使用 ConstraintLayout
个容器。
我是这样实现的:
为了使行像“网格”一样,我使用了“ConstraintLayout
链中的行数必须相同,因此自动分配将正确对齐行。 (尽管如果不使用它们可以留空或隐藏)。
Google 在 ConstraintLayout
的最新版本中引入了 "barriers" 的想法,这有助于在 XML 中 100% 解决这个问题。请参阅涉及新内容的 ConstraintLayout 1.1.0 beta 1 release notes . Although, that note doesn't contain a lot of information on the new capabilities there was a talk at I/O 2017。
新的解决方案是用障碍复制 GridLayout
的网格。在左侧 TextView
的右侧放置了一个垂直屏障,在前三行下方放置了一个屏障。障碍根据每个 TextView
中存在的文本数量而变化,但始终保持 app:constraint_referenced_ids
中指定的位置。从本质上讲,障碍就像浮动指南。此解决方案不依赖任何编码来支持视频中的内容。
这是一个 video of the new layout,它显示了每个 TextView
在另一个 TextView
的内容发生变化时所需要的定位。该视频是使用 Android Studio 2.3.2 的设计工具制作的。
和 XML 使用障碍的新布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constrained"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Barrier
android:id="@+id/barrierVertical"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:barrierDirection="right"
app:constraint_referenced_ids="L1, L2, L3, L4" />
<TextView
android:id="@+id/L1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L1 *"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier1"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L1, R1" />
<TextView
android:id="@+id/L2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L2 L2*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier1"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier1"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier2"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L2, R2" />
<TextView
android:id="@+id/L3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L3 L3 L3*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier2"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/R3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3*"
app:layout_constraintLeft_toRightOf="@id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier2"
tools:ignore="HardcodedText" />
<android.support.constraint.Barrier
android:id="@+id/barrier3"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="L3, R3" />
<TextView
android:id="@+id/L4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="L4 L4 L4 L4 L4 L4*"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier3"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/R4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4*"
app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier3"
tools:ignore="HardcodedText" />
</android.support.constraint.ConstraintLayout>