web-dev-qa-db-fra.com

Pourcentage de largeur dans un RelativeLayout

Je travaille sur une présentation de formulaire pour une connexion Activity dans mon Android App. L'image ci-dessous est ce que je veux il ressemble à:

enter image description here

J'ai pu réaliser cette présentation avec le texte suivant XML. Le problème, c'est que c'est un peu hackish. J'ai dû coder en dur une largeur pour l'hôte EditText. Plus précisément, je devais préciser:

Android:layout_width="172dp" 

J'aimerais vraiment donner un pourcentage de largeur à l'hôte et au port EditText. (Quelque chose comme 80% pour l'hôte, 20% pour le port.) Est-ce possible? Le code XML suivant fonctionne sur mon droïde, mais il ne semble pas fonctionner pour tous les écrans. J'aimerais vraiment une solution plus robuste.

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/main"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent" >

    <TextView
        Android:id="@+id/Host_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/home"
        Android:paddingLeft="15dp"
        Android:paddingTop="0dp"
        Android:text="Host"
        Android:textColor="#a5d4e2"
        Android:textSize="25sp"
        Android:textStyle="normal" />

    <TextView
        Android:id="@+id/port_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/home"
        Android:layout_toRightOf="@+id/Host_input"
        Android:paddingTop="0dp"
        Android:text="port"
        Android:textColor="#a5d4e2"
        Android:textSize="25sp"
        Android:textStyle="normal" />

    <EditText
        Android:id="@+id/Host_input"
        Android:layout_width="172dp"
        Android:layout_height="wrap_content"
        Android:layout_below="@id/Host_label"
        Android:layout_marginLeft="15dp"
        Android:layout_marginRight="15dp"
        Android:layout_marginTop="4dp"
        Android:background="@Android:drawable/editbox_background"
        Android:inputType="textEmailAddress" />

    <EditText
        Android:id="@+id/port_input"
        Android:layout_width="100dp"
        Android:layout_height="wrap_content"
        Android:layout_below="@id/Host_label"
        Android:layout_marginTop="4dp"
        Android:layout_toRightOf="@id/Host_input"
        Android:background="@Android:drawable/editbox_background"
        Android:inputType="number" />

    <TextView
        Android:id="@+id/username_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/Host_input"
        Android:paddingLeft="15dp"
        Android:paddingTop="15dp"
        Android:text="username"
        Android:textColor="#a5d4e2"
        Android:textSize="25sp"
        Android:textStyle="normal" />

    <EditText
        Android:id="@+id/username_input"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:layout_below="@id/username_label"
        Android:layout_marginLeft="15dp"
        Android:layout_marginRight="15dp"
        Android:layout_marginTop="4dp"
        Android:background="@Android:drawable/editbox_background"
        Android:inputType="textEmailAddress" />

    <TextView
        Android:id="@+id/password_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/username_input"
        Android:paddingLeft="15dp"
        Android:paddingTop="15dp"
        Android:text="password"
        Android:textColor="#a5d4e2"
        Android:textSize="25sp"
        Android:textStyle="normal" />

    <EditText
        Android:id="@+id/password_input"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:layout_below="@id/password_label"
        Android:layout_marginLeft="15dp"
        Android:layout_marginRight="15dp"
        Android:layout_marginTop="4dp"
        Android:background="@Android:drawable/editbox_background"
        Android:inputType="textPassword" />

    <ImageView
        Android:id="@+id/home"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentTop="true"
        Android:layout_centerHorizontal="true"
        Android:layout_centerVertical="false"
        Android:paddingLeft="15dp"
        Android:paddingRight="15dp"
        Android:paddingTop="15dp"
        Android:scaleType="fitStart"
        Android:src="@drawable/home" />

    <Button
        Android:id="@+id/login_button"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/password_input"
        Android:layout_marginLeft="15dp"
        Android:layout_marginTop="15dp"
        Android:text="   login   "
        Android:textSize="18sp" >
    </Button>

</RelativeLayout>
433
Sarson

Vous recherchez l'attribut Android:layout_weight. Cela vous permettra d'utiliser des pourcentages pour définir votre mise en page.

Dans l'exemple suivant, le bouton gauche utilise 70% de l'espace et le bouton droit 30%.

<LinearLayout
    Android:layout_width="match_parent" 
    Android:layout_height="wrap_content"
    Android:orientation="horizontal">

    <Button
        Android:text="left" 
        Android:layout_width="0dp" 
        Android:layout_height="wrap_content" 
        Android:layout_weight=".70" /> 

    <Button
        Android:text="right" 
        Android:layout_width="0dp" 
        Android:layout_height="wrap_content" 
        Android:layout_weight=".30" />

</LinearLayout>

Cela fonctionne de la même manière avec n'importe quel type de vue, vous pouvez remplacer les boutons par du texte de montage pour répondre à vos besoins.

Assurez-vous de régler le layout_width sur 0dp sinon vos vues risquent de ne pas être redimensionnées correctement.

Notez que la somme de poids ne doit pas nécessairement être égale à 1, je trouve juste que c'est plus facile à lire comme ça Vous pouvez définir le premier poids sur 7 et le second sur 3 pour obtenir le même résultat.

735
Dalmas

Cela ne répond pas tout à fait à la question initiale, qui concernait une scission 70/30, mais dans le cas particulier d'une scission 50/50 entre les composants, il existe un moyen: placez une entretoise invisible au centre et utilisez-la pour positionner le deux composantes d'intérêt.

<RelativeLayout 
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">
    <View Android:id="@+id/strut"
        Android:layout_width="0dp"
        Android:layout_height="0dp" 
        Android:layout_centerHorizontal="true"/>
    <Button
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_alignRight="@id/strut"
        Android:layout_alignParentLeft="true"
        Android:text="Left"/> 
    <Button 
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_alignLeft="@id/strut"
        Android:layout_alignParentRight="true"
        Android:text="Right"/>
</RelativeLayout>

Comme il s’agit d’un cas assez courant, cette solution est plus qu’une curiosité. C'est un peu un bidouillage, mais un efficace car la jambe de force de taille nulle devrait coûter très peu.

En général, cependant, il vaut mieux ne pas trop attendre du stock Android.

287
olefevre

Mise à jour 1

Comme indiqué par @EmJiHash PercentRelativeLayout est obsolète dans le niveau de l'API 26.0.0

Ci-dessous, citant le commentaire Google:

Cette classe était obsolète dans l'API de niveau 26.0.0. Pensez plutôt à utiliser ConstraintLayout et les mises en page associées. Ce qui suit montre comment répliquer la fonctionnalité des dispositions de pourcentage avec un objet ConstraintLayout.


Google a introduit une nouvelle API appelée Android.support.percent

Ensuite, vous pouvez simplement spécifier le pourcentage à prendre par vue

Ajouter une dépendance de compilation comme

compile 'com.Android.support:percent:22.2.0

en cela, PercentRelativeLayout est ce que nous pouvons faire en pourcentage

 <Android.support.percent.PercentRelativeLayout
     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">
     <ImageView
         app:layout_widthPercent="50%"
         app:layout_heightPercent="50%"
         app:layout_marginTopPercent="25%"
         app:layout_marginLeftPercent="25%"/>
 </Android.support.percent.PercentRelativeLayout>
132
N J

Vous ne pouvez pas utiliser les pourcentages pour définir les dimensions d'une vue dans une relation relative. La meilleure façon de le faire est d'utiliser LinearLayout et des poids, ou une disposition personnalisée.

78
Romain Guy

Vous pouvez consulter la nouvelle bibliothèque de support en pourcentage.

compile 'com.Android.support:percent:22.2.0'

docs

échantillon

31
gbero

Vous pouvez utiliser PercentRelativeLayout . Il s’agit d’un ajout récent et non documenté à la bibliothèque de support de conception , qui permet de spécifier des éléments non seulement. les uns par rapport aux autres mais aussi le pourcentage total de l'espace disponible.

Sous-classe de RelativeLayout qui prend en charge les dimensions et les marges basées sur des pourcentages. Vous pouvez spécifier une dimension ou une marge d'enfant en utilisant des attributs avec le suffixe "Pourcent".

<Android.support.percent.PercentRelativeLayout
     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">
  <ImageView
      Android:layout_width="match_parent"
      Android:layout_height="match_parent"
      app:layout_widthPercent="50%"
      app:layout_heightPercent="50%"
      app:layout_marginTopPercent="25%"
      app:layout_marginLeftPercent="25%"/>
</Android.support.percent.PercentFrameLayout>

Le package Pourcentage fournit des API permettant de prendre en charge l'ajout et la gestion de dimensions basées sur un pourcentage dans votre application.

Pour l'utiliser, vous devez ajouter cette bibliothèque à votre liste de dépendances de Gradle:

dependencies {
    compile 'com.Android.support:percent:22.2.0'//23.1.1
}
18
IntelliJ Amiya

J'ai résolu ce problème en créant une vue personnalisée:

public class FractionalSizeView extends View {
  public FractionalSizeView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public FractionalSizeView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(width * 70 / 100, 0);
  }
}

