Почему гравитация не применяется при относительной компоновке?

Я уже понимаю, что если я использую layout_gravity="center_horizontal" в текстовом представлении, тогда текст будет центром. Но я не хочу использовать это, потому что я хочу иметь как можно меньше кода, и лучший способ сделать это - применить gravity="center_horizontal" к моему относительному расположению. Я также задаю этот вопрос, потому что меня беспокоит даже использование gravity или layout_gravity с относительными макетами вообще. Как и при выполнении моих исследований, я ответил на этот ответ.

Обратите внимание на часть, которая гласит:

Не используйте гравитацию /layout _gravity с RelativeLayout. Используйте их для просмотров в LinearLayouts и FrameLayouts.

Хотя мне кажется довольно очевидным относительный макет Android Documentation, в котором четко указано gravity как действительный атрибут, который Google предполагал, что эти атрибуты будут использоваться с относительными макетами.

Если эта цитата верна, как мне просматривать точки в относительных макетах?

Кроме того, вот мой код:

Обратите внимание, что заголовок не центрирован по горизонтали

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:gravity="center_horizontal"
    tools:context="com.something">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp" />

    <AutoCompleteTextView
        android:id="@+id/enterContact"
        android:text="Enter Contact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAlignment="center"
        android:layout_below="@+id/title"
        android:layout_marginBottom="@dimen/main_spacing" />

</RelativeLayout>

введите описание изображения здесь

Ответы

Ответ 1

Это дополнительный ответ Gravity и layout_gravity на Android.

Просмотр gravity и layout_gravity внутри относительной компоновки

Мое первоначальное утверждение о том, что gravity и layout_gravity не должно использоваться в подзаголовках a RelativeLayout, было отчасти неправильным. gravity работает отлично. Однако layout_gravity не действует. Это можно увидеть в приведенном ниже примере. Светло-зеленый и голубой - это TextViews. Остальные два цвета фона - RelativeLayouts.

введите описание изображения здесь

Как видите, gravity работает, но layout_gravity не работает.

Относительная компоновка с gravity

Мой оригинальный ответ о gravity и layout_gravity касался этих атрибутов, применяемых к представлениям в пределах ViewGroup (в частности, LinearLayout), а не самому ViewGroup. Тем не менее, можно установить gravity и layout_gravity на RelativeLayout. layout_gravity повлияет на то, как RelativeLayout позиционируется внутри своего собственного родителя, поэтому я не буду заниматься этим. Как gravity влияет на subviews, однако, показано на изображении ниже.

введите описание изображения здесь

Я изменил ширину всех подзонов, так что происходящее стало более ясным. Обратите внимание, что способ RelativeLayout обрабатывать гравитацию - это взять все подзоны в виде группы и перемещать их по макету. Это означает, что любой вид будет самым широким, будет определять, как все остальное расположено. Таким образом, гравитация в относительной компоновке, вероятно, полезна, только если все подзоны имеют одинаковую ширину.

Линейная компоновка с gravity

Когда вы добавляете gravity в LinearLayout, он упорядочивает subviews, как и следовало ожидать. Например, можно "сохранить код", установив gravity из LinearLayout в center_horizontally. Таким образом, нет необходимости индивидуально устанавливать layout_gravity для каждого поднабора. См. Различные варианты на изображении ниже.

введите описание изображения здесь

Обратите внимание, что когда вид использует layout_gravity, он переопределяет гравитацию LinearLayout. (Это можно увидеть в заголовке для двух макетов в левом изображении. LinearLayout gravity был установлен в left и right, но заголовок TextView layout_gravity был установлен в center_horizontally.)

Заключительные заметки

Когда позиционирует представления в RelativeLayout, общий способ сделать это - добавить к каждому представлению следующие вещи:

  • layout_alignParentTop
  • layout_centerVertical
  • layout_below
  • layout_toRightOf

Если вы хотите сразу установить все представления, LinearLayout, вероятно, будет лучше (или, возможно, с использованием стиля).

Итак, чтобы подвести итог,

  • layout_gravity не работает для subviews в RelativeLayout.
  • gravity RelativeLayout работает, но не так, как можно было бы ожидать.

Дополнительный XML

