Процентная ширина в RelativeLayout - PullRequest
431 голосов
/ 10 февраля 2011

Я работаю над макетом формы для входа в систему Activity в моем приложении для Android.Изображение ниже, как я хочу, чтобы оно выглядело так:

enter image description here

Мне удалось добиться этого макета с помощью следующего XML .Проблема в том, что это немного хакерски.Мне пришлось жестко закодировать ширину для узла EditText.В частности, я должен был указать:

android:layout_width="172dp" 

Я бы очень хотел дать процентную ширину для узла и порта EditText's.(Что-то вроде 80% для хоста, 20% для порта.) Возможно ли это?Следующий XML работает на моем Droid, но, похоже, не работает на всех экранах.Мне бы очень хотелось более надежное решение.

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

Ответы [ 14 ]

734 голосов
/ 10 февраля 2011

Вы ищете атрибут android:layout_weight.Это позволит вам использовать проценты для определения макета.

В следующем примере левая кнопка занимает 70% пространства, а правая кнопка - 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>

Itработает так же с любым видом, вы можете заменить кнопки некоторым EditText в соответствии с вашими потребностями.

Обязательно установите layout_width на 0dp, иначе ваши представления могут быть неправильно масштабированы.1011 *

Обратите внимание, что весовая сумма не должна равняться 1, мне просто легче читать вот так.Вы можете установить первый вес на 7, а второй на 3, и это даст тот же результат.

285 голосов
/ 16 октября 2011

Это не совсем отвечает первоначальному вопросу, который был для разделения 70/30, но в особом случае разделения 50/50 между компонентами есть способ: поместить невидимую стойку в центр и использовать еерасположить два представляющих интерес компонента.

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

Поскольку это довольно распространенный случай, это решение - больше, чем просто любопытство.Это немного взломано, но эффективно, потому что пустая стойка нулевого размера должна стоить очень мало.

В общем, лучше не ожидать слишком многого от стандартных макетов Android ...

131 голосов
/ 23 августа 2015

Обновление 1

Как указано @EmJiHash PercentRelativeLayout устарело в Уровень API 26.0.0

Ниже цитируем комментарий Google:

Этот класс устарел на уровне API 26.0.0. рассмотрите использование ConstraintLayout и связанных макетов вместо этого. Ниже показано, как реплицировать функциональность процентных макетов с помощью ConstraintLayout


Google представил новый API под названием android.support.percent

Тогда вы можете просто указать процентное соотношение для просмотра

Добавить зависимость компиляции как

compile 'com.android.support:percent:22.2.0

, PercentRelativeLayout - это то, что мы можем сделать в процентном расположении

 <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>
78 голосов
/ 10 февраля 2011

Вы не можете использовать проценты для определения размеров представления внутри RelativeLayout.Лучший способ сделать это - использовать LinearLayout и веса или пользовательский макет.

31 голосов
/ 29 июня 2015

Вы можете взглянуть на новую библиотеку поддержки процентов.

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

документы

образец

18 голосов
/ 27 августа 2015

Вы можете использовать PercentRelativeLayout . Это недавнее недокументированное дополнение к Библиотеке поддержки проектирования , позволяющее указывать не только элементы относительно друг друга, но и общий процент свободного места.

Подкласс RelativeLayout, который поддерживает измерения в процентах и поля. Вы можете указать размер или поле дочернего элемента, используя атрибуты с суффиксом «Процент».

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

Пакет Percent предоставляет API для поддержки добавления и управления измерениями на основе процента в вашем приложении.

Чтобы использовать, вам нужно добавить эту библиотеку в список зависимостей Gradle список:

dependencies {
    compile 'com.android.support:percent:22.2.0'//23.1.1
}
11 голосов
/ 13 февраля 2016

Обновление

Как указано @EmJiHash PercentRelativeLayout и PercentFrameLayout не рекомендуется на уровне API 26.0.0

Рассмотреть возможность использования ConstraintLayout

Google представил новый API под названием android.support.percent

1) PercentRelativeLayout

2) PercentFrameLayout

Добавить зависимость компиляции, например

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

Вы можете указать размерность в процентах, чтобы получить как RelativeLayout, так и процент

 <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 голосов
