web-dev-qa-db-fra.com

Comment centrer plusieurs vues ensemble à l'aide de ConstraintLayout?

Contexte

Google a annoncé une nouvelle mise en page appelée " ConstraintLayout " qui est supposée être la mise en page idéale, qui pourrait remplacer toutes les mises en page. tout en restant à plat (sans dispositions imbriquées) et avoir une meilleure performance.

Le problème

Le fait est que je ne vois pratiquement aucun didacticiel susceptible de m'aider à ce sujet, autre que la vidéo présentée sur Google IO.

Ce que j'essaie de faire, c'est que, étant donné que j'ai un LinearLayout verticalement centré dans une autre mise en page, convertissez les deux en un seul ConstraintLayout.

Après tout, c’est le but de cette nouvelle mise en page ...

La mise en page que je souhaite traiter ressemble à ceci:

enter image description here

Notez que les vues situées au centre ne sont centrées que verticalement et que les 2 vues textuelles se trouvent à droite de la vue Image, qui est également centrée verticalement.

Tout cela fonctionne bien avec RelativeLayout, qui a le LinearLayout des 2 TextViews, mais je souhaite savoir comment les convertir en un seul ConstraintLayout.

Voici un exemple de XML de ce que j'ai montré:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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:minHeight="?attr/listPreferredItemHeightSmall">

    <ImageView
        Android:id="@+id/appIconImageView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentStart="true"
        Android:layout_centerVertical="true"
        Android:layout_marginEnd="4dp"
        Android:layout_marginLeft="2dp"
        Android:layout_marginRight="4dp"
        Android:layout_marginStart="2dp"
        Android:adjustViewBounds="true"
        Android:src="@Android:drawable/sym_def_app_icon"
        tools:ignore="ContentDescription"/>

    <LinearLayout
        Android:id="@+id/appDetailsContainer"
        Android:layout_width="0px"
        Android:layout_height="wrap_content"
        Android:layout_centerVertical="true"
        Android:layout_toEndOf="@+id/appIconImageView"
        Android:layout_toLeftOf="@+id/overflowView"
        Android:layout_toRightOf="@+id/appIconImageView"
        Android:layout_toStartOf="@+id/overflowView"
        Android:orientation="vertical">

        <TextView
            Android:id="@+id/appLabelTextView"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:ellipsize="Marquee"
            Android:text="label"
            Android:textAppearance="?android:attr/textAppearanceLarge"
            Android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>

        <TextView
            Android:id="@+id/appDescriptionTextView"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:ellipsize="Marquee"
            Android:minLines="3"
            Android:text="description"
            Android:textAppearance="?android:attr/textAppearanceSmall"
            Android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>
    </LinearLayout>

    <ImageView
        Android:id="@+id/overflowView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentEnd="true"
        Android:layout_alignParentRight="true"
        Android:layout_alignParentTop="true"
        Android:adjustViewBounds="true"
        Android:background="?attr/selectableItemBackground"
        Android:clickable="true"
        Android:padding="10dp"
        app:srcCompat="@drawable/ic_more_vert_black_24dp"

        tools:src="@drawable/ic_more_vert_black_24dp"
        tools:ignore="ContentDescription"/>

    <ImageView
        Android:id="@+id/isSystemAppImageView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignEnd="@+id/overflowView"
        Android:layout_alignLeft="@+id/overflowView"
        Android:layout_alignParentBottom="true"
        Android:layout_alignRight="@+id/overflowView"
        Android:layout_alignStart="@+id/overflowView"
        Android:adjustViewBounds="true"
        Android:scaleType="centerInside"
        app:srcCompat="@drawable/ic_warning_black_24dp"
        tools:ignore="ContentDescription"
        tools:src="@drawable/ic_warning_black_24dp"/>

</RelativeLayout>

Ce que j'ai essayé

J'ai essayé de lire des articles et de regarder des vidéos de Google:

Cela n’a pas aidé, j’ai donc essayé de l’utiliser, dans l’espoir de découvrir comment l’utiliser moi-même. Mais je ne peux pas savoir comment le faire. J'ai essayé d'utiliser la fonctionnalité pour convertir les mises en page, mais cela gâche énormément les vues et crée des marges supplémentaires que je ne souhaite pas avoir.

La question

Comment puis-je convertir les 2 mises en page en un seul ConstraintLayout?

43

Regardez ma réponse ici .

ContraintLayout contient une fonctionnalité - Chains - qui permet de mettre en œuvre ce que vous demandez:

Les chaînes offrent un comportement de groupe sur un seul axe (horizontalement ou verticalement).

Un ensemble de widgets est considéré comme une chaîne s’ils sont reliés entre eux via une connexion bidirectionnelle

