Android自定義view初識(shí)(二)

其實(shí)這一篇的代碼是在一個(gè)周之前學(xué)習(xí)的,這里做復(fù)習(xí)用吧说搅。

首先 我們了解一下自定義控件的一些屬性以及用法:

首先先了解下自定義view的屬性吧:

目前已知的屬性:
reference 資源類型,通常是@開(kāi)頭,例如@+id/XXXX
string 字符串類型葛闷,通常是文字信息
dimension 浮點(diǎn)類型,通常是尺寸度量
color 顏色類型 通常是顏色16進(jìn)制代碼禀苦,支持ARBG
boolean 布爾類型 true和false
enum 枚舉類型既荚,通常是代表這個(gè)屬性提供了幾種值來(lái)進(jìn)行選擇,并且只能選擇這幾種中的一個(gè)
flag 與enum基本沒(méi)有區(qū)別搀绣。
integer 整數(shù)類型飞袋,通常是整數(shù)

在values文件夾下新建attrs.xml :寫法如下

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="viewtext" format="string"/>
    <attr name="viewSize"  format="dimension"/>
    <attr name="viewColor" format="color"/>
    <attr name="isCircle" format="boolean"/>
<!-- 如果即支持string 又支持reference的話--!>
<!--  <attr name="this" format="string|reference"/>--!>

    <declare-styleable name="customText">
        <attr name="viewtext"/>
        <attr name="viewSize"/>
        <attr name="viewColor"/>
        <attr name="isCircle"/>
    </declare-styleable>

</resources>

在這里我定義了控件的text 、大小链患、顏色巧鸭、和一個(gè)布爾值 。這些屬性
那么在attrs中定義了屬性的話麻捻,我們?nèi)绾卧诖a中獲得這些屬性呢:

記得在自定義view時(shí)重寫的三個(gè)構(gòu)造方法纲仍,第三個(gè)構(gòu)造方法便是用來(lái)解析自定義屬性的:

 public MyCustom(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            // 使用context對(duì)象獲得我們自定義的屬性的值,attrs是我們xml中使用的屬性集合贸毕,其中包括屬性名和屬性值等相關(guān)信息郑叠,后面是我們自定義的屬性,也就是我們定義的declare-styleable明棍。
            TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.customText);

            // 使用相應(yīng)的方法獲取各個(gè)類型屬性的值乡革,第二個(gè)參數(shù)是獲取不到屬性值默認(rèn)的屬性值。
            mText = typedArray.getString(R.styleable.customText_viewtext);

            mTextSize = typedArray.getDimension(R.styleable.customText_viewSize, 16);
            mTextColor = typedArray.getColor(R.styleable.customText_viewColor, Color.BLACK);
            isCircle = typedArray.getBoolean(R.styleable.customText_isCircle, false);

            // 沒(méi)啥击蹲,google推薦的署拟,使用完及時(shí)釋放
            typedArray.recycle();

            initPaint();
      }

下面是我復(fù)習(xí)的一點(diǎn)Paint的用法和自定義view測(cè)量大小寫的一點(diǎn)東西:

當(dāng)時(shí)我是畫了一個(gè)圓,然后呢歌豺,我在想推穷,能不能再圓上寫上字,然后讓字居中顯示类咧,我在xml中寫了:

android:text="HELLO"

發(fā)現(xiàn)然并卵馒铃,然后我發(fā)現(xiàn),我們要在代碼中給控件畫上字痕惋,然后設(shè)置文字的顯示位置区宇,這里還用到了一點(diǎn)字體測(cè)量的知識(shí)(FontMetrics這個(gè)和字體相關(guān)的重要的類),然后為了證實(shí)我們的居中位置判斷的沒(méi)錯(cuò)值戳,特意給控件畫上了一條中心線议谷。
關(guān)于字體測(cè)量這一塊:
愛(ài)哥的自定義控件其實(shí)很簡(jiǎn)單有非常詳細(xì)非常全面的介紹 。

效果如下圖

Paste_Image.png
public class MyCustom extends View {

