为什么重力在应用于相对布局时不起作用?

Why doesn't gravity work when applied to Relative Layout?

我已经明白,如果我在文本视图上使用 layout_gravity="center_horizontal",那么文本将居中。但我不想使用它,因为我希望代码尽可能少,最好的方法是将 gravity="center_horizontal" 应用于我的相对布局。我也在问这个问题,因为我什至担心将 gravitylayout_gravity 与相对布局一起使用。在做研究时,我发现了 this 答案。

注意下面的部分:

Don't use gravity/layout_gravity with a RelativeLayout. Use them for Views in LinearLayouts and 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>

正在测试您的布局,对我来说它工作正常(TextView 正确居中)。

但是,您也可以从 RelativeLayout 中删除 android:gravity="center_horizontal" 并在 TextView 中添加 android:layout_centerHorizontal="true"

我也一直对 RelativeLayouts 和 TextViews 有疑问。我认为这是由于 TextView 会动态计算其大小,这会阻止它与布局的重力配合使用。这只是我的一个假设。 我一般采用的解决方案是配置一个textview水平大小为match_parent。这可能是一个次优的解决方案,但应该有效。如果您需要一个固定大小的 textView,您可以放置​​一个固定大小的尺寸并且应该也可以工作,它只会给 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"

with wrap_content 应该也可以。原因在我的脑海里还是一样的:textView的大小是稍后计算的。

试试这个:

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

作为 documentation says:

android:gravity

Specifies how an object should position its content, on both the X and Y axes, within its own bounds.

...

center_horizontal

Place object in the horizontal center of its container, not changing its size.

因此 android:gravity="center_horizontal" 会将 horizontal-ing RelativeLayout 居中到其父级。没有使其内容中心水平。

请记住,android:layout_gravity 用于相对于父级或布局的视图本身。

请注意,每个 API 级别的布局行为可能略有不同。请注意,我们不能 100% 确定 Layout Editor 中的视觉结果是正确的。始终在真实设备中测试您的布局。

TlDr: android:gravity Works with 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显然)却行不通?

  1. 如果您的目标是将 TextView 置于 Layout/Screen 的水平中心,您必须让 RelativeLayout 知道!

  2. 这是通过称为 LayoutParams 的东西实现的 - 这些是由每个 View 定义的数据结构,它们由 View 的父级(在本例中为 RelativeLayout)使用

  3. 假设您的 TextView 具有以下 LayoutParams :

    android:layout_centerHorizontal="true"

你会得到这样的东西:

RelativeLayout 在屏幕上分布其子视图时,沿途有一个回调方法 运行 - onLayout(...) - 这是更复杂方法的一部分 将确定每个子视图在 RelativeLayout 中的位置的顺序,部分是通过访问每个子视图中的 LayoutParams 来实现的View,在这种情况下,您的 TextView

中的那一行
  1. 这就是为什么我们说 LayoutParams 像在 link you mentioned before
  2. 中一样传递给父级

警告:无尽的混乱来源!

视图在 Layouts / ViewGroups 内的定位是通过 LayoutParams 完成的 onLayout 调用

碰巧像FrameLayout这样的一些布局有一个叫做android:layout_gravity的LayoutParam,这与每个视图可以定义的android:gravity 属性造成了很大的混淆,这是不一样甚至不一样LayoutParam

android:gravity 被任何视图(例如 TextView)用来将其内容放入其中。

示例:假设您将 TextView 更改为 非常高,并且您希望文本位于 TextView 的底部, 而不是在顶部

<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 在 RelativeLayout 中 居中,但文本位于 "box"

TOP

让我们使用 android:gravity 来管理 文本位置 INSIDE THE 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
        />

结果:正如预期的那样,只有视图的内部发生了变化

TLDR 现在如果你想忽略上面的所有内容并仍然使用 android:gravity 和 RelativeLayout,RelativeLayout 也是一个 View 所以它有 android:gravity 属性,但您必须 删除 其他属性或布局参数,这将 覆盖 android:gravity 定义的行为 属性 看看 android:gravity 和 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>

这是对 Gravity and layout_gravity on Android 的补充回答。

在相对布局中查看 gravitylayout_gravity

我最初关于 gravitylayout_gravity 不应在 RelativeLayout 的子视图中使用的声明部分是错误的。 gravity 实际上工作正常。但是,layout_gravity 没有任何作用。这可以在下面的示例中看到。浅绿色和浅蓝色是 TextView。另外两种背景颜色是RelativeLayouts。

如您所见,gravity 有效,但 layout_gravity 无效。

相对布局 gravity

我关于 gravitylayout_gravityoriginal answer 处理这些属性应用于 ViewGroup(特别是 LinearLayout)内的视图,而不是到 ViewGroup 本身。但是,可以在 RelativeLayout 上设置 gravitylayout_gravitylayout_gravity 会影响 RelativeLayout 在它自己的 parent 中的定位方式,所以我不会在这里处理。 gravity 如何影响子视图,如下图所示。

我调整了所有子视图的宽度,以便更清楚地了解正在发生的事情。请注意,RelativeLayout 处理重力的方式是将所有子视图作为一个组并在布局中移动它们。这意味着无论哪个视图最宽,都将决定其他所有内容的位置。因此相对布局中的引力可能仅在所有子视图具有相同宽度时才有用。

线性布局 gravity

当您将 gravity 添加到 LinearLayout 时,它会按预期排列子视图。例如,可以通过将 LinearLayoutgravity 设置为 center_horizontally 来“保存代码”。这样就不需要单独设置每个子视图的 layout_gravity 。请参阅下图中的各种选项。

请注意,当视图使用 layout_gravity 时,它会覆盖 LinearLayout 的引力。 (这可以在左图中的两个布局的标题中看到。LinearLayout gravity 被设置为 leftright,但 TextView 的标题 layout_gravity 被设置到 center_horizontally.)

最后的笔记

positioning views within a RelativeLayout 时,一般的做法是在 each 视图中添加如下内容:

  • layout_alignParentTop
  • layout_centerVertical
  • layout_below
  • layout_toRightOf

如果想一次设置所有视图,LinearLayout 可能会更好(或者可能使用样式)。

综上所述,

  • layout_gravity 不适用于 RelativeLayout 中的子视图。
  • RelativeLayout 的 gravity 确实有效,但不像人们预期的那样。

补充XML

XML for image "View gravity and layout_gravity inside a Relative Layout":

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