Android 通过代码添加自定义Shape

简述

在Android 开发中,想必总会有人遇到奇葩的需求,比如颜色值要求通过后台来配置显示。这个时候,通过在drawable 文件夹新建xml 编写shape标签则无法控制颜色值了。于是引出了今天要讲的通过代码自定义shape 设置到我们想要的View中去。

老规矩先上图(思路说完最后再附上写的代码):


视频效果图.gif

先看看我这边主界面简单XML布局

activity_main.png

很简单,就是一个垂直线性布局,里面有两个TextView控件。

通过代码自定义Shape

接下来就来说说如何通过代码设置,最主要的就是通过GradientDrawable控制其相关属性,然后设置到我们的控件中去,来达到我们要的效果。
例如这里简单写一个黑色背景圆角矩形

       GradientDrawable drawable = new GradientDrawable();
        drawable.setCornerRadius(5);
        drawable.setColor( 0xFF000000);
        drawable.setStroke(1,0xFF000000);
        tv_view.setBackground(drawable);
  • setCornerRadius(float radius) : 圆角值
  • setColor(int argb) :argb 颜色值,即0x 开头的十六进制颜色 ,若是想用 RGB 颜色 则可以通过转换 Color.parseColor(String colorString),效果一样
drawable.setColor( 0xFF000000); //十六进制黑色
drawable.setColor(Color.parseColor("#000000"));//GRB 颜色
  • setStroke(int width, int color) width-线条宽度 color-argb颜色值

通过代码自定义选择器

设置两种不同GradientDrawable ,然后添加状态到我们设置StateListDrawable中去,即可实现在xml中的效果。
例如上面视频中的按下时一种图形,松开有显示一种图形

        StateListDrawable stateListDrawable = new StateListDrawable();
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDraw);
        stateListDrawable.addState(new int[]{}, normalDraw);
        tv_round.setBackground(stateListDrawable);

其中pressedDraw,normalDraw 是我们自定义的GradientDrawable
addState(int[] stateSet, Drawable drawable)是为控件添加状态
其属性状态和XML 中的一样多 ,通过android.R.attr.state_pressed 点击跳转到 attrs.xml 查看其相关属性,这里给下粗略截图,有兴趣的小伙伴可以自行查阅


android-29 attrs.xml.png

最后为了方便写,我稍微改成了工具类(小伙伴可以自行编写,这边只给出录制的两种)
ShapeSettingUtil

public class ShapeSettingUtil {
    /**
     * 设置背景选择器
     *
     * @param pressedDraw 按下时所定义的Drawable
     * @param normalDraw  正常显示的Drawable
     * @return
     */
    public static StateListDrawable getSelector(Drawable normalDraw, Drawable pressedDraw) {
        StateListDrawable stateListDrawable = new StateListDrawable();
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDraw);
        stateListDrawable.addState(new int[]{}, normalDraw);
        return stateListDrawable;
    }


    /**
     * 设置shape
     *
     * @param radius 半径长度
     * @param fillColor 填充颜色
     * @param storeWidth 线条宽度
     * @param strokeColor 线条颜色
     * @return
     */
    public  static GradientDrawable getDrawable(int radius, String fillColor, int storeWidth, String strokeColor) {
        GradientDrawable gradientDrawable = new GradientDrawable();
        gradientDrawable.setCornerRadius(radius);
        gradientDrawable.setColor(Color.parseColor(fillColor));
        gradientDrawable.setStroke(storeWidth,Color.parseColor(strokeColor) );
        return gradientDrawable;
    }
    
}

ScreenUtil

public class ScreenUtil {

    /**
     * dp 转 px
     */
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * px 转 dp
     */
    public static int px2dp(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

}

主界面代码 MainActivity

public class MainActivity extends AppCompatActivity {

    private TextView tv_view, tv_round;
    private String color1="#9873EA",color2="#7B4BE4";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_view=findViewById(R.id.tv_view);
        tv_round=findViewById(R.id.tv_round);
        tv_view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"带有圆角的控件 点击!",Toast.LENGTH_SHORT).show();
            }
        });

        tv_round.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"圆形选择器 点击!",Toast.LENGTH_SHORT).show();
            }
        });



        setUI();
    }

    private void setUI() {

        /***
         * 设置带有圆角5dp的浅紫色矩形
         * */
        GradientDrawable drawable= ShapeSettingUtil.getDrawable(
                ScreenUtil.dp2px(this,5),color1,
                ScreenUtil.dp2px(this,1),color1);

        tv_view.setBackground(drawable);



        /***
         * 圆形选择器
         * */
        GradientDrawable normal= ShapeSettingUtil.getDrawable(
                ScreenUtil.dp2px(this,125),color1,
                0,color1);
        GradientDrawable press= ShapeSettingUtil.getDrawable(
                ScreenUtil.dp2px(this,125),color2,
                0,color2);
        tv_round.setBackground(ShapeSettingUtil.getSelector(normal,press));

    }
}

至此,Android 通过代码添加自定义Shape编写完毕。希望能对小伙伴提供到思路。

最后的最后,小伙伴们用代码而非XML来设置代码,可能不是我上面说到的奇葩问题,而是基于UI优化,通过代码创建,而不是把整个XML加载到内存中去。这样的优点是UI渲染更快性能更好,但是缺点是减少了可阅读性,对于后续迭代开发不友好,所以这边贴出了大佬们开源出来的库X2C ,是将XML 转换为 Java 代码的工具。
在针对性能要求非常高,但修改又不非常频繁的场景是可以使用使用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,322评论 5 465
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,288评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,227评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,015评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,936评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,534评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,995评论 3 389
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,616评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,907评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,923评论 2 315
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,741评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,525评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,016评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,141评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,453评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,054评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,249评论 2 339

推荐阅读更多精彩内容