用shape、selector自定义样式美化控件

        我们经常看到很漂亮的控件,就像下边两个:

                

        这样比较多样化的控件显示是很常见的,这是我现做的两个,且不论美观不美观,个人审美差异吧,我就喜欢绿色(不喜欢帽子抓狂),你可能喜欢银色或是别的。闲话打住,这样的效果是怎么实现的呢?

        有的人说“自定义控件”,不错,自定义控件能实现这样的效果,甚至更加美好,这个毋庸置疑!但是这里用自定义控件显然大材小用了——如果仅仅要求这些显示效果的话,根本用不到自定义控件这样的大工程——简简单单一个样式文件(shapeselector)就搞定了,下边我们来详细看看这两种文件。

(一)shape样式文件的使用

        我们先看shape样式文件,以下是shape文件的所有可用子节点

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- corners用于设置圆角半径 -->
    <corners ></corners>

    <!-- stroke用于设置边框宽度、颜色、边框虚线 -->
    <stroke ></stroke>

    <!-- solid用于设置内部区域填充色 -->
    <solid ></solid>

    <!-- gradient用于设置区域内渐变色 -->
    <gradient ></gradient>

    <!-- 设置大小 -->
    <size ></size>

    <!-- 设置内边距 -->
    <padding ></padding>
</shape>
        下边我们看看shape根节点下每个子节点的功能,以EditText为例:

<EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="测试编辑框"
        android:textSize="30sp"/>
        默认的EditText的显示效果为

        我们创建shape文件(我的名字是myshape),注意*文件名中不能有大写字母,然后在Edittext中添加

android:background="@drawable/myshape"

        (1)在myshape.xml中添加corners子节点:

<!-- corners用于设置圆角半径 -->
    <corners
        android:radius="10dp"
        android:topLeftRadius="3dp"
        android:topRightRadius="10dp"
        android:bottomLeftRadius="20dp"
        android:bottomRightRadius="30dp"
        />
        但是显示不出来效果——。因为没有填充色,我们再给它加上填充色:

        (2)solid子节点:

<!-- solid用于设置内部区域填充色 -->
    <solid android:color="#FFFFFF" />
        再看效果(我错了,弄了这么个颜色,太不清楚了,是米白色背景,看不清楚的换个角度斜着看一下,就当活动活动颈部,咱这一行呵呵了):


        说明:android:radius总的声明每个角圆角半径,如果4个角一致,则一句话搞定

                    android:topLeftRadius

                    android:topRightRadius

                    android:bottomLeftRadius

                    android:bottomRightRadius分别是左上、右上、左下、右下角半径,4者任意其一出现则该角半径以它为准。

        (3)继续添加stroke子节点:

<!-- stroke用于设置边框宽度、颜色、边框虚线间隔长度、虚线中每段实线的长度 -->
    <stroke
        android:width="1dp"
        android:color="#F860Af"
        android:dashGap="4dp"
        android:dashWidth="12dp" />
        运行再看效果(角半径只用10dp那个):

        

        (4)继续看padding子节点:

<!-- 设置内边距 -->
    <padding
        android:left="10dp"/>
        这里padding属性和控件的android:padding、android:paddingLeft、android:paddingTop、android:paddingRight、android:paddingBottom作用是一样的,这里只验证一下android:left就好,看效果:

        

        (5)继续添加size子节点:

<!-- 设置大小 -->
    <size
        android:width="300dp"
        android:height="100dp"/>
        注意:这里指定的是本样式的大小,而不是控件的大小,所以很少用到这个节点属性,因为显然通过控件本身属性控制大小更简单,而且能使样式文件更多的重用!

        

        (6)最后看比较麻烦的gradient子节点:

<!-- gradient用于设置区域内渐变色 -->
    <gradient
        android:startColor="@android:color/holo_red_light"
        android:centerColor="@android:color/white"
        android:endColor="@android:color/holo_green_light"
        android:type="radial"
        android:useLevel="false"
        android:centerX="0.5"
        android:centerY="0.5"
        android:gradientRadius="100dp"/>
        先看效果(此处没有使用size标签)

        

        属性:

        android:angle——Integer,渐变的角度。 0 代表从 left 到 right,90 代表bottom到 top。必须是45的倍数,默认为0,线性渐变有效;
        android:centerX——Float,渐变中心的相对X坐标,在0到1.0之间;
        android:centerY——Float,渐变中心的相对Y坐标,在0到1.0之间;
        android:startColor——Color,开始的颜色值;
        android:centerColor——Color,可选的颜色值,基于startColor和endColor之间;
        android:endColor——Color, 结束的颜色;
        android:gradientRadius——Float ,渐变的半径。只有在 android:type="radial"才使用;
        android:startColor——Color,开始的颜色值;
        android:type——Keyword,渐变的模式,下面值之一:
                "linear" 线形渐变。这也是默认的模式
                "radial" 辐射渐变。startColor即辐射中心的颜色
                "sweep" 扫描线渐变。
        android:useLevel——Boolean,如果在LevelListDrawable中使用,则为true。

        以上各节点都是按需添加的!shape样式文件只能做到这样的静态显示,不能变动,那么我们上边那个有交互效果的按钮是怎么回事呢?这就要用到selector样式文件了。

