带障碍的约束布局;如何根据尺寸限制到障碍物的底部/顶部
ConstraintLayout with Barriers; How to constraint to bottom / top of barrier depending on size
我正在试用 1.1.0-beta1 中的新屏障功能。它按预期工作但是有这个use-case我似乎无法理解或者(或者根本不可能的ConstraintLayout?)
我想要完成的是:我在左侧有一个图像视图,在图像视图的右侧有标题和副标题文本视图。 Imageview 是固定高度的。我有一个按钮,底部限制在图像视图的底部但是应该顶部限制在字幕文本视图的底部,如果字幕文本视图比图像视图高。
(顺便说一句,我也试过将其底部约束到图像视图的底部,将顶部约束到文本视图的底部,并给它 1.0 偏向底部,但不适用于大文本大小写)
有了障碍,我只能将按钮顶部限制在障碍底部(或顶部,似乎相同)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@color/blue"/>
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:scaleType="centerCrop"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/books"/>
<ImageView
android:id="@+id/imageView6"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"
app:srcCompat="@android:drawable/radiobutton_on_background"/>
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView6"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"/>
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView4"
app:layout_constraintRight_toRightOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
图片中的两种状态:
这是适合您的布局。它有点复杂,但可以做你想做的。这是它的工作原理和设置方式:
定义一个不可见按钮 blockingButton
,它与您的其他按钮具有相同的尺寸。将此按钮限制在左下方 ImageView
.
在 blockingButton
之上,放置一个 Space
小部件。此 Space
小部件的位置将定义底部按钮浮动的最大高度。
定义一个漂浮在 Space
小部件和大 TextView
.
下方的屏障
最后,将浮动按钮的顶部限制在屏障上。
随着大 TextView
中文本大小的变化,按钮将向上浮动至 Space
小部件,但不会更远。随着 TextView
的增长,它将向下推障碍物和底部按钮。
这里是short video.
<?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">
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@color/blue" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/books" />
<ImageView
android:id="@+id/imageView6"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"
app:srcCompat="@android:drawable/radiobutton_on_background"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView6"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4" />
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView4"
app:layout_constraintRight_toRightOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4"
app:layout_constraintHorizontal_bias="0.0" />
<!-- This is the start of the changes. -->
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier" />
<Button
android:id="@+id/blockingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/imageView6"
app:layout_constraintLeft_toLeftOf="@+id/imageView6" />
<android.support.v4.widget.Space
android:id="@+id/spacer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/blockingButton" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="bottom"
app:constraint_referenced_ids="spacer, textView5" />
</android.support.constraint.ConstraintLayout>
@Cheticamp 的回答很好,但他没有解释他是如何想到这个想法的。
以下是我如何根据他的解决方案得出另一个解决方案。
我们要实现的是把按钮放得尽可能高,但是要限制在两个限度内:
button.bottom >= image.bottom
button.top >= text.bottom
我们可以用Barrier
来满足这两个需求,但是我们需要修改其中一个,我选择修改第二个:
button.top >= text.bottom <=> button.bottom >= text.bottom + button.height
现在我们有这两个约束:
button.bottom >= image.bottom
button.bottom >= text.bottom + button.height
现在我们可以像这样在 TextView
下面放置一个假按钮:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/radiobutton_on_background"/>
<TextView
android:id="@+id/textView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView1"
app:layout_constraintRight_toRightOf="@+id/textView1"
app:layout_constraintTop_toBottomOf="@+id/textView1"/>
<Button
android:id="@+id/button_fake"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:visibility="invisible"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:layout_constraintRight_toRightOf="parent"/>
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="imageView,button_fake"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="@+id/barrier"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
我正在试用 1.1.0-beta1 中的新屏障功能。它按预期工作但是有这个use-case我似乎无法理解或者(或者根本不可能的ConstraintLayout?)
我想要完成的是:我在左侧有一个图像视图,在图像视图的右侧有标题和副标题文本视图。 Imageview 是固定高度的。我有一个按钮,底部限制在图像视图的底部但是应该顶部限制在字幕文本视图的底部,如果字幕文本视图比图像视图高。
(顺便说一句,我也试过将其底部约束到图像视图的底部,将顶部约束到文本视图的底部,并给它 1.0 偏向底部,但不适用于大文本大小写)
有了障碍,我只能将按钮顶部限制在障碍底部(或顶部,似乎相同)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@color/blue"/>
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:scaleType="centerCrop"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/books"/>
<ImageView
android:id="@+id/imageView6"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"
app:srcCompat="@android:drawable/radiobutton_on_background"/>
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView6"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"/>
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView4"
app:layout_constraintRight_toRightOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
图片中的两种状态:
这是适合您的布局。它有点复杂,但可以做你想做的。这是它的工作原理和设置方式:
定义一个不可见按钮
blockingButton
,它与您的其他按钮具有相同的尺寸。将此按钮限制在左下方ImageView
.在
blockingButton
之上,放置一个Space
小部件。此Space
小部件的位置将定义底部按钮浮动的最大高度。定义一个漂浮在
Space
小部件和大TextView
. 下方的屏障
最后,将浮动按钮的顶部限制在屏障上。
随着大 TextView
中文本大小的变化,按钮将向上浮动至 Space
小部件,但不会更远。随着 TextView
的增长,它将向下推障碍物和底部按钮。
这里是short video.
<?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">
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@color/blue" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/books" />
<ImageView
android:id="@+id/imageView6"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4"
app:srcCompat="@android:drawable/radiobutton_on_background"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView6"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4" />
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView4"
app:layout_constraintRight_toRightOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4"
app:layout_constraintHorizontal_bias="0.0" />
<!-- This is the start of the changes. -->
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier" />
<Button
android:id="@+id/blockingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/imageView6"
app:layout_constraintLeft_toLeftOf="@+id/imageView6" />
<android.support.v4.widget.Space
android:id="@+id/spacer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/blockingButton" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="bottom"
app:constraint_referenced_ids="spacer, textView5" />
</android.support.constraint.ConstraintLayout>
@Cheticamp 的回答很好,但他没有解释他是如何想到这个想法的。
以下是我如何根据他的解决方案得出另一个解决方案。
我们要实现的是把按钮放得尽可能高,但是要限制在两个限度内:
button.bottom >= image.bottom
button.top >= text.bottom
我们可以用Barrier
来满足这两个需求,但是我们需要修改其中一个,我选择修改第二个:
button.top >= text.bottom <=> button.bottom >= text.bottom + button.height
现在我们有这两个约束:
button.bottom >= image.bottom
button.bottom >= text.bottom + button.height
现在我们可以像这样在 TextView
下面放置一个假按钮:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="124dp"
android:layout_height="156dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/radiobutton_on_background"/>
<TextView
android:id="@+id/textView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/imageView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Lorem Ipsum je fiktívny text, používaný pri návrhu tlačovín a typografie. Lorem Ipsum je štandardným výplňovým textom už od 16. storočia, keď neznámy tlačiar zobral sadzobnicu plnú tlačových znakov a pomiešal ich, aby tak vytvoril vzorkovú knihu. Prežil nielen päť storočí, ale aj skok do elektronickej sadzby, a pritom zostal v podstate nezmenený. Spopularizovaný bol v 60-tych rokoch 20.storočia, vydaním hárkov Letraset, ktoré obsahovali pasáže Lorem Ipsum, a neskôr aj publikačným softvérom"
app:layout_constraintLeft_toLeftOf="@+id/textView1"
app:layout_constraintRight_toRightOf="@+id/textView1"
app:layout_constraintTop_toBottomOf="@+id/textView1"/>
<Button
android:id="@+id/button_fake"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:visibility="invisible"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:layout_constraintRight_toRightOf="parent"/>
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="imageView,button_fake"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="@+id/barrier"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>