C'est une partie invisible que je peux utiliser pour aligner d'autres vues dans RelativeLayout.

11
Ivan Volosyuk

Mise à jour

Comme indiqué par @EmJiHash, PercentRelativeLayout et PercentFrameLayout sont obsolètes dans le niveau 26.0.0 de l'API.

Pensez à utiliser ConstraintLayout

Google a introduit une nouvelle API appelée Android.support.percent

1) PercentRelativeLayout

2) PercentFrameLayout

Ajouter une dépendance de compilation comme

compile 'com.Android.support:percent:23.1.1'

Vous pouvez spécifier une dimension en pourcentage afin d’obtenir les avantages de RelativeLayout et un pourcentage.

 <Android.support.percent.PercentRelativeLayout
         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
         app:layout_widthPercent="40%"
         app:layout_heightPercent="40%"
         app:layout_marginTopPercent="15%"
         app:layout_marginLeftPercent="15%"/>
 </Android.support.percent.PercentRelativeLayout/>
11
ColdFire

Puisque PercentRelativeLayout était obsolète en 26.0.0 et que des dispositions imbriquées telles que LinearLayout dans RelativeLayout ont un impact négatif sur les performances ( Comprendre les avantages en termes de performances de ConstraintLayout ), la meilleure option pour atteindre un pourcentage de largeur consiste à remplacer votre RelativeLayout. avec ConstraintLayout.

