自定義View onMeasure()和onLayout()與onDrow()

onMeasure→onLayout(ViewGroup必須重寫)→onDraw

onMeasure()中的一些API
感謝大苞米
感謝易術軍

   /*
    一般情況重寫onMeasure()方法作用是為了自定義View尺寸的規(guī)則险领,如果你的自定義View的尺寸是根據(jù)父控件行為一致碉考,就不需要重寫onMeasure()方法
    如果不重寫onMeasure方法,那么自定義view的尺寸默認就和父控件一樣大小蕴纳,當然也可以在布局文件里面寫死寬高屎飘,而重寫該方法可以根據(jù)自己的需求設置自定義view大小
    onMeasure (int widthMeasureSpec, int heightMeasureSpec)是view自己的方法
    onMeasure 方法簡單的理解就是是用于測量視圖的大小妥曲,主要是用來測量自己和內容的來確定寬度和高度
    onMeasure有兩個參數(shù) ( int widthMeasureSpec, int heightMeasureSpec)贾费,該參數(shù)表示控件可獲得的空間以及關于這個空間描述的元數(shù)據(jù).
    widthMeasureSpec和heightMeasureSpec這兩個值通常情況下都是由父視圖經(jīng)過計算后傳遞給子視圖的,說明父視圖會在一定程度上決定子視圖的大小檐盟。
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int exactly = MeasureSpec.EXACTLY; //EXACTLY: 精確模式  當寬高是wrap_connect時使用
        int atMost = MeasureSpec.AT_MOST;   //AT_MOST:最大模式  當寬高是match_parent或者是準確的xxdp的時候使用褂萧,讓控件獲取到準確的大小

        int mode = MeasureSpec.getMode(widthMeasureSpec); //取得測量模式 是 MeasureSpec.EXACTLY?  還是MeasureSpec.AT_MOST?
        int size = MeasureSpec.getSize(widthMeasureSpec); //取得測量數(shù)值

        int i = MeasureSpec.makeMeasureSpec(widthMeasureSpec, widthMeasureSpec);  //以上2個方法的 結合版 結果=size + mode(注意:二進制的加法,不是十進制的加法葵萎!)
        getChildMeasureSpec(i, 10, 10);//在measureChildren中最難的部分:找出傳遞給child的MeasureSpec导犹。目的是結合父view的MeasureSpec與子view的LayoutParams信息去找到最好的結果

        int defaultSize = getDefaultSize(widthMeasureSpec, widthMeasureSpec);//第一個參數(shù)size為提供的默認大小  第二個參數(shù)為測量的大小

        int suggestedMinimumWidth = getSuggestedMinimumWidth(); //最小寬度
        int suggestedMinimumHeight = getSuggestedMinimumHeight(); //最小高度

        measureChildren(widthMeasureSpec, heightMeasureSpec); //跳過GONE類型View) 參數(shù)1:widthMeasureSpec 父視圖的寬詳細測量值 參數(shù)2:heightMeasureSpec 父視圖的高詳細測量值

        measureChild(getChildAt(0), widthMeasureSpec, heightMeasureSpec);//測量單個視圖,將寬高和padding加在一起后交給getChildMeasureSpec去獲得最終的測量值   參數(shù)1:child 需要測量的子視圖   參數(shù)2:parentWidthMeasureSpec 父視圖的寬詳細測量值  參數(shù)3:parentHeightMeasureSpec 父視圖的高詳細測量值

        Resources resources = this.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        float density = dm.density;
        int width = dm.widthPixels;     //得到屏幕的寬
        int height = dm.heightPixels;   //得到屏幕的高

        getLeft(); //子View左邊界到父view左邊界的距離
        getTop(); //子View上邊界到父view上邊界的距離
        getRight(); //?子View右邊界到父view右邊界的距離
        getBottom(); //?子View下邊界到父view下邊界的距離


        setMeasuredDimension(500, 500); //這個方法必須由onMeasure(int, int)來調用羡忘,來存儲測量的寬谎痢,高值。  這個方法可以改變控件的大小

    }

onLayout()方法中的一些API
感謝小試牛刀

 /**
     * onLayout也有個對應的layout方法卷雕。先看下layout和onLayout的區(qū)別
     * layout方法是View中的方法节猿,用來實現(xiàn)View的擺放,layout傳入是個參數(shù)left爽蝴、top沐批、right、bottom是相對于父控件而言的   例如傳入(20蝎亚,20九孩,50,70)发框,該View的左上角位置對應的坐標是(20,20),寬為30躺彬,高為50;
     * onLayout方法是ViewGroup中的方法梅惯,用來實現(xiàn)子View的擺放.  onLayout傳入的參數(shù)l宪拥、t、r铣减、f是根據(jù)父控件的實際可用空間來的(去除margin和padding的控件)
     *
     * @param l:View左邊界距離父容器(父控件)的左邊界的距離
     * @param t:View上邊界距離父容器(父控件)上邊界的距離
     * @param r:View右邊界距離父容器(父控件)左邊界的距離
     * @param b:View下邊界距離父容器(父控件)上邊界的距離
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        getMeasuredWidth();//是在measure()結束后得到的值 getMeasuredWidth是通過setMeasuredDimension()方法來設置的
        getWidth();//是在layout()結束后得到的值 getWidth()是通過視圖右邊的坐標減去左邊的坐標計算出來的
    }

一些其他API

 
    View提供的獲取坐標方法
    getTop:獲取到的是View自身的頂邊到其父布局頂邊的距離
    getLeft:獲取到的是View自身的左邊到其父布局左邊的距離
    getRight:獲取到的是View自身的右邊到其父布局左邊的距離
    getBottom:獲取到的是View自身的底邊到其父布局頂邊的距離
    

    
    MotionEvent提供的方法
    getX:獲取點擊事件距離控件左邊的距離她君,即視圖坐標
    getY:獲取點擊事件距離控件頂邊的距離,即視圖坐標
    getRawX:獲取點擊事件距離整個屏幕左邊的距離葫哗,即絕對坐標
    getRawY:獲取點擊事件距離整個屏幕頂邊的距離缔刹,即絕對坐標
    

獲取屏幕寬高

方法一:更多適用于在activity中使用
Display.getHeight(),Display.getWidth() 方法過時


WindowManager wm = (WindowManager) this
                .getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
int height = wm.getDefaultDisplay().getHeight();

方法二

WindowManager wm1 = this.getWindowManager();
int width1 = wm1.getDefaultDisplay().getWidth();
int height1 = wm1.getDefaultDisplay().getHeight();

方法三

WindowManager manager = this.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int width = outMetrics.widthPixels;
int height = outMetrics.heightPixels;

方法四:自定義控件中使用

Resources resources = this.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
float density = dm.density;
int width = dm.widthPixels;
int height = dm.heightPixels;

不為人知的解決事件沖突

.getParent().requestDisallowInterceptTouchEvent(true);//剝奪父view 對touch 事件的處理權

.performClick(); //返回一個布爾類型的值 從而讓點擊和滑動獲得良好的體驗 

CSDN鏈接

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /*
        Paint 翻譯 : 顏料
         */
        Paint paint = new Paint();

        paint.setFlags(1); //設置一些標志劣针,比如抗鋸齒校镐,下劃線等等。
        paint.setAntiAlias(true);//設置抗鋸齒捺典,如果不設置鸟廓,加載位圖的時候可能會出現(xiàn)鋸齒狀的邊界,如果設置,邊界就會變的稍微有點模糊引谜,鋸齒就看不到了
        paint.setDither(true);//設置是否抖動牍陌,如果不設置感覺就會有一些僵硬的線條,如果設置圖像就會看的更柔和一些
        paint.setLinearText(true);//這個是文本緩存员咽,設置線性文本呐赡,如果設置為true就不需要緩存
        paint.setSubpixelText(true);//設置亞像素,是對文本的一種優(yōu)化設置骏融,可以讓文字看起來更加清晰明顯,可以參考一下PC端的控制面板-外觀和個性化-調整ClearType文本
        paint.setUnderlineText(true);//設置文本的下劃線
        paint.setStrikeThruText(true);//設置文本的刪除線
        paint.setFakeBoldText(true);//設置文本粗體
        paint.setFilterBitmap(true);//對位圖進行濾波處理萌狂,如果該項設置為true档玻,則圖像在動畫進行中會濾掉對Bitmap圖像的優(yōu)化操作,加快顯示
        paint.setColor(Color.parseColor("#f00"));//設置畫筆顏色
        paint.setAlpha(255);//設置畫筆的透明度[0-255]茫藏,0是完全透明误趴,255是完全不透明
        paint.setARGB(0, 10, 10, 10);//設置畫筆顏色的argb形式 順序是 alpha,red务傲,green凉当,blue 每個范圍都是[0-255]
        paint.setStrokeWidth(0.1f);//畫筆樣式為空心時,設置空心畫筆的寬度
        paint.setStrokeMiter(0.1f);//當style為 Stroke 或 StrokeAndFill 時設置連接處的傾斜度售葡,這個值必須大于0
        paint.setElegantTextHeight(true);//設置優(yōu)雅的文字高度
        paint.setTextSize(1);//設置字體大小
        paint.setTextScaleX(1);//設置字體的水平方向的縮放因子看杭,默認值為1,大于1時會沿X軸水平放大挟伙,小于1時會沿X軸水平縮小
        paint.setTextSkewX(1);//設置文本在水平方向上的傾斜楼雹,默認值為0,推薦的值為-0.25
        paint.setLetterSpacing(0);//設置行的間距尖阔,默認值是0贮缅,負值行間距會收縮
        paint.setFontFeatureSettings("");//設置字體樣式,可以設置CSS樣式
        paint.reset();//重置Paint
        paint.setStyle(Paint.Style.FILL);//決定筆觸的樣式

        //下面這些我沒測試過
        /*
        setShader   (Shader shader) 設置著色器介却,用來給圖像著色的谴供,繪制出各種漸變效果,有BitmapShader齿坷,ComposeShader桂肌,LinearGradient,RadialGradient胃夏,SweepGradient幾種
        setColorFilter  (ColorFilter filter)    設置畫筆顏色過濾器轴或,有ColorMatrixColorFilter,LightingColorFilter仰禀,PorterDuffColorFilter幾種照雁,這個以后再單獨分析
        setXfermode (Xfermode xfermode) 設置圖形重疊時的顯示方式
        setPathEffect   (PathEffect effect) 設置繪制路徑的效果,有ComposePathEffect,CornerPathEffect饺蚊,DashPathEffect萍诱,DiscretePathEffect,PathDashPathEffect污呼,SumPathEffect幾種裕坊,以后在單獨分析
        setMaskFilter   (MaskFilter maskfilter) 對圖像進行一定的處理,實現(xiàn)濾鏡的效果燕酷,如濾化籍凝,立體等,有BlurMaskFilter,EmbossMaskFilter幾種
        setTypeface (Typeface typeface) 設置字體樣式苗缩,可以是Typeface設置的樣式饵蒂,也可以通過Typeface的createFromAsset(AssetManager mgr, String path)方法加載樣式
        setShadowLayer  (float radius, float dx, float dy, int shadowColor) 設置陰影效果,radius為陰影角度酱讶,dx和dy為陰影在x軸和y軸上的距離退盯,color為陰影的顏色。注:在用該方法之前需要調用setLayerType( LAYER_TYPE_SOFTWARE , null);關閉硬件加速
        setTextLocale   (Locale locale) 設置地理位置泻肯,比如顯示中文渊迁,日文,韓文等灶挟,默認的顯示Locale.getDefault()即可
      
         */


        /*
        measureText (char[] text, int index, int count) 測量字體的長度
                    (String text, int start, int end)
                    (String text)
                    (CharSequence text, int start, int end)

        breakText   (char[] text, int index, int count,float maxWidth, float[] measuredWidth)   剪切顯示琉朽,就是大于maxWidth的時候只截取指定長度的顯示
                    (CharSequence text, int start, int end,boolean measureForwards, float maxWidth, float[] measuredWidth)
                    (String text, boolean measureForwards,float maxWidth, float[] measuredWidth)

        getTextWidths   (char[] text, int index, int count,float[] widths)  提取指定范圍內的字符串,保存到widths中
                        (CharSequence text, int start, int end, float[] widths)
                        (String text, int start, int end, float[] widths)
                        (String text, float[] widths)

        getTextPath (char[] text, int index, int count, float x, float y, Path path)    獲取文本繪制的路徑稚铣,提取到Path中
                    (String text, int start, int end, float x, float y, Path path)

        getTextBounds   (String text, int start, int end, Rect bounds)  得到文本的邊界漓骚,上下左右,提取到bounds中榛泛,可以通過這計算文本的寬和高
                        (char[] text, int index, int count, Rect bounds)

         */

    }

