web-dev-qa-db-fra.com

Aligner l'élément ConstraintLayout sur la fin de deux éléments

J'ai un ConstraintLayout avec deux vues A et B qui sont empilées verticalement. J'ai une troisième vue C qui doit être à la fin de A et B horizontalement. A tout moment, A peut être plus large que B ou inversement, la contrainte ne peut donc être basée que sur une seule vue. Existe-t-il un moyen de définir cette contrainte via la vue C?

Actuellement, je peux définir A et B pour que 

app:layout_constraintEnd_toStartOf="C"

Cela fonctionne, mais comme il n’ya pas de contrainte de début en C, l’aperçu de conception ne dessine pas correctement d’autres propriétés telles que

app:layout_constraintHorizontal_bias="1.0"

Une autre option peut être de regrouper les groupes A et B. La plupart des questions sur le regroupement parlent de chaînes, ce qui, à mon avis, ne résout pas ce problème. Ajouter une autre vue pour envelopper les deux semble également aller à l'encontre du but de ConstraintLayout, qui est censé éliminer les enfants imbriqués.

Edit: J'ai ci-joint un exemple ci-dessous:

<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="wrap_content">

    <TextView
        Android:id="@+id/view_c"
        Android:layout_width="wrap_content"
        Android:layout_height="0dp"
        Android:layout_marginStart="16dp"
        Android:text="View C"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />

    <TextView
        Android:id="@+id/view_a"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="16dp"
        Android:text="View A"
        app:layout_constraintBottom_toTopOf="@id/view_b"
        app:layout_constraintEnd_toStartOf="@id/view_c"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_goneMarginBottom="16dp" />

    <TextView
        Android:id="@+id/view_b"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginBottom="16dp"
        Android:text="View B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/view_c"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_a" />

</Android.support.constraint.ConstraintLayout>

Dans ce cas, l'aperçu devrait afficher "View C" quelque part au milieu car son biais est 0.5. Cependant, il ne connaît pas sa limite de départ car ils sont définis dans view_a et view_b, et reste donc à l'extrême droite.

Solution:

Ci-dessous ma mise en page finale dans son intégralité

<?xml version="1.0" encoding="utf-8"?>

<!--due to animations, we need a wrapper viewgroup so our changes will stick-->

<LinearLayout 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="wrap_content"
    Android:background="?android:attr/selectableItemBackground"
    Android:baselineAligned="false"
    Android:clipToPadding="false"
    Android:minHeight="?android:attr/listPreferredItemHeightSmall"
    Android:orientation="horizontal"
    Android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    Android:paddingStart="?android:attr/listPreferredItemPaddingStart">

    <Android.support.constraint.ConstraintLayout
        Android:id="@+id/kau_pref_container"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <!--As per Android N, icons (24dp) are aligned to the left rather than centered-->

        <ImageView
            Android:id="@+id/kau_pref_icon"
            Android:layout_width="56dp"
            Android:layout_height="56dp"
            Android:layout_marginBottom="4dp"
            Android:layout_marginTop="4dp"
            Android:contentDescription="@string/kau_pref_icon"
            Android:paddingEnd="32dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5"
            tools:layout_editor_absoluteX="0dp" />

        <TextView
            Android:id="@+id/kau_pref_title"
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="16dp"
            Android:ellipsize="Marquee"
            Android:textAppearance="?android:attr/textAppearanceListItem"
            Android:textColor="?android:attr/textColorPrimary"
            app:layout_constraintBottom_toTopOf="@+id/kau_pref_desc"
            app:layout_constraintEnd_toStartOf="@+id/kau_pref_inner_frame"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_icon"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_goneMarginBottom="16dp"
            tools:layout_editor_absoluteX="-175dp" />

        <TextView
            Android:id="@id/kau_pref_desc"
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_marginBottom="16dp"
            Android:ellipsize="end"
            Android:maxLines="10"
            Android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            Android:textColor="?android:attr/textColorSecondary"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/kau_pref_inner_frame"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_icon"
            app:layout_constraintTop_toBottomOf="@id/kau_pref_title"
            tools:layout_editor_absoluteX="-175dp" />

        <Android.support.constraint.Barrier
            Android:id="@+id/kau_pref_barrier"
            Android:layout_width="1dp"
            Android:layout_height="wrap_content"
            app:constraint_referenced_ids="kau_pref_title,kau_pref_desc"
            app:barrierDirection="end"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

        <LinearLayout
            Android:id="@id/kau_pref_inner_frame"
            Android:layout_width="wrap_content"
            Android:layout_height="0dp"
            Android:gravity="center_vertical|end"
            Android:orientation="horizontal"
            Android:paddingStart="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_barrier"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5"
            tools:layout_editor_absoluteX="1dp" />

    </Android.support.constraint.ConstraintLayout>