(二)selector样式文件的使用

        我们先看一个示例用的selector文件,我的叫myselect:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--<item >
        <shape>
            <corners android:radius="8dp"/>
            <solid android:color="@android:color/white"/>
        </shape>
    </item>-->

    <!-- 想在点击按钮是让按钮上的字也变色或者变字,怎么玩呢? -->
    <item android:state_enabled="false">
        <shape>
            <corners android:radius="8dp"/>
            <solid android:color="#666666"/>
            <stroke android:color="#A46D3F"
                android:width="1dp"/>
        </shape>
    </item>

    <item android:state_enabled="true"
        android:state_pressed="false">
        <shape>
            <corners android:radius="8dp"/>
            <solid android:color="@android:color/holo_green_light"/>
            <stroke android:color="#A46D3F"
                android:width="1dp"/>
        </shape>
    </item>

    <item android:state_enabled="true"
        android:state_pressed="true">
        <shape>
            <corners android:radius="8dp"/>
            <stroke android:color="#A46D3F"
                android:width="1dp"/>
            <gradient
                android:startColor="@android:color/holo_red_light"
                android:endColor="@android:color/holo_green_light"
                android:useLevel="false"
                android:type="radial"
                android:centerX="0.5"
                android:centerY="0.5"
                android:gradientRadius="200dp"/>
        </shape>
    </item>
</selector>
        大致浏览一下就会发现:selector样式中用到了shape样式。是的!selector样式文件其实就是一系列的shape样式的集合,相当于一个map,只是这个map的key不是字符串,而是根据各种state来进行匹配的。但是又有不同,因为这个匹配是有顺序的,相当于一串if-else语句,前边有匹配的就不再往后边继续找了,所以——Selector.xml中定义Item 顺序是有讲究的,条件限定越细致,则应该放到前面。比如这儿如果把3~8 行的注释 item 放开,那么下边的就永远无法触发了, 因为有 item 已经满足条件返回了。可以理解为代码中的 if 语句

        我们常用的state主要有android:state_enabled(是否可点击或可编辑)、android:state_pressed(是否按下)以及他们的组合。比如上边我们共使用了三种状态不可点击、可点击并且未按下、可点击已按下,对应的item中有对应状态显示的shape样式,这样在buttom中加上background="@drawable/xx"即可显示。

        我们创建selector文件,(以Android Studio为例)选中drawable目录,右键new > Drawable resource file > 输入文件名如myselector(不能有大写),直接确定即可,然后将上边代码贴进去。看button的声明:

<Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:background="@drawable/myselector"
        android:text="Second"
        android:textSize="30sp"/>
        这样,按钮就有相应的效果了,基本效果就出来了。


        但是仔细看看,和上边给出的效果不一样啊——按钮背景变了,字颜色没有变,看着也缺乏灵动的感觉,下边我就来让字在点击的时候也改变颜色:

        我们在shape中并没有发现关于textColor的相关设置,怎么办呢?但是Button中有textColor属性啊!我们可以照猫画虎再给textColor建一个selector文件来达到这个效果。 

        我们创建名为mytext的selector文件,发现在item子节点下有<color />标签,所以我们这样写:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" >
        <color android:color="#A46D3F"/>
    </item>
    <item android:state_enabled="true"
        android:state_pressed="false">
        <color android:color="#000000"/>
    </item>
    <item android:state_enabled="true"
        android:state_pressed="true" >
        <color android:color="@android:color/holo_green_light"/>
    </item>
</selector>

        在Button中加上

android:textColor="@drawable/mytext"

        运行一下看效果。哦,NO!报错了——

Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #3: <item> tag requires a 'android:color' attribute.

        什么情况?item标签需要android:color属性?不是用<color />子标签吗?查了好多帖子什么的都没有说明,只有用法,我悲哀地改成这样:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false"
        android:color="#A46D3F" />
    <item android:state_enabled="true"
        android:state_pressed="false"
        android:color="#000000">
    </item>
    <item android:state_enabled="true"
        android:state_pressed="true"
        android:color="@android:color/holo_green_light" />
</selector>

        好吧,先看结果吧——


        效果达到了,可是我并不开心,因为试了一下selector文件中item的自标签<color />竟然没有效果,还有,上边这种写法在写android:color=""属性时没有代码提示,是我们强加上的吗,可我们是根据logcat报错加上的啊!?

(3)未解决问题

        好了,本文要说的用样式文件美化控件的话题就说完了,但是在文中遇到这些问题还需要我们继续学习和提高:

        (1)shape标签属性android:shape可用rectangle矩形(默认)、oval椭圆、line水平直线、ring圆环,我们只验证了矩形。

        (2)shape样式中gradient子标签的属性android:userLevel干嘛用?

        (3)selector样式的item下有很多标签(color、set、transition、animation-list……),我们只用了shape这一种,其他的都有什么作用呢?

        (4)为什么我在给自加特效时item标签的andrid:color属性没有代码提示,这是我们强行加上的吗?有没有更好的写法吗?

        暂时还没有想到上边这些问题的答案,如果有缘人对这几个问题有所了解,麻烦留言指导,程序猿大人在此谢谢了!

参考文章:

@LonelyRoamer Android Drawable Resource学习(十二)、ShapeDrawable还是GradientDrawable?


        


  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值