Une fois la chaîne créée, il existe deux possibilités:

  • Répartir les éléments dans l'espace disponible
  • Une chaîne peut aussi être "emballée", dans ce cas les éléments sont regroupés

Quant à votre cas, vous devrez emballer vos label et description TextViews et les centrer verticalement dans votre parent:

(assurez-vous d'utiliser une version de ConstraintLayout qui prend en charge les chaînes)

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


    <TextView
        Android:id="@+id/textView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="8dp"
        Android:layout_marginTop="16dp"
        Android:text="TextView"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_chainStyle="packed"/>

    <TextView
        Android:id="@+id/button"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginBottom="16dp"
        Android:layout_marginStart="8dp"
        Android:layout_marginTop="8dp"
        Android:text="Button\nMkay"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toBottomOf="@+id/textView"/>

    <ImageView
        Android:id="@+id/imageView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginEnd="16dp"
        Android:layout_marginTop="16dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        Android:id="@+id/imageView2"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginBottom="16dp"
        Android:layout_marginStart="16dp"
        Android:layout_marginTop="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        Android:id="@+id/imageView3"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginBottom="16dp"
        Android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>
</Android.support.constraint.ConstraintLayout>

Mise à jour du 25-06-2019 ( @ Saeid Z ):

Maintenant, dans la configuration de contrainte 1.1.3, nous devons utiliser app:layout_constraintHorizontal_chainStyle="packed" au lieu de app:layout_constraintVertical_chainPacked="true"

54
Yury Fedorov

Pour centrer quelque chose verticalement ou horizontalement, définissez un contrainte opposée sur la présentation.

centré verticalement

    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"

Centré horizontalement

    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
9
Kevin

Ensemble app:layout_constraintVertical_bias="0.5" pour les vues devant être centrées verticalement, l'attribut biais ne fonctionne que si vous spécifiez les contraintes pour les limites (par exemple, haut et bas pour le biais vertical, à gauche et à droite pour le biais horizontal)

Un exemple:

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

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@id/constraintLayout"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintVertical_bias="0.5" />

</Android.support.constraint.ConstraintLayout>

Je l'ai obtenu dans ma mise en page ici: https://github.com/hidroh/tldroid/blob/master/app/src/main/res/layout/activity_main.xml , disposition à peu près similaire, bien que je positionne les choses au 1/3 de la hauteur de l'écran.

enter image description here

5
hidro

EDIT: Cette réponse avait été écrite avant que les chaînes ne deviennent disponibles. Veuillez utiliser les chaînes maintenant, voir la réponse ci-dessus: https://stackoverflow.com/a/40102296/1402641


Pour le moment, je pense que votre seul choix serait d’envelopper les deux vues de texte dans une autre mise en page - la mise en page linéaire convient probablement mieux à cette situation.

Mais l’équipe derrière la disposition des contraintes a déclaré vouloir introduire des "conteneurs virtuels", qui servent exactement ce cas d’utilisation: vous regroupez deux vues ou plus et définissez une contrainte (comme le centrage vertical) sur le conteneur. L'idée est que ce n'est pas une présentation imbriquée complète à l'intérieur de la présentation de contrainte, mais simplement quelque chose que la présentation de contrainte utilise pour positionner ses enfants - elle devrait donc offrir de meilleures performances que l'imbrication.

Ils en font mention dans leur conversation I/O (liée à l'heure exacte). Donc, je suppose que restez à l'écoute.

5
Marcin Koziński

Jetez un oeil à mon exemple ( Composants du centre dans ConstraintLayout )

Pour l'instant, vous pouvez centrer "image" (contraindre de gauche à droite), contraindre "étiquette" de haut en "image" haut, contraindre "description" de haut en "étiquette". Dans l'exemple ci-dessous, la hauteur du bouton correspond à deux textviews à droite (ce qui est votre cas). Les autres vues textuelles sont contraintes comme sur le lien ci-dessus.

enter image description here

UPDATE: répondant à votre commentaire ci-dessous:

J'ai installé votre application et c'est seulement ce à quoi je peux penser actuellement. S'agissant d'une disposition ViewHolder, layout_height peut être défini sur wrap_content ou vous pouvez le corriger si vous le souhaitez. Je peux vous envoyer xml si vous voulez, je ne veux pas inonder la réponse.

La contrainte de gauche en haut de TextView est contrainte à la contrainte de droite de ImageView. De plus, la contrainte top TextView -> top est contrainte au sommet du conteneur, donc elle est correcte. Bottom TextView est contraint au bas du conteneur. Les TextViews au milieu sont obligés de correspondre à la largeur du texte TextView supérieur et n’ont aucune connexion avec ImageView.

enter image description here

2
bajicdusko