      private Context mContext;
      private String mText;
      private float mTextSize;
      private boolean isCircle;
      private int mTextColor;

      private Paint mPaint;

      public MyCustom(Context context) {
            this(context, null);
      }

      public MyCustom(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
      }

      public MyCustom(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            // 使用context對(duì)象獲得我們自定義的屬性的值堕虹,attrs是我們xml中使用的屬性集合卧晓,其中包括屬性名和屬性值等相關(guān)信息芬首,后面是我們自定義的屬性,也就是我們定義的declare-styleable逼裆。
            TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.customText);

            // 使用相應(yīng)的方法獲取各個(gè)類型屬性的值郁稍,第二個(gè)參數(shù)是獲取不到屬性值默認(rèn)的屬性值。
            mText = typedArray.getString(R.styleable.customText_viewtext);

            mTextSize = typedArray.getDimension(R.styleable.customText_viewSize, 16);
            mTextColor = typedArray.getColor(R.styleable.customText_viewColor, Color.BLACK);
            isCircle = typedArray.getBoolean(R.styleable.customText_isCircle, false);

            // 沒(méi)啥胜宇,google推薦的耀怜,使用完及時(shí)釋放
            typedArray.recycle();

            initPaint();
      }

      private void initPaint() {

            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

      }


      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //測(cè)量控件的寬和高
            setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
      }

      @Override
      protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
          //在這里判斷是繪制圓形還是正方形
            if (isCircle) {
                /*  
                * 1.先畫圓,
                *  2.其次 文字
                */
                  mPaint.setColor(Color.GRAY);
                    //畫圓桐愉,這里的參數(shù)是: 圓心的坐標(biāo)x,y,圓的半徑财破,和畫筆
                  canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getHeight() / 2, mPaint);

                  mPaint.setColor(mTextColor);
                  mPaint.setTextSize(mTextSize);
                  //文字的x軸坐標(biāo)
                  //獲取text的寬度 (Paint.measureText()這個(gè)方法可以直接獲取text的寬度)
                  float textWidth = mPaint.measureText(mText);
                  //計(jì)算text開(kāi)始的橫坐標(biāo):  圓半徑/2  -  text寬度/2
                  float x = (canvas.getWidth() - textWidth) / 2;
                  //文字的y軸坐標(biāo) (這里用到FontMetrics不詳細(xì)注釋,之后會(huì)詳細(xì)學(xué)習(xí)這一塊)
                  Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
                  float y = canvas.getHeight() / 2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2;
                  canvas.drawText(mText, x, y, mPaint);//這里的y是指的text的基線的位置


            } else {
                  mPaint.setColor(Color.GRAY);
                  float left = getLeft();
                  float top = getTop();
                  float bottom = getBottom();
                  float right = getRight();
                  canvas.drawRect(left, top, right, bottom, mPaint);

                  //     Log.i("NUM-->", canvas.getDensity()+"");

                  mPaint.setColor(mTextColor);
                  mPaint.setTextSize(mTextSize);
                  float textWidth = mPaint.measureText(mText);
                  float x = canvas.getWidth() / 2 - textWidth / 2;

                  Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
                  float y = canvas.getHeight() / 2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2;

                  canvas.drawText(mText, x, y, mPaint);
            }

            //畫出控件的水平中心線
            mPaint.setColor(Color.YELLOW);
            // float startX, float startY, float stopX, float stopY,
            canvas.drawLine(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2 + 1, mPaint);
      }


      private int measureWidth(int widthMeasureSpec) {

            int result;
            int specMode = MeasureSpec.getMode(widthMeasureSpec);
            int specSize = MeasureSpec.getSize(widthMeasureSpec);

            if (specMode == MeasureSpec.EXACTLY) {

                  result = specSize;
            } else {

                  result = 200;
                  if (specMode == MeasureSpec.AT_MOST) {
                        result = Math.min(result, specSize);

                  }
            }

            return result;
      }


      private int measureHeight(int heightMeasureSpec) {
            int result;

            int specMode = MeasureSpec.getMode(heightMeasureSpec);
            int specSize = MeasureSpec.getSize(heightMeasureSpec);

          /*  根據(jù)測(cè)量模式和設(shè)置的大小來(lái)進(jìn)行測(cè)量
          *       測(cè)量模式有三種類型
          *       1仅财、EXACTLY 精確模式狈究。用戶設(shè)置了精確的寬和高或者是設(shè)置了match_parent充滿父控件
          *       2、AT_MOST  用戶設(shè)置了warp_content
          *       3.UNSPECTIFIED 什么都不設(shè)置盏求。一般是畫的控件
          * */

            if (specMode == MeasureSpec.EXACTLY) {
              //如果用戶設(shè)置的精確模式抖锥,則返回用戶設(shè)置的值
                  result = specSize;

            } else {
          //如果用戶沒(méi)有設(shè)置精確模式,那么我們首先定義一個(gè)標(biāo)準(zhǔn)值碎罚,
                  result = 200;
                  if (specMode == MeasureSpec.AT_MOST) {
                        result = Math.min(result, specSize);
                  }

            }

            return result;
      }


}