Canvas 類的 API

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /*
        平移
        參數(shù)1: 向X軸方向移動100距離
        參數(shù)2: 向Y軸方向移動50距離
         */
        canvas.translate(100, 50);

         /*
        在X軸方向放大為原來2倍蝌蹂,Y軸方向方大為原來的4倍
        參數(shù)1: X軸的放大倍數(shù)
        參數(shù)2: Y軸的放大倍數(shù)
         */
        canvas.scale(2, 4);

        /*
        在X軸方向放大為原來2倍,Y軸方向方大為原來的4倍
        參數(shù)1: X軸的放大倍數(shù)
        參數(shù)2: Y軸的放大倍數(shù)
        參數(shù)3: 原點X坐標
        參數(shù)4: 原點Y坐標
         */
        canvas.scale(2, 4, 100, 100);

        /*
        旋轉,原點為中心曹锨,旋轉30度(順時針方向為正方向 )
        參數(shù)1: 旋轉角度
         */
        canvas.rotate(30);

        /*
        為中心孤个,旋轉30度,順時針方向為正方向
        參數(shù)1: 旋轉角度
         */
        canvas.rotate(30, 100, 100);


        /*
        畫文字
        參數(shù)1:文本
        參數(shù)2:文本的x軸的開始位置
        參數(shù)3:文本Y軸的結束位置
        參數(shù)4:畫筆對象
         */
        canvas.drawText("文字", 50, 50, new Paint());

         /*
        參數(shù)1:文本
        參數(shù)2:要從第幾個字開始繪制
        參數(shù)3:要繪制到第幾個文字
        參數(shù)4:文本的x軸的開始位置
        參數(shù)5:文本Y軸的結束位置
        參數(shù)6:畫筆對象
         */
        canvas.drawText("文字", 2, 5, 50, 50, new Paint());


         /*
        參數(shù)1:文本
        參數(shù)2:路徑
        參數(shù)3:距離路徑開始位置的偏移量
        參數(shù)4:距離路徑上下的偏移量(可以為負數(shù))
        參數(shù)5:畫筆對象
         */
        canvas.drawTextOnPath("文字", new Path(), 0, -50, new Paint());


         /*
        畫圓
        參數(shù)1:圓心X
        參數(shù)2:圓心Y
        參數(shù)3:半徑R
        參數(shù)4:畫筆對象
         */
        canvas.drawCircle(200, 200, 100, new Paint());


        /*
        畫線
        參數(shù)1:startX 起始
        參數(shù)2:startY
        參數(shù)3:stopX
        參數(shù)4:stopY
        參數(shù)5:畫筆對象
         */
        canvas.drawLine(100, 100, 300, 300, new Paint());


         /*
        同時繪制多條線沛简。
        參數(shù)1:float數(shù)組:每四個一組為一條線齐鲤。最后不足四個,就忽略那些值椒楣。
        參數(shù)2:畫筆對象
         */
        canvas.drawLines(new float[]{100, 100, 200, 200, 200, 100, 300, 100}, new Paint());


         /*
        畫一個長方形
        參數(shù)1:float left
        參數(shù)2:float top
        參數(shù)3:float right
        參數(shù)4:float bottom
         */
        RectF oval = new RectF(150, 200, 500, 400);

        /*
        畫橢圓
        參數(shù)1:RectF對象
        參數(shù)2:畫筆對象
         */
        canvas.drawOval(oval, new Paint());


        /*
        畫弧度
        參數(shù)1:RectF對象
        參數(shù)2:開始的角度给郊。(水平向右為0度順時針反向為正方向)
        參數(shù)3:掃過的角度
        參數(shù)4:是否和中心連線 參數(shù)5:畫筆對象
         */
        canvas.drawArc(oval, 20, 180, false, new Paint());


         /*
        畫矩形
        參數(shù)1:float left
        參數(shù)2:float top
        參數(shù)3:float right
        參數(shù)4:float bottom
         */
        canvas.drawRect(100, 100, 200, 200, new Paint());

         /*
        畫圓角矩形
        參數(shù)1:RectF對象
        參數(shù)2:x半徑 參數(shù)3:y半徑
         */
        canvas.drawRoundRect(new RectF(), 20, 5, new Paint());

         /*
        路徑對象    path.moveTo(80, 200)此點為多邊形的起點
         */
        Path path = new Path();



        /*
        可以添加多個點。構成多邊形
         */
        path.lineTo(120, 250);


         /*
        設置貝塞爾曲線的控制點坐標和終點坐標
         */
        new Path().quadTo(300, 100, 400, 400);



        /*
        使終點和起點鏈接捧灰,構成封閉圖形
         */
        new Path().close();



        /*
        畫多邊形
        參數(shù)1:路徑
        參數(shù)2:畫筆對象
         */
        canvas.drawPath(path, new Paint());

         /*
        畫一個點
        參數(shù)1:X坐標
        參數(shù)2:Y坐標
         */
        canvas.drawPoint(60, 390, new Paint());


        /*
        畫多個點
        參數(shù)1:多個點淆九,每兩個值為一個點。最后個數(shù)不夠兩個的值將被忽略
        參數(shù)2:畫筆對象
         */
        canvas.drawPoints(new float[]{60, 400, 65, 400, 70, 400}, new Paint());

         /*
        創(chuàng)建一個圖片
        參數(shù)1:get到res目錄
        參數(shù)2:圖片路徑
         */
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background);


        /*
        畫圖片
        參數(shù)1:bitmap對象
        參數(shù)2:圖像左邊坐標點
        參數(shù)3:圖像上邊坐標點
         */
        canvas.drawBitmap(bitmap, 200, 300, new Paint());


      

}
invalidate(); // 在UI主線程中,用invalidate()本質是調用View的onDraw()繪制

