Comment faire fonctionner ConstraintLayout avec des valeurs de pourcentage?

207

Avec un Preview 1 d'Android 2.2 Studio de Google a publié une nouvelle mise en page dans sa bibliothèque de support: ConstraintLayout. Avec ConstraintLayout, il est plus facile d'utiliser un outil de conception dans Android Studio, mais je n'ai pas trouvé de moyen d'utiliser des tailles relatives (pourcentages ou 'poids' comme dans LinearLayout). Existe-t-il un moyen de définir les contraintes en fonction des pourcentages? Par exemple, faire en sorte qu'une vue occupe 40% d'un écran, créer une marge de 20% entre les vues, définir la largeur d'une vue à 50% de la largeur d'une autre vue?

Yury Fedorov
la source
3
La prise en charge en pourcentage de la largeur ou de la hauteur a été ajoutée dans version 1.1ConstraintLayout. Voir "Dimension en pourcentage" sur developer.android.com/reference/android/support/constraint/… ou certaines des réponses les plus récentes.
sunadorer

Réponses:

225

Vous pouvez actuellement le faire de plusieurs manières.

La première consiste à créer des lignes directrices (cliquez avec le bouton droit sur la zone de conception, puis cliquez sur ajouter des lignes directrices verticales / horizontales). Vous pouvez ensuite cliquer sur "l'en-tête" de la ligne directrice pour modifier le positionnement pour qu'il soit basé sur un pourcentage. Enfin, vous pouvez contraindre les vues aux directives.

Une autre façon consiste à positionner une vue en utilisant le biais (pourcentage), puis à ancrer d'autres vues à cette vue.

Cela dit, nous avons réfléchi à la façon d'offrir des dimensions basées sur un pourcentage. Je ne peux faire aucune promesse mais c'est quelque chose que nous aimerions ajouter.

Romain Guy
la source
1
0 vote vers le bas Puis-je demander un suivi? J'essaie de définir une ImageView sur une largeur de 60% mais de conserver un rapport d'aspect de 16: 9. Je veux que la largeur soit fixe, mais la hauteur de l'ImageView soit dynamique. Est-ce possible avec ConstraintLayout? J'ai du mal à le faire fonctionner - je me retrouve avec des valeurs fixes de largeur / hauteur de 0, sauf si je spécifie des dimensions codées en dur.
MattWilliams89
3
@ MattWilliams89 Il existe un paramètre appelé layout_constraintDimensionRatio, je suppose qu'il peut être utile dans votre cas, écrivez "16: 9" ici. Mais je n'ai pas réussi à construire votre mise en page avec elle, l'image devient énorme
Yury Fedorov
1
@RomainGuy comment changez-vous le positionnement pour qu'il soit en pourcentage sur l'en-tête des guides?. j'ai essayé de faire un clic droit dessus et rien ne s'affiche
Edijae Crusar
21
Pour ceux qui se demandent exactement ce qu'est l'en-tête de la ligne directrice, c'est le cercle qui a une flèche vers le haut ou vers le bas ou un symbole de pourcentage. En cliquant dessus, vous basculez entre l'application: layout_constraintGuide_begin, l'application: layout_constraintGuide_end et l'application: layout_constraintGuide_percent en XML. J'ai rencontré un petit problème (sur ConstraintLayout version 1.0.0-alpha8 où je devais cliquer sur la ligne directrice, maintenir ma souris enfoncée et faire glisser vers le cercle pour les basculer dans l'éditeur, mais je suis sûr que ce bogue sera bientôt corrigé .
Lustig
4
Vous pouvez également définir cela dans le XML de la mise en page en utilisantapp:layout_constraintGuide_percentage
piratemurray
215

Il peut être utile d'avoir une référence rapide ici.

Placement des vues

Utilisez une ligne directrice avec app:layout_constraintGuide_percentcomme ceci:

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5"/>

