UI

Android 通过代码添加自定义Shape

2020-12-09  本文已影响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);
drawable.setColor( 0xFF000000); //十六进制黑色
drawable.setColor(Color.parseColor("#000000"));//GRB 颜色

通过代码自定义选择器

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

上一篇下一篇

猜你喜欢

热点阅读