postInvalidate(); // 主線程之外炭庙,用postInvalidate()饲窿。

postInvalidateDelayed(1000); //間隔 定時 刷新(重繪)

postInvalidateOnAnimation(); 


/*draw()
在這里面 有2個 比較容易 混淆的
invalidate() 請求我們的安卓系統(tǒng) 如果視圖的 大小沒有發(fā)生變化 就不會調用 layout()這個放置過程  (這個方法是 重繪)*/

/*requestLayout() 當布局發(fā)生變化的 時候 比如 方向?尺寸? 不會調用draw() 方法 也就是說 不會重新繪制  (這個方法是重置)*/

/**
    * 我們知道,我們在Xml寫的布局文件最終會在通過Pull解析的方式轉成代碼的焕蹄。
    * onFinishInflate的作用逾雄,就是在xml加載組件完成后調用的。這個方法一般在自制ViewGroup的時候調用腻脏。
    * 這個回調方法是在整個布局文件都實例化結束后每個View才進行回調鸦泳,或者說是在控件及其子控件都實例化結束后每個View才進行的回調
    */
   @Override
   protected void onFinishInflate() {
       super.onFinishInflate();
   }

   /**
    * 如果舊的寬度和高度任意一個發(fā)生了改變都會調用sizeChange方法 
    * @param w
    * @param h
    * @param oldw
    * @param oldh
    */
   @Override
   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
       super.onSizeChanged(w, h, oldw, oldh);
   }



   /**
    * 該方法是焦點改變的回調方法,當某個控件重寫了該方法后永品,當焦點發(fā)生變化時辽故,會自動調用該方法來處理焦點改變事件
    * @param gainFocus  參數(shù)gainFocus表示觸發(fā)該事件的View是否獲得了焦點,當該控件獲得焦點時腐碱,gainFocus等于true,否則等于false
    * @param direction  參數(shù)direction表示焦點移動的方向掉弛,用數(shù)值表示
    * @param previouslyFocusedRect  表示觸發(fā)事件的View的坐標系中症见,前一個獲得焦點的矩形區(qū)域,即表示焦點是從哪里來的殃饿。如果不可以則為null
    */
   @Override
   protected void onFocusChanged(boolean gainFocus, int direction, @androidx.annotation.Nullable Rect previouslyFocusedRect) {
       super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
   }

