在原生 Android 开发中,许多控件默认都是方方正正的,而我个人也比较喜欢这种设计,因为 Google 的 Material Design 就是从纸片中提炼出来的。

默认的 Button 样式

但是近年来 Material Design 的发展,似乎更加往大圆角的方向靠拢了。

Material Design 的大圆角

Android 的原生控件中是不支持直接设置类似 Radius 的属性,所以又得另辟蹊径了。

Shape Attr

可以通过一个 XML 资源文件来定义,属性参考如下:

shape (形状)

最外层标签,用于定义控件的形状。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:dither="false"
    android:innerRadius="16dp"
    android:innerRadiusRatio="8"
    android:thickness="8dp"
    android:thicknessRatio="8"
    android:tint="@color/colorAccent"
    android:tintMode="add"
    android:useLevel="false">
    ...
</shape>

属性比较多,听我一一道来。

android:shape 是控件的形状,默认为矩形 rectangle,其他可选值还有椭圆 oval、线 line 和 环 ring

android:dither 用于指定在位图的像素配置与屏幕不同时(例如:ARGB_8888 位图和 RGB_565 屏幕)是否启用位图的抖动,默认值 true,当值为 false 时则停用抖动。

android:innerRadius 是内环半径;android:innerRadius 是内环厚度比,即环的宽度比表示内环半径,默认为 3,可被 android:innerRadius 的值覆盖。android:thickness 是环的厚度,android:thicknessRatio 是环的厚度比,即环的宽度比表示环的厚度,默认为 9,可被 android:thicknessRatio 的值覆盖。这四个属性只有当形状为 ring 的时候才有效。

android:tint 用于着色,这个我们在其他控件也有用到。

android:tintMode 是着色类型,有 addmultiplyscreensrc_atopsrc_insrc_over 六个可选值,这里不细说。

android:useLevel 这个属性比较特殊,是个布尔类型,默认值为 false,一般情况下不需要修改它,为 true 时可在 LevelListDrawable 使用。

corners (圆角)

Creates rounded corners for the shape. Applies only when the shape is a rectangle.

用于定义控件的圆角属性,仅可用于矩形 Shape。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners
        android:radius="8dp"
        android:topLeftRadius="8dp"
        android:topRightRadius="8dp"
        android:bottomLeftRadius="8dp"
        android:bottomRightRadius="8dp" />
</shape>

这个比较简单,不过多解释。

solid (填充)

A solid color to fill the shape.

用于定义控件的填充颜色。

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

有且仅有颜色这一属性。

gradient (渐变)

Specifies a gradient color for the shape.

用于定义控件的渐变色及渐变样式等。

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:type="radial"
        android:angle="90"
        android:startColor="@color/colorPrimaryDark"
        android:centerColor="@color/colorAccent"
        android:endColor="@color/colorPrimary"
        android:centerX="50%"
        android:centerY="50%"
        android:gradientRadius="8dp"
        android:useLevel="false" />
</shape>

这个相对比较复杂,分组来说。

android:type 是渐变的样式,有三个可选值,线性渐变 linear 是默认值,另外还有放射渐变 radial 和扫描渐变 sweep

android:angle 是渐变角度,须为 45 的整倍数,其中 0 为从左到右,90 为从上到下。

android:startColorandroid:centerColorandroid:endColor 分别是渐变的起始点、中间点和结束点颜色,但你可以按需设置,因为其支持两色渐变和三色渐变,即当选择两色渐变时,android:centerColor 可以不用填写。

android:centerXandroid:centerY 是渐变中心点 X 和 Y 的相对位置,取值范围为 0~1。

android:gradientRadius 是渐变的半径,只有当渐变类型为 radial 时才有效。

android:useLevel 这个属性比较特殊,是个布尔类型,默认值为 false,一般情况下不需要修改它,而使用 LevelListDrawable 时就要设置其为 true

stroke (描边)

A stroke line for the shape.

用于定义控件的描边属性。

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

android:width 是描边的宽度。android:color 是描边的颜色。

一般情况下描边为实线,如果想设置虚线,则需要另外两个属性,android:dashWidth 是指虚线段的长度,android:dashGap 是指虚线段间隔的长度。

padding (边距)

Padding to apply to the containing View element (this pads the position of the View content, not the shape).

用于定义控件的边距属性。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <padding
        android:bottom="4dp"
        android:left="4dp"
        android:right="4dp"
        android:top="4dp" />
</shape>

这个也比较简单,不过多解释。

size (大小)

The size of the shape.

用于定义控件的尺寸属性。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size
        android:width="128dp"
        android:height="128dp" />
</shape>

同样比较简单,不过多解释。

Usage

用法也不复杂,在「drawable」文件夹中新建一个 XML 资源文件,将上面的属性按照需要进行组合即可。

比如,我建一个「button_shape.xml」,用来定义 Button 控件的形状。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/colorAccent" />
    <corners
        android:topLeftRadius="5dp"
        android:topRightRadius="10dp"
        android:bottomLeftRadius="15dp"
        android:bottomRightRadius="0dp" />
</shape>

代码并不难理解,形状为矩形,颜色设定为主题色,为四个圆角半径设定为 不同的值。

然后使用其在控件属性中设置为 android:background

<Button
    android:layout_width="128dp"
    android:layout_height="wrap_content"
    android:background="@drawable/button_shape"
    android:text="Button" />

效果如下:

不一样的圆角

其实 Shape 的可配置属性并没有很复杂,所以学起来也不会很难上手,但是却足够我们使用。