Cela peut être résolu de deux manières.

SOLUTION N ° 1 Utilisation de recommandations avec un pourcentage de décalage

Layout Editor

<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/Host_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Host"
        Android:layout_marginTop="16dp"
        Android:layout_marginLeft="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="@+id/Host_input" />

    <TextView
        Android:id="@+id/port_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Port"
        Android:layout_marginTop="16dp"
        Android:layout_marginLeft="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="@+id/port_input" />

    <EditText
        Android:id="@+id/Host_input"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:inputType="textEmailAddress"
        app:layout_constraintTop_toBottomOf="@+id/Host_label"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/guideline" />

    <EditText
        Android:id="@+id/port_input"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:inputType="number"
        app:layout_constraintTop_toBottomOf="@+id/port_label"
        app:layout_constraintLeft_toLeftOf="@+id/guideline"
        app:layout_constraintRight_toRightOf="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_percent="0.8" />

</Android.support.constraint.ConstraintLayout>

SOLUTION N ° 2 Utilisation d'une chaîne avec une largeur pondérée pour EditText

Layout Editor

<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/Host_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Host"
        Android:layout_marginTop="16dp"
        Android:layout_marginLeft="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="@+id/Host_input" />

    <TextView
        Android:id="@+id/port_label"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Port"
        Android:layout_marginTop="16dp"
        Android:layout_marginLeft="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="@+id/port_input" />

    <EditText
        Android:id="@+id/Host_input"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:inputType="textEmailAddress"
        app:layout_constraintHorizontal_weight="0.8"
        app:layout_constraintTop_toBottomOf="@+id/Host_label"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/port_input" />

    <EditText
        Android:id="@+id/port_input"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:layout_marginLeft="8dp"
        Android:layout_marginRight="8dp"
        Android:inputType="number"
        app:layout_constraintHorizontal_weight="0.2"
        app:layout_constraintTop_toBottomOf="@+id/port_label"
        app:layout_constraintLeft_toRightOf="@+id/Host_input"
        app:layout_constraintRight_toRightOf="parent" />

</Android.support.constraint.ConstraintLayout>

Dans les deux cas, vous obtenez quelque chose comme ça

Result View

6
Eugene Brusov

PercentRelativeLayout est obsolète de la révision 26.0.0 de la bibliothèque de support.

Google a introduit une nouvelle mise en page appelée ConstraintLayout .

Ajoutez la bibliothèque en tant que dépendance dans votre fichier build.gradle au niveau du module:

     dependencies {
        compile 'com.Android.support.constraint:constraint-layout:1.0.1'
      }

ajoutez simplement un fichier de mise en page:

<?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">
</Android.support.constraint.ConstraintLayout>

Contraintes