為什么要用組合控件

1.執(zhí)行效率高(假設我們需要一個Button上既有圖片又有文字,常規(guī)提供的效果滿足不了我們.而且這個特殊的Button會有很多頁面用到.這個時候,我們就可以將這個Button寫成一個自定義組合控件)
2.維護成本低,容易修改(如:上邊所舉的的例子,這個自定義的組合控件相當于我們寫的基類,一旦需求被改變,我們只需要改動這個控件本身就好)
3.簡單,上手快,容易使用

自定義布局

引入布局

/*
在動態(tài)創(chuàng)建控件的時候調用,也就是JAVA代碼
*/
public class Custom extends LinearLayout {/*1.*/
    public Custom(Context context) {
        this(context,null);
    }
/*
在XML文件聲明的時候調用
*/
    public Custom(Context context,  AttributeSet attrs) {
        this(context, attrs,-1);
    }
/*
可以不借助XML文件去聲明Style資源 這里有個int參數(shù)
*/
    public Custom(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        /*2.*/LayoutInflater.from(context).inflate(R.layout.custom,this,true);
        //View.inflate(context,R.layout.custom,this);
    }
}

上述代碼標記:

1.自定義組合控件時可以繼承RelativeLayout谋作、LinearLayout、FrameLayout 等 控件(這里我們用LinearLayout)
2.LayoutInflater.from().inflate() 這個方法中的inflate()的三個參數(shù)依次是:

