Material 带边框的设计按钮

Material design button with border

我知道如何制作 Material 带有颜色填充的设计按钮:

style="@style/Widget.AppCompat.Button.Colored"

无边框透明按钮:

style="@style/Widget.AppCompat.Button.Borderless.Colored"

但是,有没有办法让 Material 设计有边框(内部透明)的按钮?像下面这样的东西?

这就是我在 Lollipop 及更高版本上制作仅带边框和波纹效果的按钮的方法。就像 AppCompat 按钮一样,这些按钮对较低的 API 具有后备按下效果(如果您需要在较低的 API 上产生涟漪,则需要使用外部库)。我使用 FrameLayout 因为它很便宜。文字和边框的颜色是黑色的,但是你可以用自定义的颜色来改变它:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="20dp"
    android:background="@drawable/background_button_ghost">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?android:selectableItemBackground"
        android:gravity="center"
        android:padding="14dp"
        android:textSize="16sp"
        android:textAllCaps="true"
        android:textStyle="bold"
        android:textColor="@android:color/black"
        android:text="Text"/>
</FrameLayout>

drawable/background_button_ghost.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="2dp"
        android:color="@android:color/black"/>
    <solid android:color="@color/transparent"/>
</shape>

如果我遗漏了什么,请发表评论,我会更新答案。

只需您就可以使用此代码。 看起来真不错。

           <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#ffffff"
                android:orientation="vertical">

                <android.support.v7.widget.AppCompatButton
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:backgroundTint="#F48025"
                    android:text="login"
                    android:textColor="@color/colorWhite" />

            </LinearLayout>

此处边框颜色为:

android:background="#ffffff"

背景颜色为:

android:backgroundTint="#F48025"

以下是正确的做法。

你需要做的是

1 - 创建带描边的可绘制形状
2 - 创建波纹可绘制对象
3 - 创建小于 v21
的选择器 drawable 4 - 为带边框的按钮创建新样式
5 - 在按钮上应用样式

1 - 用描边创建形状 btn_outline.xml

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

    <stroke
        android:width="2dp"
        android:color="@color/colorAccent">
    </stroke>
    <solid android:color="@color/colorTransparent"/>
    <corners
        android:radius="5dp">
    </corners>

</shape>

2 - 创建波纹可绘制对象 drawable-v21/bg_btn_outline.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorOverlay">
    <item>
        <shape>
            <stroke
                android:width="2dp"
                android:color="@color/colorAccent"/>
            <corners android:radius="5dp"/>
        </shape>
    </item>
    <item android:id="@android:id/mask">
        <shape>
            <stroke
                android:width="2dp"
                android:color="@color/colorAccent"/>
            <solid android:color="@android:color/white"/>
            <corners android:radius="5dp"/>
        </shape>
    </item>

</ripple>

android:id="@android:id/mask" 需要在按钮上有波纹触摸反馈。标记为蒙版的图层在屏幕上不可见,仅用于触摸反馈。

3 - 创建小于 v21 的选择器可绘制对象 drawable/bg_btn_outline.xml

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

    <item android:drawable="@drawable/btn_outline"/>

</selector>

4 - 为带边框的按钮创建新样式 创建样式所需的所有资源都在上面给出,这就是您的样式应该是什么样子

<style name="ButtonBorder" parent="Widget.AppCompat.Button.Colored"/>

<style name="ButtonBorder.Accent">
        <item name="android:background">@drawable/bg_btn_outline</item>
        <item name="android:textColor">@color/colorAccent</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:textSize">16sp</item>
        <item name="android:singleLine">true</item>
    </style>

4 - 在按钮上应用样式

<Button
   style="@style/ButtonBorder.Accent"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

差不多就这些了。下面是按钮现在的外观示例。

您也可以使用 Material Components for Android

the dependency 添加到您的 build.gradle:

dependencies { implementation 'com.google.android.material:material:1.3.0' }

在这种情况下,您可以在布局文件中使用 MaterialButton

<com.google.android.material.button.MaterialButton
   ....
   style="@style/Widget.MaterialComponents.Button.OutlinedButton"
   app:cornerRadius=".."
   app:strokeColor="@color/colorPrimary"/>

应用样式 @style/Widget.MaterialComponents.Button.OutlinedButton

在您的情况下,使用 app:cornerRadius 属性更改圆角半径的大小。这将以指定的尺寸圆整角。
使用属性 app:strokeColorapp:strokeWidth 改变边框的颜色和宽度。

您还可以使用ShapeApperance自定义角(需要1.1.0版本)

<style name="MyButton" parent="Widget.MaterialComponents.Button.OutlinedButton">
    <item name="shapeAppearanceOverlay">@style/MyShapeAppearance</item>
</style>
<style name="MyShapeAppearance" parent="">
    <item name="cornerFamilyTopLeft">rounded</item>
    <item name="cornerFamilyBottomLeft">rounded</item>
    <item name="cornerFamilyTopRight">cut</item>
    <item name="cornerFamilyBottomRight">cut</item>
    <item name="cornerSize">8dp</item>
</style>

官方文档是here and all the android specs here