Les contraintes vous aident à garder les widgets alignés. Vous pouvez utiliser des ancres, telles que les poignées de contrainte illustrées ci-dessous, pour déterminer les règles d'alignement entre différents widgets.

  1. Wrap Content: La vue se développe autant que nécessaire pour s'adapter à son contenu.
  2. Match Constraints: La vue s'agrandit pour répondre à la définition de ses contraintes après comptabilisation des marges. Toutefois, si la dimension donnée n'a qu'une contrainte, la vue s'agrandit pour s'adapter à son contenu. L'utilisation de ce mode sur la hauteur ou la largeur vous permet également de définir un rapport de taille.
  3. Fixed: vous spécifiez une dimension spécifique dans la zone de texte ci-dessous ou en redimensionnant la vue dans l'éditeur.
  4. Spread: Les vues sont réparties uniformément (après la comptabilisation des marges). C'est la valeur par défaut.
  5. Spread inside: La première et la dernière vue sont apposées sur les contraintes à chaque extrémité de la chaîne et le reste est uniformément réparti.
  6. Weighted: Lorsque la chaîne est définie pour être étendue ou étendue à l'intérieur, vous pouvez remplir l'espace restant en définissant une ou plusieurs vues pour "faire correspondre les contraintes" (0dp). Par défaut, l'espace est uniformément réparti entre chaque vue définie pour "faire correspondre les contraintes", mais vous pouvez attribuer un poids d'importance à chaque vue à l'aide des attributs layout_constraintHorizontal_weight et layout_constraintVertical_weight. Si vous connaissez layout_weight dans une présentation linéaire, cela fonctionne de la même manière. Ainsi, la vue avec la valeur de poids la plus élevée reçoit le plus d’espace; les vues qui ont le même poids obtiennent le même espace.
  7. Packed: les vues sont regroupées (après la prise en compte des marges). Vous pouvez ensuite ajuster le biais de la chaîne entière (gauche/droite ou haut/bas) en modifiant le biais de la vue de la tête de la chaîne.
  8. Center Horizontally or Center Vertically: pour créer rapidement une chaîne de vues, sélectionnez-les toutes, cliquez avec le bouton droit de la souris sur l'une des vues, puis sélectionnez Centrer horizontalement ou Centrer verticalement pour créer une chaîne horizontale ou verticale.
  9. Baseline alignment: Aligne la ligne de base du texte d'une vue sur la ligne de base du texte d'une autre vue.
  10. Constrain to a guideline: Vous pouvez ajouter un repère vertical ou horizontal auquel vous pouvez contraindre des vues. Le repère sera invisible pour les utilisateurs de l'application. Vous pouvez positionner le repère dans la présentation en fonction des unités dp ou du pourcentage, par rapport au bord de la présentation.
  11. Adjust the constraint bias: Lorsque vous ajoutez une contrainte aux deux côtés d'une vue (et que la taille de la vue pour la même dimension est "fixe" ou "envelopper le contenu"), la vue devient centrée entre les deux contraintes avec un biais de 50% par défaut. Vous pouvez ajuster le biais en faisant glisser le curseur de biais dans la fenêtre Propriétés.
  12. Set size as a ratio: Vous pouvez définir la taille de la vue sur un rapport tel que 16: 9 si au moins une des dimensions de la vue est définie sur "respecter les contraintes" (0dp).

Vous pouvez en apprendre plus depuis le fonctionnaire doc .

6
Darish

Il est intéressant de noter que, en s’appuyant sur la réponse de @olefevre, on peut non seulement réaliser des dispositions 50/50 avec des "entretoises invisibles", mais toutes sortes de dispositions impliquant une puissance de deux.

Par exemple, voici une disposition qui coupe la largeur en quatre parties égales (en réalité trois, avec des poids de 1, 1, 2):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content" >

    <View
        Android:id="@+id/strut"
        Android:layout_width="1dp"
        Android:layout_height="match_parent"
        Android:layout_centerHorizontal="true"
        Android:background="#000000" />

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_toLeftOf="@+id/strut" >

        <View
            Android:id="@+id/left_strut"
            Android:layout_width="1dp"
            Android:layout_height="match_parent"
            Android:layout_toLeftOf="@+id/strut"
            Android:layout_centerHorizontal="true"
            Android:background="#000000" />

        <Button
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_alignParentLeft="true"
            Android:layout_alignRight="@+id/left_strut"
            Android:text="Far Left" />

        <Button
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_alignParentRight="true"
            Android:layout_toRightOf="@+id/left_strut"
            Android:text="Near Left" />
    </RelativeLayout>

        <Button
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_alignLeft="@id/strut"
            Android:layout_alignParentRight="true"
            Android:text="Right" />

</RelativeLayout>
3
coco

Vous pouvez accomplir cela via des poids de mise en page. Un poids détermine la façon dont les parties non réclamées de l'écran sont divisées. Donnez à chaque EditText une largeur de layout_width de 0 et un poids proportionnel. C'est-à-dire, attribuez à l'une un poids de 2 et à l'autre un poids de 1 si vous voulez que le premier occupe deux fois plus de place.

3
Cheryl Simon

Il suffit de placer vos deux vues de texte hôte et port dans un affichage linéaire indépendant et d'utiliser Android: layout_weight pour définir le pourcentage.

3
Cyatophilum

Vérifiez https://github.com/mmin18/FlexLayout lequel vous pouvez utiliser le pourcentage ou l'expression Java directement dans la mise en forme xml.

<EditText
    app:layout_left="0%"
    app:layout_right="60%"
    app:layout_height="wrap_content"/>
<EditText
    app:layout_left="prev.right+10dp"
    app:layout_right="100%"
    app:layout_height="wrap_content"/>
1
mmin