简体   繁体   English

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

[英]How to properly remove padding (or margin?) around buttons in Android?

Currently, I have the following bottom log in button.目前,我有以下底部登录按钮。

When button is not being pressed未按下按钮时

在此处输入图片说明

When button is being pressed当按钮被按下时

在此处输入图片说明

The XML looks like this XML 看起来像这样

<LinearLayout
    android:background="?attr/welcomeBottomNavBarBackground"
    android:orientation="horizontal"
    android:id="@+id/sign_in_bottom_nav_bar"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true">
    <Button
        style="?android:attr/buttonBarButtonStyle"
        android:id="@+id/sign_in_button"
        android:layout_width="0dp"
        android:width="0dp"
        android:layout_weight="1.0"
        android:layout_height="48dp"
        android:gravity="center"
        android:layout_gravity="center"
        android:enabled="true"
        android:textAllCaps="true"
        android:text="@string/log_in" />
</LinearLayout>

I would like to remove the padding (Or should I call it margin? Please refer to my bottom most p/s section) around button when it is being pressed.我想在按下按钮时删除按钮周围的填充(或者我应该称之为边距?请参阅我最底部的 p/s 部分)。

I look at How to remove padding around buttons in Android?我看看如何在 Android 中删除按钮周围的填充?

I had tried我试过了

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

It doesn't work and has no effect.它不起作用,也没有效果。


I further try我进一步尝试

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

No more padding when pressed.按下时不再填充。 However, the material designed pressed visual effect will gone too.然而,材料设计的压制视觉效果也会消失。

May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?我可以知道在按下过程中删除按钮填充的最佳方法是什么,同时保留材料设计的按下视觉效果?

P/S P/S

I don't really know whether I should call it padding or margin.我真的不知道我应该称之为填充还是边距。 What I wish to achieve is that, when we press on the bottom region, press visual effect change should be covered entire 100% bottom bar region ( @+id/sign_in_bottom_nav_bar ), instead of current 95% bottom bar region.我希望实现的是,当我们按下底部区域时,按下视觉效果变化应该覆盖整个 100% 底部栏区域( @+id/sign_in_bottom_nav_bar ),而不是当前 95% 底部栏区域。

A standard button is not supposed to be used at full width which is why you experience this.标准按钮不应该以全宽使用,这就是您遇到这种情况的原因。

Background背景

If you have a look at the Material Design - Button Style you will see that a button has a 48dp height click area, but will be displayed as 36dp of height for...some reason.如果您查看Material Design - Button Style,您将看到按钮具有 48dp 高度的点击区域,但出于某种原因将显示为 36dp 的高度。

This is the background outline you see, which will not cover the whole area of the button itself.这是您看到的背景轮廓,它不会覆盖按钮本身的整个区域。
It has rounded corners and some padding and is supposed to be clickable by itself, wrap its content, and not span the whole width at the bottom of your screen.它有圆角和一些填充,并且应该可以自己点击,包裹其内容,而不是跨越屏幕底部的整个宽度。

Solution解决方案

As mentioned above, what you want is a different background .如上所述,您想要的是不同的背景 Not a standard button, but a background for a selectable item with this nice ripple effect.不是标准按钮,而是具有这种漂亮涟漪效果的可选项目的背景。

For this use case there is the ?selectableItemBackground theme attribute which you can use for your backgrounds (especially in lists).对于这个用例,有?selectableItemBackground主题属性,您可以将其用于背景(尤其是在列表中)。
It will add a platform standard ripple (or some color state list on < 21) and will use your current theme colors.它将添加一个平台标准波纹(或 < 21 上的一些颜色状态列表),并将使用您当前的主题颜色。

For your usecase you might just use the following:对于您的用例,您可能只使用以下内容:

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

There is also no need to add layout weights if your view is the only one and spans the whole screen如果您的视图是唯一的并且跨越整个屏幕,则也无需添加布局权重

