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
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 TextView
s 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>
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.)
Voici une capture d'écran. J'espère que tu trouves ca utile.
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);
}
}
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>
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:
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