在 Android Studio 中使用约束布局时的奇怪结果
Strange consequence when use Constraint Layout in Android Studio
我正处于 Android 开发的初期阶段。最近,为了练习布局设计,我正在尝试构建一个简单计算器的模拟。我在“设计”选项卡中创建并放置了视图(按钮、EditTexts)。然后我陷入 "This view is not constrained" 错误,所以我在 Whosebug 上搜索,最后找到解决方案是右键单击小部件 -> Constraint Layout -> Infer Constraints。但是当我这样做的时候,我程序中的那些视图发生了严重的变化,我无法将它们修改到原来的位置和大小。如何在不更改视图位置和大小的情况下解决错误?
这是我使用约束布局之前的计算器:
before_constraint:
这是我使用后的计算器:
after_constraint:
这是我的源代码:
<?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"
tools:context="com.huy9515gmail.helloworld.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<Button
android:id="@+id/button10"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="0"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="186dp" />
<Button
android:id="@+id/button7"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="7"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="141dp" />
<Button
android:id="@+id/button8"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="8"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="141dp" />
<Button
android:id="@+id/button9"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="9"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="141dp" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="My First Calculator"
tools:layout_editor_absoluteX="134dp"
tools:layout_editor_absoluteY="16dp" />
<Button
android:id="@+id/button"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="2"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button3"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="3"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button4"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="/"
tools:layout_editor_absoluteX="281dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button14"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="x"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button13"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="-"
tools:layout_editor_absoluteX="281dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button12"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="+"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button11"
android:layout_width="106dp"
android:layout_height="40dp"
android:text="Delete"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="210dp" />
<Button
android:id="@+id/button16"
android:layout_width="106dp"
android:layout_height="40dp"
android:text="Calculate"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="170dp" />
<Button
android:id="@+id/button15"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="1"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button2"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="4"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button5"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="5"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button6"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="6"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="96dp" />
<EditText
android:id="@+id/editText"
android:layout_width="310dp"
android:layout_height="98dp"
android:ems="10"
android:inputType="textPersonName"
tools:layout_editor_absoluteX="37dp"
tools:layout_editor_absoluteY="327dp" />
None 的视图受到限制,尽管它们都有设计时位置。看看这个documentation regarding run-time constraints. This也是不错的介绍
设计时位置是这样的:
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"
此代码将在设计器中定位您的视图。 运行-时间限制是这样的:
app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout”
app:layout_constraintEnd_toStartOf=”@+id/imageView”
app:layout_constraintStart_toStartOf=”@+id/constraintLayout”
并会在 运行 时间定位您的视图(以及在设计器中。)
不幸的是,当您推断约束时,发生了一些不好的事情。设计师做出了最好的猜测,但这不是我们想要的。
我建议您逐个查看布局,删除设计时约束并添加 运行 时间约束,直到您的布局看起来像您想要的那样。
硬编码值是在您“推断约束”时出现的。我建议您删除所有布局并重新开始,了解约束布局的工作原理。如果您看到“此视图不受约束”错误,Android Studio 告诉您的是:视图需要更多约束。
记住 iOS 上的 AutoLayout 和 Android 上的 ConstraintLayout(两者)的核心规则:每个视图都需要知道将自己定位在哪里(水平和垂直)并且它还需要知道它的大小又是什么,宽度和高度。
所以,想想你的布局……我给你举个例子。
从顶部开始,您希望“标签”与文本“欢迎使用我的计算器”居中。
很好,现在引擎需要知道 4 件事:
- 我应该把这个标签放在 X 轴的什么地方?
- 我应该把这个标签放在 Y 轴的哪个位置?
- 这个标签的宽度是多少?
- 这个标签的高度是多少?
有一些方法可以让引擎推断其中的一些(正如我们将要看到的),但对于大多数情况,您需要 这四个,per view(不管是推断的还是显式的)。
那么让我们从你的“标题”开始吧。
TextView 将居中,但我确定您希望它跨越它能找到的所有宽度(并在需要时压缩)。由于 ConstraintLayout 没有 match_parent
(原因很明显:a.k.a。:这个想法是你必须设置约束),我们必须能够以不同的方式来做……
对于 X 轴(水平),我们希望将 textView 固定到 parent
的 start
(又名:本例中的根),以及 end
的 parent (有效地使用所有屏幕,减去您决定在任一侧添加的任何边距)。
到目前为止,有两个约束。为了使上面的工作正常,ConstraintLayout 说你必须在 width
中使用 0dp
的“特殊”值。这告诉引擎宽度将是“我还不知道的任何值,在我计算完所有约束后我会知道”。
很好。现在我们已经解决了#1 和#3。
对于#2 和#4,你可以做类似的事情......或者你可以享受一些观点具有推断值的事实。例如:文本视图不需要高度,它们将根据字体大小、字符数等 auto-size,但您仍然需要告诉它文本视图在 Y
轴的哪个位置会去的
对于您的情况,我只是将文本视图的 top
与您的 parent.top
对齐。请注意,您不需要告诉布局将文本的 bottom
固定到任何内容,因为它的高度 = wrap_content
.
等等……
现在转到 the official docs 并开始阅读有关您可以做的事情的更多信息(例如,锁链在这里可能会派上用场)。
我正处于 Android 开发的初期阶段。最近,为了练习布局设计,我正在尝试构建一个简单计算器的模拟。我在“设计”选项卡中创建并放置了视图(按钮、EditTexts)。然后我陷入 "This view is not constrained" 错误,所以我在 Whosebug 上搜索,最后找到解决方案是右键单击小部件 -> Constraint Layout -> Infer Constraints。但是当我这样做的时候,我程序中的那些视图发生了严重的变化,我无法将它们修改到原来的位置和大小。如何在不更改视图位置和大小的情况下解决错误?
这是我使用约束布局之前的计算器:
before_constraint:
这是我使用后的计算器:
after_constraint:
这是我的源代码:
<?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"
tools:context="com.huy9515gmail.helloworld.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<Button
android:id="@+id/button10"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="0"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="186dp" />
<Button
android:id="@+id/button7"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="7"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="141dp" />
<Button
android:id="@+id/button8"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="8"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="141dp" />
<Button
android:id="@+id/button9"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="9"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="141dp" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="My First Calculator"
tools:layout_editor_absoluteX="134dp"
tools:layout_editor_absoluteY="16dp" />
<Button
android:id="@+id/button"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="2"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button3"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="3"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button4"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="/"
tools:layout_editor_absoluteX="281dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button14"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="x"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button13"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="-"
tools:layout_editor_absoluteX="281dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button12"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="+"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button11"
android:layout_width="106dp"
android:layout_height="40dp"
android:text="Delete"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="210dp" />
<Button
android:id="@+id/button16"
android:layout_width="106dp"
android:layout_height="40dp"
android:text="Calculate"
tools:layout_editor_absoluteX="228dp"
tools:layout_editor_absoluteY="170dp" />
<Button
android:id="@+id/button15"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="1"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="51dp" />
<Button
android:id="@+id/button2"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="4"
tools:layout_editor_absoluteX="34dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button5"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="5"
tools:layout_editor_absoluteX="87dp"
tools:layout_editor_absoluteY="96dp" />
<Button
android:id="@+id/button6"
android:layout_width="53dp"
android:layout_height="45dp"
android:text="6"
tools:layout_editor_absoluteX="140dp"
tools:layout_editor_absoluteY="96dp" />
<EditText
android:id="@+id/editText"
android:layout_width="310dp"
android:layout_height="98dp"
android:ems="10"
android:inputType="textPersonName"
tools:layout_editor_absoluteX="37dp"
tools:layout_editor_absoluteY="327dp" />
None 的视图受到限制,尽管它们都有设计时位置。看看这个documentation regarding run-time constraints. This也是不错的介绍
设计时位置是这样的:
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"
此代码将在设计器中定位您的视图。 运行-时间限制是这样的:
app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout”
app:layout_constraintEnd_toStartOf=”@+id/imageView”
app:layout_constraintStart_toStartOf=”@+id/constraintLayout”
并会在 运行 时间定位您的视图(以及在设计器中。)
不幸的是,当您推断约束时,发生了一些不好的事情。设计师做出了最好的猜测,但这不是我们想要的。
我建议您逐个查看布局,删除设计时约束并添加 运行 时间约束,直到您的布局看起来像您想要的那样。
硬编码值是在您“推断约束”时出现的。我建议您删除所有布局并重新开始,了解约束布局的工作原理。如果您看到“此视图不受约束”错误,Android Studio 告诉您的是:视图需要更多约束。
记住 iOS 上的 AutoLayout 和 Android 上的 ConstraintLayout(两者)的核心规则:每个视图都需要知道将自己定位在哪里(水平和垂直)并且它还需要知道它的大小又是什么,宽度和高度。
所以,想想你的布局……我给你举个例子。
从顶部开始,您希望“标签”与文本“欢迎使用我的计算器”居中。
很好,现在引擎需要知道 4 件事:
- 我应该把这个标签放在 X 轴的什么地方?
- 我应该把这个标签放在 Y 轴的哪个位置?
- 这个标签的宽度是多少?
- 这个标签的高度是多少?
有一些方法可以让引擎推断其中的一些(正如我们将要看到的),但对于大多数情况,您需要 这四个,per view(不管是推断的还是显式的)。
那么让我们从你的“标题”开始吧。
TextView 将居中,但我确定您希望它跨越它能找到的所有宽度(并在需要时压缩)。由于 ConstraintLayout 没有 match_parent
(原因很明显:a.k.a。:这个想法是你必须设置约束),我们必须能够以不同的方式来做……
对于 X 轴(水平),我们希望将 textView 固定到 parent
的 start
(又名:本例中的根),以及 end
的 parent (有效地使用所有屏幕,减去您决定在任一侧添加的任何边距)。
到目前为止,有两个约束。为了使上面的工作正常,ConstraintLayout 说你必须在 width
中使用 0dp
的“特殊”值。这告诉引擎宽度将是“我还不知道的任何值,在我计算完所有约束后我会知道”。
很好。现在我们已经解决了#1 和#3。
对于#2 和#4,你可以做类似的事情......或者你可以享受一些观点具有推断值的事实。例如:文本视图不需要高度,它们将根据字体大小、字符数等 auto-size,但您仍然需要告诉它文本视图在 Y
轴的哪个位置会去的
对于您的情况,我只是将文本视图的 top
与您的 parent.top
对齐。请注意,您不需要告诉布局将文本的 bottom
固定到任何内容,因为它的高度 = wrap_content
.
等等……
现在转到 the official docs 并开始阅读有关您可以做的事情的更多信息(例如,锁链在这里可能会派上用场)。