</LinearLayout>

Il y a un titre et une description, et le contenu interne doit être à la fin des deux vues. J'ai également essayé Group, qui est également nouveau dans la version bêta de la configuration des contraintes, mais il ne s'ajuste pas lorsqu'un enfant est marqué comme parti.

 Resulting layout

6
Allan W

Ceci peut être facilement réalisé en utilisant la nouvelle fonctionnalité Barriers

<?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="wrap_content">

    <TextView
        Android:id="@+id/view_c"
        Android:layout_width="wrap_content"
        Android:layout_height="0dp"
        Android:text="View C"
        app:layout_constraintLeft_toRightOf="@+id/barrier1"
        app:layout_constraintTop_toTopOf="parent" />

    <Android.support.constraint.Barrier
        Android:id="@+id/barrier1"
        Android:layout_width="1dp"
        Android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="view_a, view_b"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        Android:id="@+id/view_a"
        Android:layout_width="100dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="16dp"
        Android:text="View A"
        app:layout_constraintBottom_toTopOf="@id/view_b"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_goneMarginBottom="16dp" />

    <TextView
        Android:id="@+id/view_b"
        Android:layout_width="200dp"
        Android:layout_height="wrap_content"
        Android:layout_marginBottom="16dp"
        Android:text="View B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_a" />

</Android.support.constraint.ConstraintLayout>

Comment utiliser les barrières?

Les barrières ressemblent à la construction d’un MUR HUUUUGE qui "protège" les vues mentionnées dans constraint_referenced_ids. Donc, vous devez mentionner dans quelle direction il est "supposé rester en dehors" qui, dans notre cas, est le droit (view_c). Utilisez simplement l'attribut barrierDirection
Enfin, n'oubliez pas de vous assurer que view_c est dans la zone interdite (layout_constraintLeft_toRightOf="@+id/barrier1").

Comme cette fonctionnalité est disponible uniquement dans la version 1.1.0 beta1 de ConstraintLayout, n'oubliez pas d'ajouter cette ligne à votre fichier build.gradle.

compile 'com.Android.support.constraint:constraint-layout:1.1.0-beta1'


J'espère que cela t'aides!

6
Rami Jemli

J'ai essayé ceci dans mon IDE et je suis arrivé avec un code pour le faire dynamiquement à l'exécution

TextView viewa = (TextView) findViewById(R.id.view_a);
TextView viewb = (TextView) findViewById(R.id.view_b);

ConstraintLayout cl = (ConstraintLayout) findViewById(R.id.constraintLayout);
ConstraintSet cs = new ConstraintSet();
cs.clone(cl);
cs.connect(viewb.getWidth() > viewa.getWidth() ? R.id.view_b : R.id.view_a, ConstraintSet.RIGHT, R.id.view_c, ConstraintSet.LEFT);
cs.applyTo(cl);

Cela finit par le gâcher légèrement en poussant la vue plus large hors de l’écran de gauche. Peut-être que vous pourriez comprendre cela car je suis incapable de le faire à ce stade.

0
Eyad Kobatte