第二個參數(shù):
這里我們將this 傳入進去 父布局自然是ViewGroup,而我們繼承了LinearLayout,所以this沒有問題
第三個參數(shù):
如果 第二個參數(shù) 為null乎芳,無論attachToRoot為true或者false遵蚜,效果都是一樣的
如果 第二個參數(shù) 不為null,attachToRoot為true奈惑,表示將layout布局添加到root布局中
如果 第二個參數(shù) 不為null吭净,attachToRoot為false,表示不將layout布局添加到root布局肴甸,若要添加則需要手動addView
如果 第二個參數(shù) 不為null寂殉,不設置attachToRoot(即調用兩個參數(shù)的方法),情況和(2)中一樣

繼續(xù)講這個第2條,這里我們還有一個方法可以起到同樣的作 View.inflate(context,R.layout.custom,this) 這個方法和上一個方法有什么區(qū)別呢?
View的inflate()的方法是靜態(tài)方法 而我們的 LayoutInflater 中的則是 普通方法

第二個參數(shù)若是第三個參數(shù)為true,那么第二個參數(shù)的意義是從第一個參數(shù)填充成的view對象的父控件原在;若是第三個參數(shù)為false友扰,那么第二個參數(shù)的意義是可以為第一個參數(shù)生成的view對象的根布局提供LayoutParams參數(shù)的控件。
第三個參數(shù)庶柿,從第一個參數(shù)填充成的view對象是否要附著到第二個參數(shù)指定的控件上作為其子控件村怪。

