Android 通過代碼添加自定義Shape

簡述

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

老規(guī)矩先上圖(思路說完最后再附上寫的代碼):


視頻效果圖.gif

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

activity_main.png

很簡單,就是一個垂直線性布局,里面有兩個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)屬性,這里給下粗略截圖,有興趣的小伙伴可以自行查閱


android-29 attrs.xml.png

最后為了方便寫,我稍微改成了工具類(小伙伴可以自行編寫,這邊只給出錄制的兩種)
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 代碼的工具。
在針對性能要求非常高,但修改又不非常頻繁的場景是可以使用使用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容