簡述
在Android 開發(fā)中,想必總會有人遇到奇葩的需求,比如顏色值要求通過后臺來配置顯示。這個時候,通過在drawable 文件夾新建xml 編寫shape標(biāo)簽則無法控制顏色值了。于是引出了今天要講的通過代碼自定義shape 設(shè)置到我們想要的View中去。
老規(guī)矩先上圖(思路說完最后再附上寫的代碼):

先看看我這邊主界面簡單XML布局

很簡單,就是一個垂直線性布局,里面有兩個TextView控件。
通過代碼自定義Shape
接下來就來說說如何通過代碼設(shè)置,最主要的就是通過GradientDrawable控制其相關(guān)屬性,然后設(shè)置到我們的控件中去,來達(dá)到我們要的效果。
例如這里簡單寫一個黑色背景圓角矩形
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 開頭的十六進(jìn)制顏色 ,若是想用 RGB 顏色 則可以通過轉(zhuǎn)換 Color.parseColor(String colorString),效果一樣
drawable.setColor( 0xFF000000); //十六進(jìn)制黑色
drawable.setColor(Color.parseColor("#000000"));//GRB 顏色
- setStroke(int width, int color) width-線條寬度 color-argb顏色值
通過代碼自定義選擇器
設(shè)置兩種不同GradientDrawable ,然后添加狀態(tài)到我們設(shè)置StateListDrawable中去,即可實現(xiàn)在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)是為控件添加狀態(tài)
其屬性狀態(tài)和XML 中的一樣多 ,通過android.R.attr.state_pressed 點擊跳轉(zhuǎn)到 attrs.xml 查看其相關(guān)屬性,這里給下粗略截圖,有興趣的小伙伴可以自行查閱

最后為了方便寫,我稍微改成了工具類(小伙伴可以自行編寫,這邊只給出錄制的兩種)
ShapeSettingUtil
public class ShapeSettingUtil {
/**
* 設(shè)置背景選擇器
*
* @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;
}
/**
* 設(shè)置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 轉(zhuǎn) px
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* px 轉(zhuǎn) 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() {
/***
* 設(shè)置帶有圓角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來設(shè)置代碼,可能不是我上面說到的奇葩問題,而是基于UI優(yōu)化,通過代碼創(chuàng)建,而不是把整個XML加載到內(nèi)存中去。這樣的優(yōu)點是UI渲染更快性能更好,但是缺點是減少了可閱讀性,對于后續(xù)迭代開發(fā)不友好,所以這邊貼出了大佬們開源出來的庫X2C ,是將XML 轉(zhuǎn)換為 Java 代碼的工具。
在針對性能要求非常高,但修改又不非常頻繁的場景是可以使用使用。