LayoutInflater 是Android中專門進行布局填充的方法,Android中所有使用布局填充的地方浮庐,都會調用這個方法; View類中的inflate方法封裝了LayoutInflater類的inflate方法甚负,相比之下用法比上一個簡單,但是功能就不及了.
布局文件的根布局不受限制,盡量避免資源浪費,比如LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

自定義屬性

在res下的values中新建一個份attrs的xml文檔



以下的name=""中的中文是為了方便說明而已!命名須規(guī)范

<?xml version="1.0" encoding="utf-8"?>
<resources>
  
    <declare-styleable name="MyValues">
        <attr name="引用資源" format="reference" /> <!--引用資源  如:@drawable/textStyle(引用類型,傳入的是某一資源的ID,必須以@符號開頭)  -->
        <attr name="字符串" format="string" /> <!--字符串  如:"文字"  -->
        <attr name="布爾值" format="boolean" /> <!--布爾值  如:true  -->
        <attr name="浮點型" format="float" /> <!--浮點型  如:0.5  -->
        <attr name="整型" format="integer" /> <!--整型  如:1  -->
        <attr name="百分數(shù)" format="fraction" /> <!--百分數(shù)  如:20%(必須是%符號結尾)  -->
        <attr name="尺寸值" format="dimension" /> <!--尺寸  如:23dp (后面必須跟dp腊敲、dip击喂、px、sp等單位)    -->
        <attr name="顏色" format="color" /> <!--顏色  如:#FF565656  -->

        <!--拓展-->
        <attr name="顏色復合" format="reference|color" />


        <!--枚舉 enum 屬性只能選擇一個使用,如:  顏色enum="紅色"    -->
        <attr name="顏色enum" format="color">
            <enum name="紅色" value="#f00" />
            <enum name="黑色" value="#000" />
            <enum name="白色" value="#fff" />
        </attr>

        <!--位或運算 flag 屬性可以復合使用,如:   文字flag="one|two"   -->
        <attr name="文字flag" format="string">
            <flag name="one" value="1" />
            <flag name="two" value="2" />
            <flag name="three" value="3" />
        </attr>

    </declare-styleable>