/ 07 мая 2013

Я решил эту проблему, создав собственный вид:

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);
  }
}

Это невидимая распорка, которую я могу использовать для выравнивания других видов в RelativeLayout.

6 голосов
/ 24 октября 2017

Поскольку PercentRelativeLayout устарел в 26.0.0, а вложенные макеты, такие как LinearLayout внутри RelativeLayout, оказывают негативное влияние на производительность ( Понимание преимуществ производительности ConstraintLayout ), лучшим вариантом для достижения процентной ширины является заменаВаш RelativeLayout с ConstraintLayout.

Это можно решить двумя способами.

РЕШЕНИЕ # 1 Использование указаний с процентным смещением

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>

РЕШЕНИЕ № 2 Использование цепочки с взвешенной шириной для 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>

В обоих случаях вы получите что-то вроде этого

Result View

6 голосов
/ 26 марта 2017

PercentRelativeLayout устарела с версии 26.0.0 библиотеки поддержки.

Google представил новый макет под названием ConstraintLayout .

Добавьте библиотеку в качестве зависимости в файл build.gradle уровня модуля:

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

просто добавьте в файл макета:

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

Ограничения

Ограничения помогают поддерживать выравнивание виджетов. Вы можете использовать привязки, такие как дескрипторы ограничений, показанные ниже, для определения правил выравнивания между различными виджетами.

  1. Wrap Content: представление расширяется по мере необходимости, чтобы соответствовать его содержимому.
  2. Match Constraints: представление расширяется по мере необходимости, чтобы соответствовать определению его ограничений после учета полей. Однако, если данное измерение имеет только одно ограничение, то представление расширяется, чтобы соответствовать его содержимому. Использование этого режима для высоты или ширины также позволяет вам установить соотношение размеров.
  3. Fixed: Вы указываете конкретное измерение в текстовом поле ниже или изменяете размер представления в редакторе.
  4. Spread: ракурсы распределяются равномерно (после учета полей). Это значение по умолчанию.
  5. Spread inside: первый и последний вид прикреплены к ограничениям на каждом конце цепочки, а остальные распределены равномерно.
  6. Weighted: Когда для цепочки задано либо распространение, либо распространение внутри, вы можете заполнить оставшееся пространство, установив одно или несколько представлений в «соответствие ограничениям» (0dp). По умолчанию пространство равномерно распределяется между каждым представлением, для которого установлено «соответствие ограничениям», но вы можете назначить вес важности для каждого представления, используя атрибуты layout_constraintHor horizontal_weight и layout_constraintVertical_weight. Если вы знакомы с layout_weight в линейном макете, это работает точно так же. Таким образом, представление с наибольшим значением веса получает наибольшее количество места; виды с одинаковым весом получают одинаковое количество места.
  7. Packed: виды упакованы вместе (после учета полей). Затем вы можете отрегулировать смещение всей цепи (влево / вправо или вверх / вниз), изменив смещение вида головы.
  8. Center Horizontally or Center Vertically: Чтобы быстро создать цепочку видов, выделите их все, щелкните правой кнопкой мыши один из видов, а затем выберите Центр по горизонтали или Центр по вертикали, чтобы создать горизонтальную или вертикальную цепочку
  9. Baseline alignment: выровнять текстовую базовую линию представления к текстовой базовой линии другого представления.
  10. Constrain to a guideline: Вы можете добавить вертикальную или горизонтальную направляющую, к которой вы можете ограничить виды, и эта направляющая будет невидимой для пользователей приложения. Вы можете расположить направляющую в макете, основываясь на единицах dp или процентах относительно края макета.
  11. Adjust the constraint bias: когда вы добавляете ограничение к обеим сторонам вида (и размер вида для одного и того же измерения либо «фиксированный», либо «обтекание содержимым»), представление становится центрированным между двумя ограничениями смещением 50% по умолчанию. Вы можете настроить смещение, перетаскивая ползунок смещения в окне «Свойства»
  12. Set size as a ratio: Вы можете установить размер вида в таком соотношении, как 16: 9, если хотя бы для одного из размеров вида установлено «соответствие ограничениям» (0dp).

Подробнее вы можете узнать у официального doc .

...