Android - 自定义样式中指定的边距无效

30

我希望EditText的默认margin为10dp,因此我在我的styles.xml文件中设置如下:

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <style name="MyTheme" parent="android:style/Theme.NoTitleBar">
        <item name="android:editTextStyle">@style/edit_text_default</item>
    </style>

    <style name="edit_text_default" parent="android:style/Widget.EditText">
        <item name="android:layout_margin">10dp</item>
    </style>

</resources>

然后在 AndroidManifest.xml 文件中,我将应用程序的主题设置为我定义的主题:

<application
     android:icon="@drawable/ic_launcher"
     android:label="@string/app_name"
     android:theme="@style/MyTheme" >
...

主题的“无标题栏”功能正在工作。但是EditText的默认边距不起作用,它仍然填充父容器。这是我的表格视图:

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF" >
    <TableRow>
        <EditText android:hint="@string/last_name" />
    </TableRow>
    <TableRow>
        <EditText android:hint="@string/first_name" />
    </TableRow>
</TableLayout>
3个回答

60

简短回答: 如果您在自定义样式中指定layout_margin,则必须明确地将此样式应用于您希望具有指定边距的每个单独视图(如下面的代码示例所示)。将此样式包含在主题中并将其应用于您的应用程序或活动将不起作用。

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF" >
    <TableRow>
        <EditText android:hint="@string/last_name" style="@style/edit_text_default" />
    </TableRow>
    <TableRow>
        <EditText android:hint="@string/first_name" style="@style/edit_text_default" />
    </TableRow>
</TableLayout>
解释:layout_ 开头的属性是 LayoutParams 或者它的子类(例如 MarginLayoutParams)。LayoutParams 被视图用来告诉其父 ViewGroup 如何布局它们。每个 ViewGroup 类都实现了一个继承自 ViewGroup.LayoutParams 的嵌套类。因此,LayoutParams 是特定于 ViewGroup 类型的。这意味着,虽然 TableLayoutLinearLayout 都可以将 layout_margin 作为其 LayoutParams 之一,但它们被认为是完全不同的属性。
因此,layout_margin 不仅仅是可在任何地方应用的通用属性。它必须在明确将其定义为有效参数的 ViewGroup 上下文中应用。当应用 LayoutParams 时,视图必须知道其父 ViewGroup 的类型。
在样式中指定 layout_margin,将该样式包含在主题中,并尝试将该主题应用于应用程序/活动将导致布局属性被丢弃,因为尚未指定 ViewGroup 父项,因此参数无效。但是,将样式应用于已使用 TableLayout 定义的 EditText 视图将起作用,因为父 ViewGroup(即 TableLayout)已知。 来源:
Android 文档中关于布局参数的说明。
由 Android 框架工程师和 StackOverflow 用户 adamp 所提供的答案
由 StackOverflow 用户 inazaruk 所提供的答案

10
W...T...F?? 为什么?为什么?为什么?!?! 请原谅我……我受够了Android开发的所有怪癖。 - pbristow
1
这个答案有些不尽如人意 - 即使父ViewGroup和子View在同一个布局xml文件中,布局边距仍然没有被应用。在这种情况下,布局填充器确实知道父ViewGroup的具体类型(因为它刚刚填充了它),并且也知道要应用的样式(因为其他样式属性已经被应用)。 - Robert Tuck

1

您在清单文件中使用的主题名称不正确。请尝试将其更改为:

<application
     android:icon="@drawable/ic_launcher"
     android:label="@string/app_name"
     android:theme="@style/MyTheme" >

抱歉,那是我在帖子中的笔误。它们在我的实际项目中是相同的。不过你提出了一个好建议 :/ - Groppe

0

如果对其他人有用的话,我想在这里分享Oliv在另一个SO问题中的答案

我试图为所有按钮添加边距,但发现layout_margin不起作用。

主题:

<style name="FooThemeStyle" parent="Base.Theme.AppCompat">
    <item name="android:buttonStyle">@style/FooButton</item>
    <item name="buttonStyle">@style/FooButton</item>
</style>

按钮样式:
<style name="FooButton" parent="Widget.AppCompat.Button">
    <item name="android:background">@drawable/button_background</item>
</style>

这里是button_background.xml,其中使用了Oliv对另一个SO问题的回答来设置边距为2dp:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp">
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
          ...
        </selector>
    </item>
</layer-list>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接