使用 jetpack compose 1.0.x 你可以使用 OutlinedButtonborder属性:

    OutlinedButton(
        onClick = { },
        border = BorderStroke(1.dp, Color.Blue),
        shape = RoundedCornerShape(8.dp) 
    ) {
        Text(text = "Save")
    }


OLD(支持图书馆)

有了新的 Support Library 28.0.0,设计库现在包含 Material Button

您可以将此按钮添加到我们的布局文件中:

<android.support.design.button.MaterialButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="XXXX"
    android:textSize="18sp"
    app:icon="@drawable/ic_android_white_24dp" />

您可以使用这些属性自定义按钮:

  • app:backgroundTint: 用于对按钮的背景应用色调。如果您想更改按钮的背景颜色,请使用此属性而不是背景。

  • app:strokeColor: 按钮描边要使用的颜色

  • app:strokeWidth: 按钮描边的宽度

还有

感谢@NomanRafique 的详细解答!但是,由于自定义背景,我们丢失了一些重要的东西:

  1. 按钮的高度大于默认值Widget.AppCompat.Button
  2. 填充
  3. Enable/Disable 状态

如果您想知道,这里是默认背景的样子:https://android.googlesource.com/platform/frameworks/support/+/a7487e7/v7/appcompat/res/drawable-v21/abc_btn_colored_material.xml

通过重复使用原始的插图、填充和颜色选择器,在一个简单的情况下,我们可以想出这样的东西(所有值都是默认值,来自 android support/material 图书馆) :

drawable-v21/bg_btn_outlined.xml

<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:insetLeft="@dimen/abc_button_inset_horizontal_material"
       android:insetTop="@dimen/abc_button_inset_vertical_material"
       android:insetRight="@dimen/abc_button_inset_horizontal_material"
       android:insetBottom="@dimen/abc_button_inset_vertical_material">
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
            android:color="?attr/colorControlHighlight">
        <item>
            <shape>
                <stroke
                    android:width="2dp"
                    android:color="@color/abc_btn_colored_borderless_text_material"/>
                <corners android:radius="@dimen/abc_control_corner_material"/>
                <padding
                    android:bottom="@dimen/abc_button_padding_vertical_material"
                    android:left="@dimen/abc_button_padding_horizontal_material"
                    android:right="@dimen/abc_button_padding_horizontal_material"
                    android:top="@dimen/abc_button_padding_vertical_material"/>
            </shape>
        </item>
        <item android:id="@android:id/mask">
            <shape>
                <stroke
                    android:width="2dp"
                    android:color="@color/abc_btn_colored_borderless_text_material"/>
                <solid android:color="@android:color/white"/>
                <corners android:radius="@dimen/abc_control_corner_material"/>
            </shape>
        </item>
    </ripple>
</inset>

styles.xml

<style name="Button.Outlined" parent="Widget.AppCompat.Button.Borderless.Colored">
    <item name="android:background">@drawable/bg_btn_outlined</item>
</style>

此时,我们应该有一个轮廓按钮响应触摸,尊重 enabled="false" 状态并且与默认高度相同 Widget.AppCompat.Button:

现在,您可以从这里开始自定义颜色,方法是提供您自己的 @color/abc_btn_colored_borderless_text_material 颜色选择器实现。

您可以通过将 Material 设计按钮的 style 属性设置为 @style/Widget.MaterialComponents.Button.OutlinedButton 并将 app:strokeColor 属性值设置为您喜欢的颜色来轻松完成此操作。

示例:

<com.google.android.material.button.MaterialButton
                android:text="Rounded outlined button"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:id="@+id/btnRound"
                style="@style/Widget.MaterialComponents.Button.OutlinedButton"
                app:strokeColor="@color/colorPrimaryDark"/>

参考文献:

在你的XML中使用这个,

            <com.google.android.material.button.MaterialButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Its a button"
                android:textColor="@android:color/white"
                android:textSize="@dimen/_12ssp"
                app:backgroundTint="@android:color/transparent"
                app:strokeColor="@android:color/white"
                app:strokeWidth="@dimen/_1sdp" />

其中

  1. app:backgroundTint 用于背景色
  2. app:strokeColor 是边框颜色
  3. app:strokeWidth 是边框宽度
<Button
    android:id="@+id/btn_add_discussion"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginHorizontal="15dp"
    android:padding="8dp"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="5dp"
    android:backgroundTint="#80ffffff"
    android:textColor="@color/colorPrimaryDark"
    style="@style/btn_start_new_discussion"
    android:text="Start new discussion" />

将以下代码放入 Styles.xml 文件中:

<style name="btn_start_new_discussion">
    <item name="android:layout_marginTop">15dp</item>
    <item name="strokeWidth">2dp</item>
    <item name="strokeColor">@color/colorPrimary</item>
    <item name="cornerRadius">10dp</item>
</style>

您也可以使用 Jetpack Compose 执行此操作。为此,只需创建一个带有 OutlinedButton 的可组合函数,并将 as 参数传递给您想要的边框:

@Composable
fun OutlineButton() {
    OutlinedButton(
        onClick = { //TODO - implement click here },
        border = BorderStroke(1.dp, Color.Blue), // <-- border property
        shape = RoundedCornerShape(corner = CornerSize(20.dp)),
        colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.Blue)
    ){
        Text(text = "CONFIRM")
    }
}