XML для изображения "Просмотр gravity и layout_gravity внутри относительной компоновки:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#e3e2ad" >

        <TextView
            android:id="@+id/tvTop1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:textSize="24sp"
            android:text="Views' gravity=" />

        <!-- examples of gravity -->

        <TextView
            android:id="@+id/tvTop2"
            android:layout_below="@id/tvTop1"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="left"
            android:text="left" />

        <TextView
            android:id="@+id/tvTop3"
            android:layout_below="@id/tvTop2"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center_horizontal"
            android:text="center_horizontal" />

        <TextView
            android:id="@+id/tvTop4"
            android:layout_below="@id/tvTop3"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="right"
            android:text="right" />

        <TextView
            android:id="@+id/tvTop5"
            android:layout_below="@id/tvTop4"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center"
            android:text="center" />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#d6c6cd" >

        <TextView
            android:id="@+id/tvBottom1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:textSize="24sp"
            android:text="Views' layout_gravity=" />

        <!-- examples of layout_gravity -->

        <TextView
            android:id="@+id/tvBottom2"
            android:layout_below="@id/tvBottom1"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_gravity="left"
            android:background="#bcf5b1"
            android:text="left" />

        <TextView
            android:id="@+id/tvBottom3"
            android:layout_below="@id/tvBottom2"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_gravity="center_horizontal"
            android:background="#aacaff"
            android:text="center_horizontal" />

        <TextView
            android:id="@+id/tvBottom4"
            android:layout_below="@id/tvBottom3"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_gravity="right"
            android:background="#bcf5b1"
            android:text="right" />

        <TextView
            android:id="@+id/tvBottom5"
            android:layout_below="@id/tvBottom4"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_gravity="center"
            android:background="#aacaff"
            android:text="center" />

    </RelativeLayout>

</LinearLayout>

XML для изображения "Относительная макета с гравитацией" :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center_horizontal"
        android:background="#e3e2ad" >

        <TextView
            android:id="@+id/tvTop1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="24sp"
            android:text="Views' gravity=" />

        <!-- examples of gravity -->

        <TextView
            android:id="@+id/tvTop2"
            android:layout_below="@id/tvTop1"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="left"
            android:text="left" />

        <TextView
            android:id="@+id/tvTop3"
            android:layout_below="@id/tvTop2"
            android:layout_width="300dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center_horizontal"
            android:text="center_horizontal" />

        <TextView
            android:id="@+id/tvTop4"
            android:layout_below="@id/tvTop3"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="right"
            android:text="right" />

        <TextView
            android:id="@+id/tvTop5"
            android:layout_below="@id/tvTop4"
            android:layout_width="150dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center"
            android:text="center" />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:background="#d6c6cd" >

        <TextView
            android:id="@+id/tvBottom1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="24sp"
            android:text="Views' gravity=" />

        <!-- examples of layout_gravity -->

        <TextView
            android:id="@+id/tvBottom2"
            android:layout_below="@id/tvBottom1"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:gravity="left"
            android:background="#bcf5b1"
            android:text="left" />

        <TextView
            android:id="@+id/tvBottom3"
            android:layout_below="@id/tvBottom2"
            android:layout_width="300dp"
            android:layout_height="40dp"
            android:gravity="center_horizontal"
            android:background="#aacaff"
            android:text="center_horizontal" />

        <TextView
            android:id="@+id/tvBottom4"
            android:layout_below="@id/tvBottom3"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:gravity="right"
            android:background="#bcf5b1"
            android:text="right" />

        <TextView
            android:id="@+id/tvBottom5"
            android:layout_below="@id/tvBottom4"
            android:layout_width="150dp"
            android:layout_height="40dp"
            android:gravity="center"
            android:background="#aacaff"
            android:text="center" />

    </RelativeLayout>

</LinearLayout>

XML для изображения "Линейная компоновка с гравитацией" :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center_horizontal"
        android:background="#e3e2ad"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="24sp"
            android:text="View gravity=" />

        <TextView
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="left"
            android:text="left" />

        <TextView
            android:layout_width="300dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center_horizontal"
            android:text="center_horizontal" />

        <TextView
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="right"
            android:text="right" />

        <TextView
            android:layout_width="150dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center"
            android:text="center" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:background="#d6c6cd"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="24sp"
            android:text="View gravity=" />

        <TextView
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="left"
            android:text="left" />

        <TextView
            android:layout_width="300dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center_horizontal"
            android:text="center_horizontal" />

        <TextView
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:background="#bcf5b1"
            android:gravity="right"
            android:text="right" />

        <TextView
            android:layout_width="150dp"
            android:layout_height="40dp"
            android:background="#aacaff"
            android:gravity="center"
            android:text="center" />

    </LinearLayout>

</LinearLayout>

Ответ 2

Тестирование макета, для меня это работает (TextView центрируется правильно).

Однако вы также можете удалить android:gravity="center_horizontal" из RelativeLayout и добавить android:layout_centerHorizontal="true" в TextView.

Ответ 3

У меня всегда были проблемы с RelativeLayouts и TextViews. Я думаю, что это связано с тем, что TextView вычисляет его размер динамически, и это не позволяет ему хорошо работать с гравитацией макета. Это только одно мое предположение. Решение, которое я обычно принимаю, заключается в настройке горизонтального размера textview с помощью match_parent. Это может быть субоптимальное решение, но должно работать. Если вам нужен текстовый файл с фиксированным размером, вы можете поместить размер фиксированного размера и работать тоже, он дает проблемы только с wrap_content.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:gravity="center_horizontal"
    tools:context="com.something">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp" />

</RelativeLayout>

Изменить: как предложил @Valentino S., добавив