本人菜鳥(niǎo)磅废,正在努力學(xué)習(xí)中。荆烈。有什么錯(cuò)誤拯勉,希望大家指導(dǎo)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末憔购,一起剝皮案震驚了整個(gè)濱河市宫峦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玫鸟,老刑警劉巖导绷,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異屎飘,居然都是意外死亡妥曲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門钦购,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)檐盟,“玉大人,你說(shuō)我怎么就攤上這事押桃】” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)陌宿。 經(jīng)常有香客問(wèn)我锡足,道長(zhǎng)波丰,這世上最難降的妖魔是什么壳坪? 我笑而不...
    開(kāi)封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮掰烟,結(jié)果婚禮上爽蝴,老公的妹妹穿的比我還像新娘。我一直安慰自己纫骑,他們只是感情好蝎亚,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著先馆,像睡著了一般发框。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上煤墙,一...
    開(kāi)封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天梅惯,我揣著相機(jī)與錄音,去河邊找鬼仿野。 笑死铣减,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脚作。 我是一名探鬼主播葫哗,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼球涛!你這毒婦竟也來(lái)了劣针?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤亿扁,失蹤者是張志新(化名)和其女友劉穎捺典,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體魏烫,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辣苏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哄褒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稀蟋。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呐赡,靈堂內(nèi)的尸體忽然破棺而出退客,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布萌狂,位于F島的核電站档玻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏茫藏。R本人自食惡果不足惜误趴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望务傲。 院中可真熱鬧凉当,春花似錦、人聲如沸售葡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挟伙。三九已至楼雹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尖阔,已是汗流浹背贮缅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诺祸,地道東北人携悯。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筷笨,于是被迫代替她去往敵國(guó)和親憔鬼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,280評(píng)論 25 707
  • 6胃夏、View的繪制 (1)當(dāng)測(cè)量好一個(gè)View之后轴或,我們就可以簡(jiǎn)單的重寫 onDraw()方法,并在 Canvas...
    b5e7a6386c84閱讀 1,899評(píng)論 0 3
  • View的繼承關(guān)系 Android中所有控件,都是View或View的子類,比如開(kāi)發(fā)中最常寫的代碼 findVie...
    四月一號(hào)閱讀 712評(píng)論 1 3
  • 走出醫(yī)院時(shí)饺蚊,晚心無(wú)意識(shí)的向醫(yī)院的東邊看了看,那是火車站的方向悬嗓,他依舊沒(méi)有出現(xiàn)在晚心的視線里污呼。 晚心抬頭看著烏云密布...
    小魚叔閱讀 541評(píng)論 1 2
  • 最近看的電影部部都讓我落淚燕酷。 本以為看個(gè)溫情的喜劇電影不會(huì)再哭籍凝。 結(jié)果,哭得更難過(guò)了苗缩。 一 四口之家三人都有聽(tīng)說(shuō)障...
    一隻兔幾閱讀 361評(píng)論 1 2