Android之selector自定义背景实现2

来源:互联网 发布:正则匹配ip端口号 编辑:程序博客网 时间:2024/05/27 06:54

Android之selector自定义背景实现2

文章链接:Android之selector自定义背景实现2

文章链接:Android之selector自定义背景实现1

知识点

  1. selector和shap节点属性详解;
  2. selector背景/点击反馈效果的XML文件实现;
  3. selector背景/点击反馈效果的Java代码实现;
  4. 新名词记录{StateListDrawable:和XML设置selector相同效果的代理类;GradientDrawable:设置按钮/控件背景的圆角/边框等的实现类;}

书接上一回 上一回


第二种:Java代码实现

利用第一种实现方式,我们看到要写3个的XML文件。但是,我懒,不想写这么多的文件,应该怎么办呢???

很多人就会想到,我利用Java代码来替代啊。

这个是木有问题的,因为在今天的工作中,我自己也是懒了,所以我要“另辟蹊径”,决定用Java代码来实现。就可以不用新建n多个资源文件了,有时候看到这么多文件都烦都怕。

首先我们应该知道Google的SDK是用哪几个类来替代XML实现的效果的。回想一下,XML代码是被设置到background属性去的,在Java代码中有setBackground()方法,形参是一个Drawable,那么我们要找到这个类,估计和Drawable类多少有些关联的。

查一下API,果然找到了一个类:StateListDrawable类的说明是:让你在一个drawable上面设置一系列图形,用以根据资源id来置换不同图形的一个类。这个类里面有增加状态、动态加载一个XML文件、获取状态的总数、根据下标得到状态的drawable、应用theme等公共方法。

好啦,找到了,我们就可以开始用代码来替代第一种方法了。这里我使用纯颜色背景来响应不同的点击反馈效果。下面的方法是根据传入的颜色的ID来获取到一个drawable,然后返回StateListDrawable实例。

/**     * @param context      上下文     * @param normalResId  默认的颜色     * @param pressedResId 按下不放的颜色     * @param strokeWidth  控件边框的颜色     * @param roundRadius  控件圆角的大小     * @return drawable对象,设置了selector的效果     */    public StateListDrawable getPressedSelector(Context context, int normalResId, int pressedResId,                                                int strokeWidth, int roundRadius) {        //这里我使用getDrawable()获取一个drawable        Drawable normal = normalResId == -1 ? null : context.getResources().getDrawable(normalResId);        Drawable pressed = pressedResId == -1 ? null : context.getResources().getDrawable(pressedResId);        StateListDrawable stateListDrawable = new StateListDrawable();        //以下的顺序很重要,normal必须在最后面才起作用        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressed);        stateListDrawable.addState(new int[]{}, normal);        return stateListDrawable;    }

说明:这里需要注意:我传入一个颜色的id,使用getDrawable()获取一个drawable在这里是可行的。然后我们调用stateListDrawable.addState()方法来加入需要的状态对应的图片。

public void addState(int[] stateSet, Drawable drawable){}

看到此方法,参数1是对应的状态的int数组,可以一次传入多个状态,参数2是参数1所有的状态时要展示的drawable。关于每个状态,在第一种方法里面已经有说明了,他们在系统android.R.attr文件下面都有定义。这里需要注意一点:加的时候,默认的状态要在最后面,否则不起作用。

还有一点更加

然后我们就得到stateListDrawable实例,然后调用setBackground()方法将drawable设置进去,运行就可以看到效果了。

这里我就不给出效果图了,大家可以自己去运行看下。


你以为这就完了吗?No No No

还有一个效果木有实现,那就是加入圆角、边框等的效果。

我们继续来找用来替代shap的Java类,然后我们看到这个类:GradientDrawableGradientDrawable类说明:为按钮和背景等提供颜色渐变的drawable。它也是一个drawable的一个直接子类。Google也说明了,这个类的功能也是可以再XML里面利用shap来实现的。类里面的方法,和XML里面每个属性功能都是有对应的,有需要深入理解的可以去看源码。

找到了,我们就开始使用起来了。因为它是drawable的子类,那么就可以像stateListDrawable一样来操作,只是方法不同罢了。使用无非就是设置它的填充颜色,圆角的角度,边框颜色和大小等等。我们直接看代码吧。

/**     * @param context      上下文     * @param normalResId  默认的颜色     * @param pressedResId 按下不放的颜色     * @param strokeWidth  控件边框的颜色     * @param roundRadius  控件圆角的大小     * @return drawable对象,设置了selector的效果     */    public StateListDrawable getPressedSelector(Context context, int normalResId, int pressedResId,                                                int strokeWidth, int roundRadius) {        int normalFillColor = context.getResources().getColor(normalResId);        GradientDrawable normalGd = new GradientDrawable();        normalGd.setColor(normalFillColor);        normalGd.setCornerRadius(roundRadius);        normalGd.setStroke(strokeWidth, normalFillColor);        int pressedFillColor = context.getResources().getColor(pressedResId);        GradientDrawable pressedGd = new GradientDrawable();        pressedGd.setColor(pressedFillColor);        pressedGd.setCornerRadius(roundRadius);        pressedGd.setStroke(strokeWidth, pressedFillColor);        StateListDrawable stateListDrawable = new StateListDrawable();        //以下的顺序很重要,normal必须在最后面才起作用        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedGd);        stateListDrawable.addState(new int[]{}, normalGd);        return stateListDrawable;    }

因为要复用,我写了一个方法,把需要的几个参数统一由外面传进来。注意:我这里传入的还是color的资源id。如果是传入drawable的资源,必须要使用getDrawable()方法。

调用方法:

                btn_fMvLastMonth.setBackground(mManageOverviewImpl.getPressedSelector(this, R.color.withe, R.color.black99, 1, 8));

第二种实现方法完。


总结

其实两种方法实现起来也不难,来做一下对比:

方法一:

在XML里面能够看到效果,但是需要的文件很多,管理就难了。想像一下,如果一个APP里面有十多个不同的样式背景或者点击反馈效果,那么文件可能就多了几十个了,要改变的时候得要一个一个去找,修改和管理起来比较困难。

方法二:

要运行时才能看到效果,调试比较费劲。但是代码简洁了不少,像我提取成一个方法,颜色等样式由外面提供,复用性比较高,XML文件数量几乎为0.

OK,以上就是所有内容。

如有任何疑问,请及时与我联系。谢谢!

0 0
原创粉丝点击