If you have some different idea on what your background should look like you have to create a custom drawable yourself, and manage color and state there.如果你对背景应该是什么样子有一些不同的想法,你必须自己创建一个自定义的可绘制对象,并在那里管理颜色和状态。

As simple, use the inset property like:很简单,使用inset属性,如:

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

In styles.xmlstyles.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>

In values/drawable :values/drawable

my_drawable.xml 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

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

In values/drawable-v21 :values/drawable-v21

my_drawable.xml 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

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

In layout:在布局中:

<Button
    android:id="@+id/button"
    style="@style/MyButtonStyle"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:text="Test"/>

Result on API 19: API 19 上的结果:

在此处输入图片说明

Result on API 21: API 21 的结果:

在此处输入图片说明

Source code源代码

I think the best solution to solve that is create your own Ripple Effect .我认为解决这个问题的最佳解决方案是创建自己的Ripple Effect The padding when you press the button is respecting the default Ripple Effect of the component.按下按钮时的填充Ripple Effect组件的默认Ripple Effect

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

Or you can try change the style of your button to style="?android:textAppearanceSmall"或者您可以尝试将按钮的样式更改为style="?android:textAppearanceSmall"

Remember: This effect is only shown on Android Lollipop (API 21) or higher.请记住:此效果仅在Android Lollipop (API 21)或更高版本上显示。

I have been through what you are going through.我经历过你正在经历的事情。 Long story short, you just cannot do it cleanly with a <Button> tag alone, while ensuring backwards compatibility.长话短说,你不能单独使用<Button>标签做到这一点,同时确保向后兼容性。

The simplest and the most widely practiced method is to use a <RelativeLayout> underlay, around a <Button> .最简单和最广泛使用的方法是在<Button>周围使用<RelativeLayout>底层。

Button Code:按钮代码:

        <RelativeLayout
            android:id="@+id/myButtonUnderlay"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:visibility="visible">

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

        </RelativeLayout>

Wherever you need to use a button, you use this complete code.无论您需要在何处使用按钮,都可以使用此完整代码。

Here is the breakdown:这是细分:


  1. OnClick events will be hooked to myButton . OnClick 事件将连接到myButton
  2. Control dimensions of your button, by changing attributes of myButtonUnderlay .通过更改myButtonUnderlay属性来控制按钮的尺寸。
  3. In myButton , android:background="?attr/selectableItemBackgroundBorderless" .myButtonandroid:background="?attr/selectableItemBackgroundBorderless" This will make it a transparent button with just the text, and backwards compatible ripples.这将使它成为一个透明的按钮,只有文本和向后兼容的涟漪。
  4. In myButtonUnderlay , you will do all the other background applications, like setting the color of the button, margins, paddings, borders, gradients, and shadows etc.myButtonUnderlay ,您将执行所有其他后台应用程序,例如设置按钮的颜色、边距、填充、边框、渐变和阴影等。
  5. If manipulation of the button's visibility (programmatic or not) is wish, you do it on myButtonUnderlay .如果希望操作按钮的可见性(编程与否),您可以在myButtonUnderlay

Note: To ensure backwards compatibility, make sure that you use注意:为确保向后兼容,请确保您使用

android:background="?attr/selectableItemBackgroundBorderless" , and NOT android:background="?attr/selectableItemBackgroundBorderless" ,而不是

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

As @David Medenjak answer you can read the Google Material design Button-style to its developer site.正如@David Medenjak 回答的那样,您可以在其开发人员网站上阅读 Google Material design Button-style Use button style as @David Medenjak explained in his answer.使用@David Medenjak 在他的回答中解释的按钮样式。 You can also do by the following way also It is not a padding or margin but it is actually background effect of button.您也可以通过以下方式进行它也不是填充或边距,但它实际上是按钮的背景效果。 If you want to remove that then you can do as following.如果您想删除它,那么您可以执行以下操作。

Option 1:选项1:

Step 1: Put the below code in styles.xml第 1 步:将下面的代码放在 style.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>

Step 2:Create a new XML file under drawables folder and add the following code: I named my XML file as button_prime.xml第 2 步:在 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>