Et vous pouvez ensuite utiliser ce guide comme points d'ancrage pour d'autres vues.

ou

Utilisez le biais avec app:layout_constraintHorizontal_biaset / ou app:layout_constraintVertical_biaspour modifier l'emplacement de la vue lorsque l'espace disponible le permet

<Button
    ...
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintHorizontal_bias="0.25"
    ...
    />

Taille des vues

Une autre valeur en pourcentage est la hauteur et / ou la largeur des éléments, avec app:layout_constraintHeight_percentet / ou app:layout_constraintWidth_percent:

<Button
    ...
    android:layout_width="0dp"
    app:layout_constraintWidth_percent="0.5"
    ...
    />
Amir Uval
la source
3
pourquoi sa largeur est-elle réglée sur 1dp?
user924
1
@ user924 Il aurait été judicieux de donner à une ligne directrice une largeur de 0dp, je ne sais pas pourquoi les développeurs qui l'ont implémenté ont décidé de 1dp. Peut-être parce que 0dp est considéré comme "étiré" lors de l'utilisation de poids.
Amir Uval
3
@ user924: 0dpest utilisé dans ConstraintLayout pour indiquer le dimensionnement dynamique. Voir developer.android.com/reference/android/support/constraint/…
serv-inc
1
@ serv-inc mais ici 1dp, pas 0dp.. c'est ce dont je parle
user924
3
@ user924: vous devez le définir sur une largeur. 0dpest déjà réservé, 1dpsemble donc raisonnable.
serv-inc
109

Depuis "ConstraintLayout1.1.0-beta1", vous pouvez utiliser le pourcentage pour définir les largeurs et les hauteurs.

android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent=".4"

Cela définira la largeur à 40% de la largeur de l'écran. Une combinaison de cela et des directives en pourcentage vous permet de créer n'importe quelle mise en page basée sur le pourcentage que vous souhaitez.

