web-dev-qa-db-fra.com

Essayer de répliquer l'alignement des colonnes GridLayout avec ConstraintLayout

Je suis nouveau dans ConstraintLayout et j'essaie de reproduire le même comportement de grille proposé par GridLayout avec ConstraintLayout.

Plus précisément, je veux concevoir une grille à deux colonnes. La largeur de la première colonne doit être aussi étroite que possible, tandis que la seconde doit occuper tout l’espace horizontal restant. Bien sûr, la deuxième colonne devrait être juste à droite de la première colonne, ou plutôt, à la vue la plus large de la première colonne.

Je ne sais pas comment puis-je répliquer cette dernière exigence avec ConstraintLayout. Je ne souhaite pas utiliser de quadrillage entre les deux colonnes, car la première colonne ne devrait pas avoir de largeur fixe ni de largeur, mais être aussi large que la plus large de sa vue.

Sur https://Gist.github.com/venator85/499dd82f47b3efbbed7a1e9e1ca1412d j'ai préparé un exemple de mise en page et l'aperçu correspondant, montrant un GridLayout qui implémente ce que je veux. Les deux premières tentatives de ConstraintLayout dans cette présentation montrent que C1 et D1 sont alignés sur B1 et que C2 et D2 sont alignés sur B2. Lorsque B2 est plus étroit que A2, A1 et C1 se chevauchent.

De l'aide?

Merci

13
Venator85

Google a introduit l'idée de "barrières" dans la dernière version de ConstraintLayout qui permet de répondre à cette question à 100% en XML. Voir les notes de publication de ConstraintLayout 1.1.0 beta 1 . Bien que cette note ne contienne pas beaucoup d'informations sur les nouvelles fonctionnalités, un talk à l'I/O 2017 a abordé les nouveaux éléments.

La nouvelle solution consiste à reproduire la grille de GridLayout avec des barrières. Une barrière verticale est placée à droite des TextViews de gauche et une barrière sous les trois rangées supérieures. Les barrières changent en fonction de la quantité de texte présente dans chaque TextView, mais conservent toujours la position spécifiée dans app:constraint_referenced_ids. Essentiellement, les barrières agissent comme des lignes directrices flottantes. Cette solution ne repose sur aucun codage pour prendre en charge le contenu de la vidéo.

Voici un video de la nouvelle mise en page qui montre le positionnement souhaité, chaque TextView étant maintenu alors que le contenu d'un autre TextView change. La vidéo a été réalisée dans les outils de conception d'Android Studio 2.3.2.

Et XML pour la nouvelle mise en page utilisant des barrières:

<?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:id="@+id/constrained"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.constraint.Barrier
        Android:id="@+id/barrierVertical"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:orientation="vertical"
        app:barrierDirection="right"
        app:constraint_referenced_ids="L1, L2, L3, L4" />

    <TextView
        Android:id="@+id/L1"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="L1 *"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R1"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1 R1*"
        app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <Android.support.constraint.Barrier
        Android:id="@+id/barrier1"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:orientation="horizontal"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="L1, R1" />

    <TextView
        Android:id="@+id/L2"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="L2 L2*"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/barrier1"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R2"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2 R2*"
        app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/barrier1"
        tools:ignore="HardcodedText" />

    <Android.support.constraint.Barrier
        Android:id="@+id/barrier2"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:orientation="horizontal"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="L2, R2" />

    <TextView
        Android:id="@+id/L3"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="L3 L3 L3*"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/barrier2"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R3"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3 R3*"
        app:layout_constraintLeft_toRightOf="@id/barrierVertical"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/barrier2"
        tools:ignore="HardcodedText" />

    <Android.support.constraint.Barrier
        Android:id="@+id/barrier3"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:orientation="horizontal"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="L3, R3" />

    <TextView
        Android:id="@+id/L4"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="L4 L4 L4 L4 L4 L4*"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/barrier3"
        tools:ignore="HardcodedText,RtlHardcoded" />

    <TextView
        Android:id="@+id/R4"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_margin="8dp"
        Android:text="R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4 R4*"
        app:layout_constraintLeft_toRightOf="@+id/barrierVertical"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/barrier3"
        tools:ignore="HardcodedText" />

</Android.support.constraint.ConstraintLayout>
7
Cheticamp

Mise à jour: Voir la réponse acceptée .

Je doute qu'il existe un moyen de répliquer une GridLayout avec une ConstraintLayout de la manière que vous souhaitez utiliser uniquement avec XML. Si vous êtes prêt à laisser un peu de code faciliter la mise en page, vous pouvez configurer la variable ConstraintLayout pour qu'elle fonctionne comme une GridLayout à l'aide d'un repère vertical mobile. 

Construisez la présentation XML en deux colonnes comme vous le décrivez. Le haut de chaque TextView dans la colonne de gauche sera contraint en haut de la TextView correspondante dans la colonne de droite, de sorte que les entrées de gauche flotteront de haut en bas à mesure que les entrées de droite augmentent ou diminuent en hauteur.

Toutes les vues de colonne de droite seront contraintes de gauche à la ligne directrice verticale mentionnée ci-dessus. Le placement de cette directive dans le fichier XML devrait être une chose raisonnable mais le placement réel sera effectué dans le code et sera ajusté en fonction de la largeur de la vue la plus large à gauche.

