美文网首页UI
Android 通过代码添加自定义Shape

Android 通过代码添加自定义Shape

作者: 隐姓埋名的猫大叔 | 来源:发表于2020-12-09 23:28 被阅读0次

    简述

    在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 代码的工具。
    在针对性能要求非常高,但修改又不非常频繁的场景是可以使用使用。

    相关文章

      网友评论

        本文标题:Android 通过代码添加自定义Shape

        本文链接:https://www.haomeiwen.com/subject/ylahgktx.html