如何正确删除Android中按钮周围的填充(或边距?)?

Posted

技术标签:

【中文标题】如何正确删除Android中按钮周围的填充(或边距?)?【英文标题】:How to properly remove padding (or margin?) around buttons in Android? 【发布时间】:2017-08-28 18:38:56 【问题描述】:

目前,我有以下底部登录按钮。

当按钮未被按下时

按下按钮时

XML 看起来像这样

<LinearLayout
    android:background="?attr/welcomeBottomNavBarBackground"
    android:orientation="horizontal"
    android:id="@+id/sign_in_bottom_nav_bar"
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true">
    <Button
        style="?android:attr/buttonBarButtonStyle"
        android:id="@+id/sign_in_button"
        android:layout_
        android:
        android:layout_weight="1.0"
        android:layout_
        android:gravity="center"
        android:layout_gravity="center"
        android:enabled="true"
        android:textAllCaps="true"
        android:text="@string/log_in" />
</LinearLayout>

我想在按下按钮时移除按钮周围的填充(或者我应该称之为边距?请参阅我最底部的 p/s 部分)。

我看How to remove padding around buttons in Android?

我试过了

<Button
    ...
    ...
    android:minHeight="0dp"
    android:minWidth="0dp" />

它不起作用,没有效果。


我进一步尝试

<Button
    ...
    ...
    android:background="@null"
    android:minHeight="0dp"
    android:minWidth="0dp" />

按下时不再有填充。但是,材质设计的压制视觉效果也会消失。

我可以知道在按下时移除按钮填充的最佳方法是什么,同时保留材料设计的按下视觉效果吗?

P/S

我真的不知道我应该称之为填充还是边距。我希望实现的是,当我们按下底部区域时,按下视觉效果变化应该覆盖整个 100% 底部栏区域 (@+id/sign_in_bottom_nav_bar),而不是当前 95% 底部栏区域。

【问题讨论】:

您是指文本周围的内边距还是按钮周围的边距? 我认为您想要的样式是style="@style/Widget.AppCompat.Button.Borderless",这是您从 AppCompat 库中获得的样式。 materialdoc.com/flat-button @DeeV 我添加了“p/s”部分,希望能更清楚地解释我的情况。我试过style="@style/Widget.AppCompat.Button.Borderless"。它与style="?android:attr/buttonBarButtonStyle" 没有区别(按钮文本颜色变为白色除外)。按下时,仍然没有 100% 覆盖@+id/sign_in_bottom_nav_bar 区域。 为什么不在 style.xml 文件中定义样式并在需要 ui 元素的地方调用它们。在您的按钮 style="@style/mybutton" 中并在 style.xml 中定义 mybutton 并填充零。 android:layout_ android:layout_ 这样使用会得到什么输出?你使用重量属性是为了什么?认为它不需要.. 【参考方案1】:

如今最好的解决方案就是使用MaterialButton 代替Button

注意:MaterialButton 在视觉上与 Button 和 AppCompatButton 不同。主要区别之一是 AppCompatButton 在左右两侧有一个 4dp 插图,而 MaterialButton 没有。要添加插入以匹配 AppCompatButton,请将按钮上的 android:insetLeft 和 android:insetRight 设置为 4dp,或更改按钮父布局上的间距。

在使用 MaterialButton 替换应用中的按钮时,您应该检查这些更改的大小和间距差异。

来源:https://material.io/develop/android/components/material-button/

【讨论】:

【参考方案2】:

很简单,使用inset 属性,例如:

android:insetTop="0dp"
android:insetBottom="0dp"
android:insetRight="0dp"
android:insetLeft="0dp"

【讨论】:

【参考方案3】:

在尝试了很多解决方案后,最后我得出一个结论,仅使用标签我们无法实现这一点。要删除按钮周围不需要的空间,我的解决方案如下:

 <RelativeLayout
    android:id="@+id/myButtonUnderlay"
    android:layout_
    android:layout_
    android:layout_gravity="bottom"
    android:visibility="visible">
<Button
    android:id="@+id/save_button"
    android:layout_
    android:layout_
    android:layout_marginTop="-5dp" 
    android:layout_marginBottom="-5dp"
    android:layout_above="@+id/content_scrollview"
    android:layout_gravity="bottom"
    android:background="@drawable/ripple_theme"
    android:enabled="true"
    android:text="SetUp Store"
    android:textColor="#fff"
    android:textSize="18sp"
    android:visibility="gone"
    tools:visibility="visible"
    style="@style/MediumFontTextView" />
</RelativeLayout>