C'est une solution au problème que vous posez mais ce n'est pas une solution générale. Ce qui suit dépend de la hauteur de chaque TextView à gauche inférieure ou égale à la hauteur de la TextView correspondante à droite.

Voici à quoi ressemble la disposition dans l'éditeur de disposition d'Android Studio. J'ai poussé la ligne directrice vers la droite pour montrer comment elle flotte. (Le code suit les images.)

 enter image description here

Voici une capture d'écran. J'espère que tu trouves ca utile.

 enter image description here

Voici la mise en page en utilisant ConstraintLayout. (Mis à jour depuis le message initial pour envelopper la colonne de droite.)

constrained.xml

<?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:id="@+id/constrained"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.constraint.Guideline
        Android:id="@+id/guideline"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        app:layout_constraintGuide_begin="257dp" />

    <TextView
        Android:id="@+id/L1"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="0dp"
        Android:text="A1 A1 A1 A1 A1*"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="wrap"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/L2"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="0dp"
        Android:layout_marginTop="0dp"
        Android:text="B1 B1 B1 B1 B1*"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toTopOf="@+id/R2"
        app:layout_constraintWidth_default="wrap"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/L3"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="0dp"
        Android:layout_marginTop="0dp"
        Android:text="A2 A2 A2 A2*"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toTopOf="@+id/R3"
        app:layout_constraintWidth_default="wrap"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/L4"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="0dp"
        Android:layout_marginTop="0dp"
        Android:text="B2 B2 B2 B2 B2*"
        app:layout_constraintHorizontal_bias="0.02"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toTopOf="@+id/R4"
        app:layout_constraintWidth_default="wrap"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R1"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:text="C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1*"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R2"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:text="D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 D1*"
        app:layout_constraintLeft_toRightOf="@+id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/R1"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R3"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:text="C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2 C2*"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/R2"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/R4"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:text="D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2 D2*"
        app:layout_constraintLeft_toRightOf="@+id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/R3"
        tools:ignore="HardcodedText" />

</Android.support.constraint.ConstraintLayout>

Voici la Activity qui ajuste l'emplacement de la ligne directrice.

MainActivity.Java

package com.example.layout2;

import Android.os.Bundle;
import Android.support.constraint.ConstraintLayout;
import Android.support.constraint.Guideline;
import Android.support.v7.app.AppCompatActivity;
import Android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private Guideline mGuideline;
    private ConstraintLayout mConstraintLayout;
    private TextView L1;
    private TextView L2;
    private TextView L3;
    private TextView L4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.constrained);
        mConstraintLayout = (ConstraintLayout) findViewById(R.id.constrained);
        mGuideline = (Guideline) findViewById(R.id.guideline);
        L1 = (TextView) findViewById(R.id.L1);
        L2 = (TextView) findViewById(R.id.L2);
        L3 = (TextView) findViewById(R.id.L3);
        L4 = (TextView) findViewById(R.id.L4);
        // We will adjust the location of the guideline after layout is completed.
        mConstraintLayout.post(new Runnable() {
            @Override
            public void run() {
                moveGuideline();
            }
        });
    }

    public void moveGuideline() {
        ConstraintLayout.LayoutParams params;

        params = (ConstraintLayout.LayoutParams) mGuideline.getLayoutParams();
        // Find the widest TextView in the left column...
        params.guideBegin = Math.max(Math.max(L1.getWidth(), L2.getWidth()),
                Math.max(L3.getWidth(), L4.getWidth()));
        // ... and set the guideline to the right of the widest one.
        mGuideline.setLayoutParams(params);
    }
}
2
Cheticamp

Essayez ceci.

<?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"
Android:orientation="horizontal">


    <TextView
        Android:id="@+id/textView5"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="8dp"
        Android:layout_marginTop="8dp"
        Android:text="A1 A1 A1 A1 "
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        Android:id="@+id/textView8"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:layout_marginTop="8dp"
        Android:text="C1 C1 C1 C1 "
        app:layout_constraintHorizontal_bias="0.506"
        app:layout_constraintLeft_toRightOf="@+id/textView5"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        Android:id="@+id/textView9"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:layout_marginTop="8dp"
        Android:text="B1 B1 B1 B1 "
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/textView8"
        app:layout_constraintTop_toBottomOf="@+id/textView8" />

    <TextView
        Android:id="@+id/textView10"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:layout_marginTop="8dp"
        Android:text="D1 D1 D1 D1 "
        app:layout_constraintHorizontal_bias="0.506"
        app:layout_constraintLeft_toRightOf="@+id/textView5"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView5" />

</Android.support.constraint.ConstraintLayout>

Quelque chose comme ça.  enter image description here

2
shekhar g h

Je ne pense pas qu'il soit possible d'effectuer uniquement avec un conteneur ConstraintLayout pour le moment. J'espère qu'à l'avenir Google ajoutera quelque chose comme group_id ou un autre moyen de calculer la présentation avec "aligner sur le groupe".

En attendant, je vous suggère d'utiliser les conteneurs ConstraintLayout dans ConstraintLayout. Voici comment j'ai implémenté ceci:

 enter image description here  enter image description here

Pour faire les lignes "grille" comme, j'ai utilisé " Chaînes ConstraintLayout ". Le nombre de lignes dans chaque chaîne ConstraintLayout doit être identique pour que la distribution automatique aligne les lignes correctement. (Bien qu'ils puissent rester vides ou cachés s'ils ne sont pas utilisés).

Le xml Gist

0
Amir Uval