android:layout_centerHorizontal="true"

с wrap_content тоже должен работать. Причина в моей голове все та же: размер textView вычисляется позже.

Ответ 4

попробуйте следующее:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:background="#000000"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:background="#ffffffff"
        android:text="TITLE"
        android:textAlignment="center"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textSize="24sp" />

    <AutoCompleteTextView
        android:id="@+id/enterContact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:layout_marginBottom="10dp"
        android:background="#ffffffff"
        android:text="Enter Contact"
        android:textAlignment="center" />

</RelativeLayout>

введите описание изображения здесь

Ответ 5

Как сообщает :

Android: гравитация

Определяет, как объект должен размещать свой контент как на X, так и на Y, в пределах собственных границ.

...

center_horizontal

Поместите объект в горизонтальный центр его контейнера, не меняя его размер.

Таким образом, android:gravity="center_horizontal" будет центрировать горизонтальное положение RelativeLayout до его родителя. Не создавайте горизонтальный центр содержимого.

Помните, что android:layout_gravity используется для самого представления относительно родителя или макета.

Помните, что поведение макета может немного отличаться для каждого уровня API. Следует отметить, что мы не можем на 100% убедиться, что визуальный результат в редакторе макета правильный. Всегда проверяйте свой макет в реальных устройствах.

Ответ 6

TL;DR: android: gravity Работает с RelativeLayout, вы можете пропустить снизу, если вы не хотите читать объяснение

ИЗМЕНИТЬ это гигантская стена текста, пожалуйста, несите меня

Это то, что, я думаю, вы хотите достичь:

<TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp"
        android:layout_centerHorizontal="true"/>  <!-- LAYOUT PARAMS WORK!!!-->

Почему это работает, а android:gravity (по-видимому) не работает?

  • если ваша цель состоит в том, чтобы поместить TextView в горизонтальный центр Layout/Screen, который вы должны сообщить RelativeLayout!

  • это достигается с помощью LayoutParams - это структуры данных, определенные каждым View, которые используются родителем View (в данном случае RelativeLayout)

  • поэтому скажем, что ваш TextView имеет следующий LayoutParams:

    Android: layout_centerHorizontal = "истина"

вы получите что-то вроде этого:

enter image description here

Когда RelativeLayout распространяет свои дочерние представления по экрану, по пути выполняется метод обратного вызова - onLayout (...) - это часть более сложной последовательности методов, в которой будет определять положение каждого дочернего элемента View внутри RelativeLayout, это достигается частично за счет доступа к LayoutParams для каждого дочернего элемента View, в этом случае эта строка в вашем TextView

  1. Вот почему мы говорим, что LayoutParams передаются родительскому элементу, как в упомянутой выше ссылке .

ПРЕДУПРЕЖДЕНИЕ: Бесконечный источник путаницы!

Просмотр позиционирования внутри Layout/ViewGroup выполняется через LayoutParam вызов onLayout

Так получилось, что в некоторых макетах, таких как FrameLayout, есть LayoutParam, называемый android: layout_gravity, который вызывает большую путаницу с свойством android:gravity что каждый вид может определить, который НЕ тот же и даже не LayoutParam

android:gravity используется любым представлением (например, a TextView), чтобы разместить его содержимое внутри.

Пример: скажем, что вы изменили TextView на очень высокий, и вы хотите, чтобы текст в нижней части TextView, а не вверху p >

<TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="95dp"   <------------ very high!
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp"
        android:layout_centerHorizontal="true" <----- LayoutParams for RelativeLayout
        />

TextView is CENTERED but text is at the TOP

TextView имеет CENTERED в RelativeLayout, но текст находится в ВЕРХНИХ из окна "

Позвольте использовать android: гравитация для управления текстовой позицией ВНУТРИ TextView

<TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="95dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp"
        android:layout_centerHorizontal="true"
        android:gravity="bottom"       <---**NOT LayoutParams**, NOT passed to RLayout
        />

Результат: как ожидалось, только внутри из View изменил

enter image description here

TL;DR Теперь, если вы хотите игнорировать все выше и по-прежнему использовать андроид: гравитация с RelativeLayout, RelativeLayout есть и View, поэтому у него есть свойство android: gravity, но вы должны удалить другие свойства или LayoutParams, которые будут отменять поведение, определяемое свойством android: gravity, посмотреть на android: гравитация при работе с RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:gravity="bottom">   <!-- NOT LAYOUT PARAMS -->

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="95dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textAlignment="center"
        android:text="@string/app_title"
        android:layout_marginBottom="@dimen/main_spacing"
        android:textSize="24sp"
        android:layout_centerHorizontal="true"
        />

    <AutoCompleteTextView
        android:id="@+id/enterContact"
        android:text="Enter Contact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAlignment="center"
        android:layout_below="@+id/title"
        android:layout_marginBottom="@dimen/main_spacing" />

</RelativeLayout>

введите описание изображения здесь