</resources>

在JAVA代碼中的引用

 /*
        獲取我們自定義的 自定義屬性 文件  <declare-styleable name="MyValues">
         */
        TypedArray mAttrs = context.obtainStyledAttributes(attrs, R.styleable.MyValues);
        if(mAttrs !=null){

            /*
            參數(shù)1:xml 文件
            參數(shù)2:默認值
             */

            int color = mAttrs.getColor(R.styleable.MyValues_顏色, Color.WHITE);
            //根據(jù)你定義的方法 獲取到 在xml中填寫的值 用這個值對 控件進行操作~
           
        }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末碰辅,一起剝皮案震驚了整個濱河市懂昂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌没宾,老刑警劉巖凌彬,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異循衰,居然都是意外死亡铲敛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門会钝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伐蒋,“玉大人,你說我怎么就攤上這事迁酸∠扔悖” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵奸鬓,是天一觀的道長焙畔。 經(jīng)常有香客問我,道長串远,這世上最難降的妖魔是什么宏多? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮澡罚,結果婚禮上伸但,老公的妹妹穿的比我還像新娘。我一直安慰自己留搔,他們只是感情好砌烁,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著催式,像睡著了一般函喉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荣月,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天管呵,我揣著相機與錄音,去河邊找鬼哺窄。 笑死捐下,一個胖子當著我的面吹牛账锹,可吹牛的內容都是我干的。 我是一名探鬼主播坷襟,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奸柬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了婴程?” 一聲冷哼從身側響起廓奕,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎档叔,沒想到半個月后桌粉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡衙四,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年铃肯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片传蹈。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡押逼,死狀恐怖,靈堂內的尸體忽然破棺而出惦界,到底是詐尸還是另有隱情挑格,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布表锻,位于F島的核電站,受9級特大地震影響乞娄,放射性物質發(fā)生泄漏瞬逊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一仪或、第九天 我趴在偏房一處隱蔽的房頂上張望确镊。 院中可真熱鬧,春花似錦范删、人聲如沸蕾域。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旨巷。三九已至,卻和暖如春添忘,著一層夾襖步出監(jiān)牢的瞬間采呐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工搁骑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斧吐,地道東北人又固。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像煤率,于是被迫代替她去往敵國和親仰冠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容