简述
在Android 开发中,想必总会有人遇到奇葩的需求,比如颜色值要求通过后台来配置显示。这个时候,通过在drawable 文件夹新建xml 编写shape标签则无法控制颜色值了。于是引出了今天要讲的通过代码自定义shape 设置到我们想要的View中去。
老规矩先上图(思路说完最后再附上写的代码):
先看看我这边主界面简单XML布局
很简单,就是一个垂直线性布局,里面有两个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 查看其相关属性,这里给下粗略截图,有兴趣的小伙伴可以自行查阅
最后为了方便写,我稍微改成了工具类(小伙伴可以自行编写,这边只给出录制的两种)
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 代码的工具。
在针对性能要求非常高,但修改又不非常频繁的场景是可以使用使用。