hoford
la source
6
Dans la disposition de contraintes 1.0.2, la valeur en pourcentage de layout_constraintWidth_default n'est pas prise en charge. Je pense que la bonne façon est d'utiliser la directive.
vovahost
1
ça marche avec Android Studio 3.0 construit le 20 octobre 2017
douarbou
5
Comme indiqué dans la réponse, cela a été ajouté dans version 1.1ConstraintLayout. L'additionnel _default="percent"n'est plus nécessaire sur la version stable! Voir "Dimension en pourcentage" sur developer.android.com/reference/android/support/constraint/…
sunadorer
@hoford, pour une vue contenant du texte, dont la taille doit être définie en spunités, comment la taille du texte pourrait-elle être auto-proportionnelle à la taille de la vue (qui, en soi, est définie proportionnellement à la taille totale de la mise en page, c'est-à-dire en 'pourcentage') ?
Bliss
77

Avec la nouvelle version de ConstraintLayout v1.1, vous pouvez désormais effectuer les opérations suivantes:

<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.2"
app:layout_constraintWidth_percent="0.65" />

Cela contraindra le bouton à 20% de la hauteur et 65% de la largeur de la vue parent.

Adam
la source
1
pour moi, je n'ai travaillé que lorsque je suis passé de "android:" à "app:" -> app: layout_constraintHeight_percent = "0.2"
Kirill Karmazin
C'est un must pour moi lors de la mise en page fluide de la conception matérielle. material.io/design/layout/…
@Adam, pour une vue contenant du texte, dont la taille doit être définie en spunités, comment la taille du texte pourrait-elle être auto-proportionnelle à la taille de la vue (qui, en soi, est définie proportionnellement à la taille totale de la mise en page, c'est-à-dire en 'pourcentage') ?
Bliss
1
@Bliss Des sons comme celui-ci pourraient aider: developer.android.com/guide/topics/ui/look-and-feel/… Je ne l'ai cependant jamais utilisé moi-même.
Adam
43

Comment utiliser les directives

La réponse acceptée n'est pas claire sur la façon d'utiliser les directives et sur ce qu'est "l'en-tête".

Pas

Ajoutez d'abord une directive.

entrez la description de l'image ici

Sélectionnez la ligne directrice ou déplacez-la un peu pour rendre les contraintes visibles.

entrez la description de l'image ici

Cliquez ensuite sur le cercle rond (l '"en-tête") jusqu'à ce qu'il devienne un pourcentage. Vous pouvez ensuite faire glisser ce pourcentage jusqu'à 50% ou ce que vous voulez.

entrez la description de l'image ici

Après cela, vous pouvez contraindre votre vue à la ligne directrice pour en faire un pourcentage du parent (en utilisant match_constraintla vue).

entrez la description de l'image ici

Suragch
la source
Où doit être visible l'en-tête? Cela n'apparaît pas à mon avis.
Marcel50506
@ Marcel50506, assurez-vous que les vues Design et Blueprint s'affichent. Cela vous donnera la meilleure chance de pouvoir le voir. Si vous pouvez voir la ligne directrice, essayez de cliquer dessus pour la sélectionner. Si vous ne voyez pas la ligne, essayez de cliquer sur l'élément de ligne directrice dans le menu Arborescence des composants qui devrait être désactivé sur le côté gauche (en supposant que vous avez déjà ajouté une ligne directrice).
Suragch
1
Je ne vois pas le cercle, mais en cliquant sur la gauche de la ligne directrice, je peux le modifier en pourcentages. Problème de rendu, je pense. Je vous remercie.
Marcel50506
C'est la meilleure réponse car elle propose une meilleure approche de mise en page. Nous pouvons aligner plusieurs vues sur la ligne de base au lieu d'ajouter un pourcentage sur une seule vue
Nguyen Minh Hien
33

La directive est inestimable - et l'application: layout_constraintGuide_percent est un grand ami ... Cependant, parfois, nous voulons des pourcentages sans directives. Il est maintenant possible d'utiliser des poids :

android:layout_width="0dp"
app:layout_constraintHorizontal_weight="1"

Voici un exemple plus complet qui utilise une directive avec des poids supplémentaires :

<?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:padding="16dp"
    tools:context="android.itomerbu.layoutdemo.MainActivity">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.44"/>

    <Button
        android:id="@+id/btnThird"
        android:layout_width="0dp"
        app:layout_constraintHorizontal_weight="1"
        android:layout_height="wrap_content"
        android:text="@string/btnThird"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginBottom="8dp"
        app:layout_constraintRight_toLeftOf="@+id/btnTwoThirds"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"/>

    <Button
        android:id="@+id/btnTwoThirds"
        app:layout_constraintHorizontal_weight="2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/btnTwoThirds"
        app:layout_constraintBottom_toBottomOf="@+id/btnThird"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/btnThird"/>
</android.support.constraint.ConstraintLayout>
TomerBu
la source
2
@Plumbus - Les poids sont équivalents à des pourcentages (n'importe quel pourcentage peut être mathématiquement converti en poids et vice-versa). En étant pointilleux sur la terminologie, vous manquez le point de la réponse.
Scott Biggs
11

Avec ConstraintLayout v1.1.2, la dimension doit être définie sur 0dp, puis définissez les attributs layout_constraintWidth_percentou layout_constraintHeight_percentsur une valeur comprise entre 0 et 1, comme:

<!-- 50% width centered Button -->
<Button
    android:id="@+id/button"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintWidth_percent=".5" />

(Vous n'avez pas besoin de définir app:layout_constraintWidth_default="percent"ou app:layout_constraintHeight_default="percent"avec ConstraintLayout 1.1.2 et les versions suivantes)

Bubu
la source
10

Contrainte Layout 1.0 faisant qu'une vue occupe un pourcentage de l'écran requis en faisant deux directives. Dans Constraint Layout 1.1, il a été simplifié en vous permettant de contraindre facilement n'importe quelle vue à un pourcentage de largeur ou de hauteur.

entrez la description de l'image ici

N'est-ce pas fantastique? Toutes les vues prennent en charge les attributs layout_constraintWidth_percent et layout_constraintHeight_percent. Celles-ci entraîneront la fixation de la contrainte à un pourcentage de l'espace disponible. Il est donc possible de créer un bouton ou une extension TextView pour remplir un pourcentage de l'écran avec quelques lignes de XML.

Par exemple, si vous souhaitez définir la largeur du bouton à 70% de l'écran, vous pouvez le faire comme ceci:

<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_constraintWidth_percent="0.7" />

Veuillez noter que vous devrez mettre la dimension à utiliser en pourcentage à 0dp comme nous l'avons spécifié android: layout_width à 0dp ci-dessus.

De même, si vous souhaitez régler la hauteur du bouton à 20% de l'écran, vous pouvez le faire comme ceci:

<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_constraintHeight_percent="0.2" />

Voir! nous avons spécifié android: layout_height à 0dp cette fois car nous voulons que le bouton utilise la hauteur en pourcentage.

Ashish Satpute
la source
8

Essayez ce code. Vous pouvez modifier les pourcentages de hauteur et de largeur avec app: layout_constraintHeight_percent et app: layout_constraintWidth_percent.

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

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FF00FF"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_percent=".6"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent=".4"></LinearLayout>

</android.support.constraint.ConstraintLayout>

Gradle:

dependencies {
...
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}

entrez la description de l'image ici

l'amour en direct
la source
7

vous pouvez l'utiliser app:layout_constraintVertical_weightcomme layout_weightdanslinearlayout

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

<Button
    android:id="@+id/button4"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Button"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/button5"
    app:layout_constraintVertical_weight="1"/>

<Button
    android:id="@+id/button5"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Button"
    app:layout_constraintLeft_toRightOf="@+id/button4"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintVertical_weight="1"/>
</android.support.constraint.ConstraintLayout>

REMARQUE: app:layout_constraintVertical_weight( app:layout_constraintHorizontal_weight) fonctionnera avec android:layout_width="0dp"(android:layout_height="0dp"

vuhung3990
la source
5

Pour quelqu'un qui pourrait trouver utile, vous pouvez utiliser layout_constraintDimensionRatioim n'importe quelle vue enfant à l'intérieur d'un ConstraintLayoutet nous pouvons définir la hauteur ou la largeur un rapport de l'autre dimension (au moins un doit être 0dp soit largeur ou hauteur) exemple

 <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:src="@drawable/top_image"
        app:layout_constraintDimensionRatio="16:9"        
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

dans ce cas le rapport d'aspect est de 16: 9 app:layout_constraintDimensionRatio="16:9" vous pouvez trouver plus d'informations ICI

Javier
la source
3

Je sais que ce n'est pas directement ce que OP demandait à l'origine, mais cela m'a beaucoup aidé dans cette situation quand j'avais une question similaire. . Ajoutez ceci à votre onCreate dans l'activité de question. (Le change à 80%)

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);

int width = dm.widthPixels;
int height = dm.heightPixels;

getWindow().setLayout((int)(width * 0.8), (int)(height * 0.8));
David Azzi
la source
2

Remplacez simplement, dans votre balise de ligne directrice

app:layout_constraintGuide_begin="291dp"

avec

app:layout_constraintGuide_percent="0.7"

où 0,7 signifie 70%.

De plus, si vous essayez maintenant de faire glisser les directives, la valeur glissée apparaîtra désormais en% age.

Udit Kapahi
la source
2

À l'aide des directives, vous pouvez modifier le positionnement pour qu'il soit basé sur un pourcentage

<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5"/>

Vous pouvez également utiliser cette méthode

android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.4"
Ashish Satpute
la source