ConstraintLayout with Barriers; How to constraint to bottom / top of barrier depending on size

时光怂恿深爱的人放手 提交于 2019-12-30 05:14:12

问题


I am trying out the new Barrier feature in the 1.1.0-beta1. It works as expected however there is this use-case I cant seem to figure or (or is possible ConstraintLayout at all?)

What I am trying to accomplish is: I have a imageview to the left, and title and subtitle textviews to the right of the imageview. Imageview is fixed height. I have a button, that is bottom constrained to the bottom of the imageview however should be top constrained to the bottom of the subtitle textview, if subtitletextview is taller than imageview.

(Btw I also tried having it bottom constrained to bottom of imageview, and topconstrained to bottom of textview and giving it 1.0 bias towards bottom, but didnt work with large text case)

With barriers I am only able to get button top constrained to bottom of barrier (or top, seemed to to the same)

<?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>

Both states in images:


回答1:


Here is a layout that will work for you. It is a little complicated but does what you want. Here is how it works and is set up:

  • Define an invisible button, blockingButton, that has the same dimensions as your other button. Constrain this button to the bottom of your left ImageView.

  • On top of blockingButton, place a Space widget. The location of this Space widget will define the maximum height that the bottom button will float to.

  • Define a barrier that floats below the Space widget and the large TextView.

  • Finally, constrain the top of your floating button to the barrier.

As the size of the text changes in the large TextView, the button will float up as far as the Space widget but no farther. As the TextView grows, it will push down the barrier and the bottom button.

Here is a 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>



回答2:


@Cheticamp 's answer is great, but he doesn't explain how he came up that idea.

Here is how I came up another solution inspired by his solution.

What we want to achieve is to put the button as high as possible, but it should be constrained to two limits:

  1. button.bottom >= image.bottom

  2. button.top >= text.bottom

We can use Barrier to satisfy these two requirements, but we need to modify one of them, I choose to modify the second one:

button.top >= text.bottom <=> button.bottom >= text.bottom + button.height

Now we have these two constraints:

  1. button.bottom >= image.bottom

  2. button.bottom >= text.bottom + button.height

Now we can place a fake button below the TextView like this:

<?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>


来源:https://stackoverflow.com/questions/44232501/constraintlayout-with-barriers-how-to-constraint-to-bottom-top-of-barrier-dep

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!