Step 3: Use the style and drawable in your Button as follows.第 3 步:按如下方式在 Button 中使用样式和可绘制对象。

<Button
        style="@style/myColoredButton"
        android:layout_width="250dp"
        android:layout_height="50dp"
        android:text="Cancel"
        android:gravity="center"
        android:background="@drawable/button_prime"
        android:colorButtonNormal="#3578A9" />

Option 2:选项 2:

With the Support Library v7, all the styles are actually already defined and ready to use, for the standard buttons, all of these styles are available.So you can set your button style like this使用支持库 v7,实际上所有样式都已经定义并可以使用,对于标准按钮,所有这些样式都可用。因此您可以像这样设置按钮样式

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

For more detail of Button style please check this answer有关按钮样式的更多详细信息,请查看此答案

I think you will check this answer also.我想你也会检查这个答案 I hope you will get your solution.我希望你能得到你的解决方案。

The padding and margin may be a result of the original resources used in the button.填充和边距可能是按钮中使用的原始资源的结果。

So you could try to change the resources used, using a selector:因此,您可以尝试使用选择器更改使用的资源:

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

That would change the default images/shapes for your buttons, so you could try using drawables and set every item to a drawable.这将更改按钮的默认图像/形状,因此您可以尝试使用可绘制对象并将每个项目设置为可绘制对象。 The drawable being either a bitmap, or a .xml file(style file) defining the look of the button in its current state. drawable 可以是位图,也可以是 .xml 文件(样式文件),用于定义按钮在当前状态下的外观。 I assume there still are some native styles included even though you have set the button-style yourself.我认为即使您自己设置了按钮样式,仍然包含一些本机样式。 This may be because you aren't using a custom theme.这可能是因为您没有使用自定义主题。 So the issue may also be solved by defing所以这个问题也可以通过defing来解决

theme="@style/myNewTheme"

where myNewTheme is your theme, and it should have any parents( parent="" should not be defined).其中 myNewTheme 是您的主题,它应该有任何父级(不应定义parent="" )。

Take any given theme(designed by Google/Android, for an instance Theme.AppCompat.[name]), it does also come with a buttonStyle.以任何给定的主题(由 Google/Android 设计,例如 Theme.AppCompat.[name]),它也带有一个 buttonStyle。 This is a part of Theme.Holo.Light:这是 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>

As you see, this theme defines how your buttons will look/work in basic features.如您所见,此主题定义了按钮在基本功能中的外观/工作方式。 You can override parts of it, but you haven't overridden the important parts(being buttonStyle and similar).你可以覆盖它的一部分,但你没有覆盖重要的部分(按钮样式和类似的)。 So if you create a new theme yourself and style it to your liking and set the theme(using theme="themename") and that theme does not inherit any theme, you should be able to style your buttons to your liking without having to worry about the default styles in the theme因此,如果您自己创建一个新主题并根据自己的喜好设置样式并设置主题(使用 theme="themename")并且该主题不继承任何主题,您应该能够根据自己的喜好设置按钮样式而不必担心关于主题中的默认样式

Basically:基本上:

calling padding/margin="0dp" will not help.调用 padding/margin="0dp" 将无济于事。 The default drawable defined by the theme has this in the button drawable, meaning you cannot change it.主题定义的默认可绘制对象在按钮可绘制对象中具有此项,这意味着您无法更改它。 So you have to either change the button style, or change the theme completely.所以你要么改变按钮样式,要么完全改变主题。 Make sure that theme does not have any parents, because many themes define the button style.确保主题没有任何父主题,因为许多主题定义了按钮样式。 You do not want the button style defined by the theme.您不想要主题定义的按钮样式。

The best solution these days is just to use MaterialButton in place of Button .目前最好的解决方案是使用MaterialButton代替Button