【讨论】:

【参考方案4】:

不应该在全宽使用标准按钮,这就是您遇到这种情况的原因。

背景

如果您查看Material Design - Button Style,您会看到一个按钮具有 48dp 高度的点击区域,但由于...某些原因将显示为 36dp 的高度。

这是您看到的背景轮廓,不会覆盖按钮本身的整个区域。 它有圆角和一些内边距,应该可以自己点击,包裹其内容,而不是跨越屏幕底部的整个宽度。

解决方案

如上所述,您想要的是不同的背景。不是标准按钮,而是具有这种漂亮涟漪效果的可选项目的背景。

对于这个用例,您可以将?selectableItemBackground 主题属性用于您的背景(尤其是在列表中)。 它将添加一个平台标准波纹(或

对于您的用例,您可以只使用以下内容:

<Button
    android:id="@+id/sign_in_button"
    style="?android:attr/buttonBarButtonStyle"
    android:layout_
    android:layout_
    android:text="Login"
    android:background="?attr/selectableItemBackground" />
                   <!--  /\ that's all -->

如果你的视图是唯一的并且跨越整个屏幕,也不需要添加布局权重

如果您对背景应该是什么样子有不同的想法,您必须自己创建一个自定义可绘制对象,并在那里管理颜色和状态。

【讨论】:

感谢android:background="?android:selectableItemBackground" 的提示。然而,它在 Androd 6 中看起来不错。在 Android 4 中,它看起来仍然像 holo。 i.imgur.com/6PT09aP.png(预期按下颜色)。 i.imgur.com/NCgi9yC.png(更改后的样子)。知道如何让它在 Android 4 上运行吗? @CheokYanCheng 如前所述,这将采用平台默认选择器,我真的建议使用它以获得一致的外观。如果要更改它,则必须将主题属性设置为自定义可绘制对象,并且如果要为不同版本使用不同的可绘制对象,则必须确保处理所有 -v21 内容等。 使用?attr/selectableItemBackground 对 Android 6 和 Android 4 都适用。也许您想修改答案?【参考方案5】:

内边距和边距可能是按钮使用的原始资源的结果。

因此您可以尝试使用选择器更改使用的资源:

<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/btn_action_hover" />
    <item android:state_selected="true" android:drawable="@drawable/btn_action_hover" />
    <item android:state_focused="true" android:drawable="@drawable/btn_action_hover" />
    <item android:drawable="@drawable/btn_action_normal" />
</selector>

这将更改按钮的默认图像/形状,因此您可以尝试使用可绘制对象并将每个项目设置为可绘制对象。可绘制对象可以是位图,也可以是 .xml 文件(样式文件),用于定义按钮在其当前状态下的外观。我认为即使您自己设置了按钮样式,仍然包含一些原生样式。这可能是因为您没有使用自定义主题。所以这个问题也可以通过defing来解决

theme="@style/myNewTheme"

myNewTheme 是你的主题,它应该有任何父项(parent="" 不应定义)。

采用任何给定的主题(由 Google/Android 设计,例如 Theme.AppCompat.[name]),它还带有一个 buttonStyle。这是 Theme.Holo.Light 的一部分:

    <!-- Button styles -->
    <item name="buttonStyle">@style/Widget.Holo.Light.Button</item>

    <item name="buttonStyleSmall">@style/Widget.Holo.Light.Button.Small</item>
    <item name="buttonStyleInset">@style/Widget.Holo.Light.Button.Inset</item>

    <item name="buttonStyleToggle">@style/Widget.Holo.Light.Button.Toggle</item>
    <item name="switchStyle">@style/Widget.Holo.Light.CompoundButton.Switch</item>
    <item name="mediaRouteButtonStyle">@style/Widget.Holo.Light.MediaRouteButton</item>

    <item name="selectableItemBackground">@drawable/item_background_holo_light</item>
    <item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
    <item name="borderlessButtonStyle">@style/Widget.Holo.Light.Button.Borderless</item>
    <item name="homeAsUpIndicator">@drawable/ic_ab_back_holo_light</item>

如您所见,此主题定义了您的按钮在基本功能中的外观/工作方式。你可以覆盖它的一部分,但你没有覆盖重要的部分(是 buttonStyle 和类似的)。因此,如果您自己创建一个新主题并根据自己的喜好设置样式并设置主题(使用 theme="themename")并且该主题不继承任何主题,您应该能够根据自己的喜好设置按钮的样式而不必担心关于主题中的默认样式

基本上:

调用 padding/margin="0dp" 将无济于事。主题定义的默认drawable在按钮drawable中有这个,这意味着你不能改变它。所以你要么改变按钮样式,要么完全改变主题。确保主题没有任何父主题,因为许多主题定义了按钮样式。你不想要主题定义的按钮样式。

【讨论】:

【参考方案6】:

我经历过你正在经历的。长话短说,你不能单独使用&lt;Button&gt; 标签来干净利落地做到这一点,同时确保向后兼容性。

最简单且应用最广泛的方法是在&lt;Button&gt; 周围使用&lt;RelativeLayout&gt; 底层。

按钮代码:

        <RelativeLayout
            android:id="@+id/myButtonUnderlay"
            android:layout_
            android:layout_
            android:background="@color/colorPrimary"
            android:visibility="visible">

            <Button
                android:id="@+id/myButton"
                android:layout_
                android:layout_
                android:background="?attr/selectableItemBackgroundBorderless"
                android:text="I am as cute as a Button"/>

        </RelativeLayout>

无论您需要在何处使用按钮,都可以使用此完整代码。

以下是细分:


    OnClick 事件将与myButton 挂钩。 通过更改myButtonUnderlay 的属性来控制按钮的尺寸。 在myButtonandroid:background="?attr/selectableItemBackgroundBorderless"。这将使它成为一个透明按钮,仅包含文本和向后兼容的波纹。 在myButtonUnderlay 中,您将执行所有其他后台应用程序,例如设置按钮的颜色、边距、内边距、边框、渐变和阴影等。 如果希望控制按钮的可见性(无论是否以编程方式),您都可以在 myButtonUnderlay 上进行操作。

注意:为确保向后兼容,请务必使用

android:background="?attr/selectableItemBackgroundBorderless"不是

android:background="?android:attr/selectableItemBackgroundBorderless"

【讨论】:

【参考方案7】:

作为@David Medenjak 的回答,您可以在其开发者网站上阅读 Google Material design Button-style。使用@David Medenjak 在他的回答中解释的按钮样式。您也可以通过以下方式进行 它不是填充或边距,但它实际上是按钮的背景效果。 如果您想删除它,那么您可以执行以下操作。

选项 1:

第1步:将以下代码放入styles.xml中

<style name="myColoredButton">
        <item name="android:textColor">#FF3E96</item>
        <item name="android:padding">0dp</item>
        <item name="android:minWidth">88dp</item>
        <item name="android:minHeight">36dp</item>
        <item name="android:elevation">1dp</item>
        <item name="android:translationZ">1dp</item>
        <item name="android:background">#FF0000</item>
    </style>

第二步:在drawables文件夹下新建一个XML文件,添加如下代码:我把我的XML文件命名为button_prime.xml

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimary">
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <corners android:radius="1dp" />
            <solid android:color="#8B8386" />
        </shape>
    </item>
</ripple>

第 3 步:在 Button 中使用样式和可绘制对象,如下所示。

<Button
        style="@style/myColoredButton"
        android:layout_
        android:layout_
        android:text="Cancel"
        android:gravity="center"
        android:background="@drawable/button_prime"
        android:colorButtonNormal="#3578A9" />

选项 2:

使用支持库 v7,所有样式实际上已经定义并可以使用,对于标准按钮,所有这些样式都可用。因此您可以像这样设置按钮样式

<Button
    style="@style/Widget.AppCompat.Button.Borderless"
    android:layout_
    android:layout_
    android:text="BUTTON"
    android:gravity="center"
    android:minHeight="0dp"
    android:minWidth="0dp"
    android:background="@color/colorAccent"/>

更多按钮样式请check this answer

我想你也会检查this answer。我希望你能得到你的解决方案。

【讨论】:

【参考方案8】:

我真的不知道我应该称之为填充还是边距。

该按钮正在制定表面高度,以响应触摸提供视觉反馈。它是用于surface reaction 的两个反馈之一;第一个是连锁反应。例如,一个凸起按钮的静止状态高度为 2dp,按下状态高度为 8dp(参见 Shadows 下的凸起按钮)。按钮在接触表面时与手指接触。

我可以知道在按下时移除按钮填充的最佳方法是什么,同时保留材料设计的按下视觉效果?

在回答了第一部分之后,如果您希望移除表面高程效果,我不相信您已经掌握了所有材料设计。

无论如何,这里是如何移除表面高程视觉反馈:

将动画文件button_raise.xml添加到res目录下的animator目录,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_enabled="true"
        android:state_pressed="true">

        <objectAnimator
            android:duration="@android:integer/config_shortAnimTime"
            android:propertyName="translationZ"
            android:valueTo="0dp"
            android:valueType="floatType" />
    </item>
</selector>

使用stateListAnimator属性在按钮中引用新创建的动画师:

<Button
    ...
    android:stateListAnimator="@animator/button_raise"
    ... />

希望这会有所帮助。

【讨论】:

【参考方案9】:

1.添加一个名为button_background.xml的可绘制资源文件

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#ff0000"/>
            <stroke android: android:color="#00ff00"/>
        </shape>
    </item>
    <item>
        <shape>
            <solid android:color="#00ff00"/>
        </shape>
    </item>
</selector>

2.使用button_background.xml作为按钮背景,完成!

github

blog

【讨论】:

【参考方案10】:

Button背景设置为android:background="?selectableItemBackground"

<LinearLayout
    android:background="?attr/welcomeBottomNavBarBackground"
    android:orientation="horizontal"
    android:id="@+id/sign_in_bottom_nav_bar"
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true">

    <Button
        style="?android:attr/buttonBarButtonStyle"
        android:background="?selectableItemBackground"
        android:id="@+id/sign_in_button"
        android:layout_
        android:
        android:layout_weight="1.0"
        android:layout_
        android:gravity="center"
        android:layout_gravity="center"
        android:enabled="true"
        android:textAllCaps="true"
        android:text="@string/log_in" />

</LinearLayout>

【讨论】:

【参考方案11】:

我建议你看看this,以防万一。

然后,如果不工作,我建议您使用 android xml 可绘制对象创建自己的样式(如 azizbekian 建议),并使用可绘制状态来区分按下/未按下。

我认为使用您自己的样式可能是最好的答案,因为它可以进一步让您更好地控制应用的显示方式,但是使用 android 默认主题和样式还允许用户拥有自定义样式,这是一个好主意。但是,您无法测试每个自定义样式,因此您无法检查您的应用是否会在所有自定义样式上正确显示,因此可能会遇到一些问题。

【讨论】:

【参考方案12】:

styles.xml

<style name="MyButtonStyle" parent="Base.Widget.AppCompat.Button">
    <item name="android:background">@drawable/selector</item>
    <item name="android:textColor">@android:color/black</item>
</style>

values/drawable:

my_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="2dp" />
    <!-- specify your desired color here -->
    <solid android:color="#9e9b99" />
</shape>

selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:drawable="@drawable/my_drawable"/>
    <item android:state_pressed="true" android:drawable="@drawable/my_drawable"/>
    <item android:drawable="@android:color/transparent"/>
</selector>

values/drawable-v21:

my_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
       android:tint="?attr/colorButtonNormal"
       xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="2dp" />
    <solid android:color="@android:color/white" />
</shape>

selector.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight">
    <item android:id="@android:id/mask"
          android:drawable="@drawable/my_drawable" />
</ripple>

在布局中:

<Button
    android:id="@+id/button"
    style="@style/MyButtonStyle"
    android:layout_
    android:layout_
    android:text="Test"/>

API 19 上的结果:

API 21 上的结果:

Source code

【讨论】:

嗨,由于多种原因,这不能按预期工作。对于 v21 设备,它看起来像 imgur.com/a/zg2j7 和 imgur.com/a/OvpbV。由于我们在应用程序中使用不同颜色的主题,我们希望 (1) 按钮背景是透明的,以便它显示其父级的颜色 (@+id/sign_in_bottom_nav_bar) (2) 按钮文字颜色也不再准确。我们希望它使用colorAccent 对于v21以下的设备,除了上面提到的2个问题外,它们还失去了所有的新闻视觉效果。 @CheokYanCheng,确实如此。更新了答案。【参考方案13】:

我认为最好的解决方案是创建自己的Ripple Effect。按下按钮时的填充尊重组件的默认Ripple Effect

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight">
    <item android:drawable="?attr/colorPrimary"/>
</ripple>

或者您可以尝试将按钮的样式更改为style="?android:textAppearanceSmall"

记住:此效果仅在Android Lollipop (API 21) 或更高版本上显示。

【讨论】:

以上是关于如何正确删除Android中按钮周围的填充(或边距?)?的主要内容,如果未能解决你的问题,请参考以下文章

如何仅向 Angular ngMaterial 中的布局容器添加填充或边距?

从 Google 图表中删除填充或边距

Android中不需要的填充或按钮周围的边距

Bootstrap - 当屏幕尺寸较小时删除填充或边距

Bootstrap - 当屏幕尺寸较小时删除图形的填充或边距

如何设置按钮的内部文本边距