Note: MaterialButton is visually different from Button and AppCompatButton.注意:MaterialButton 在视觉上与 Button 和 AppCompatButton 不同。 One of the main differences is that AppCompatButton has a 4dp inset on the left and right sides, whereas MaterialButton does not.主要区别之一是 AppCompatButton 在左右两侧有一个 4dp 的内嵌,而 MaterialButton 没有。 To add an inset to match AppCompatButton, set android:insetLeft and android:insetRight on the button to 4dp, or change the spacing on the button's parent layout.要添加一个 inset 以匹配 AppCompatButton,请将按钮上的 android:insetLeft 和 android:insetRight 设置为 4dp,或者更改按钮父布局上的间距。

When replacing buttons in your app with MaterialButton, you should inspect these changes for sizing and spacing differences.使用 MaterialButton 替换应用中的按钮时,您应该检查这些更改的大小和间距差异。

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

I'd suggest you taking a look at this just in case before all.我建议你先看看这个以防万一。

Then, if not working i'd suggest you to create your own style (like azizbekian suggest)using android xml drawables, and drawable states to differentiate pressed/notpressed.然后,如果不起作用,我建议您使用 android xml drawables 创建自己的样式(如 azizbekian 建议),并使用 drawable 状态来区分按下/未按下。

I think using your own style may be the best answer as it will further give you more control on how your app is displaying, but using android default themes and styles also allows the user to have custom styles which is a good idea.我认为使用您自己的样式可能是最好的答案,因为它可以进一步让您更好地控制应用程序的显示方式,但使用 android 默认主题和样式还允许用户拥有自定义样式,这是一个好主意。 However, you cannot test every custom style so you cannot check that your app will display correctly on ALL custom styles, and therefore may encounter problems with some.但是,您无法测试每个自定义样式,因此您无法检查您的应用程序是否会在所有自定义样式上正确显示,因此可能会遇到一些问题。

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

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

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

</LinearLayout>

After trying lots of solution, Finally I came to a conclusion that with tag alone we can't achieve this.在尝试了很多解决方案之后,我终于得出结论,仅凭标签我们无法实现这一点。 to remove this unwanted space around button my solution is as below:要删除按钮周围不需要的空间,我的解决方案如下:

 <RelativeLayout
    android:id="@+id/myButtonUnderlay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:visibility="visible">
<Button
    android:id="@+id/save_button"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    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>

1.add a drawable resource file named maybe button_background.xml 1.添加一个drawable资源文件,命名为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:width="5dp" android:color="#00ff00"/>
        </shape>
    </item>
    <item>
        <shape>
            <solid android:color="#00ff00"/>
        </shape>
    </item>
</selector>

2.Use the button_background.xml as the button background, done! 2.使用button_background.xml作为按钮背景,大功告成!

github github

blog 博客

I don't really know whether I should call it padding or margin.我真的不知道我应该称之为填充还是边距。

The button is enacting surface elevation for providing visual feedback in response to touch.该按钮正在制定表面高度,以响应触摸提供视觉反馈。 It is one of two feedbacks used for surface reaction ;它是用于表面反应的两个反馈之一; the first one being the ripple effect.第一个是涟漪效应。 For example, a raised button has resting state elevation of 2dp and pressed state elevation of 8dp (See raised button under Shadows ).例如,凸起按钮的静止状态高度为 2dp,按下状态高度为 8dp(参见阴影下的凸起按钮)。 The button meets the finger as it touches the surface.当手指接触表面时,按钮会与手指接触。

May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?我可以知道在按下过程中删除按钮填充的最佳方法是什么,同时保留材料设计的按下视觉效果?

Having answered the first part, I do not believe you are having all of the material design if you wish to remove the surface elevation effect.回答了第一部分后,如果您希望消除表面高程效果,我不相信您拥有所有的材料设计。

Anyways, here is how to remove surface elevation visual feedback:无论如何,这里是如何删除表面高程视觉反馈:

Add animator file button_raise.xml to animator directory under res directory having the following code:将动画文件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>

Refer newly created animator in the button using stateListAnimator property:使用stateListAnimator属性在按钮中引用新创建的动画器:

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

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM