Android開發(fā)之自定義View

自定義控件

使用場景: 在實際開發(fā)中經(jīng)常會遇到現(xiàn)有的UI控件不能滿足項目需求咖刃,或一個功能涉及到多個UI控件的組合泳炉,或?qū)崿F(xiàn)某一特效的UI,這時必須通過自定義View的方式嚎杨,實現(xiàn)這些功能花鹅,例如股票的實時統(tǒng)計圖、電子書等枫浙。

分類

繪制控件 - 自繪控件

1.繼承View
需要自定義繪制內(nèi)容刨肃,需要繼承View,必須要重寫onDraw方法箩帚,在onDraw方法中來進行繪制真友,實現(xiàn)onMeasure方法,來測量控件的空間紧帕。

2.繼承ViewGroup

  • 通過在ViewGroup中通過this.addView(<控件對象>)來添加控件
  • onMeasure方法盔然,來測量控件的空間
  • onLayout方法必須實現(xiàn),在此方法中處理子控件的位置是嗜。當視圖初始化愈案,或者視圖位置發(fā)生改變時候,調(diào)用此方法鹅搪。

組合控件

通過繼承系統(tǒng)已經(jīng)存在的視圖容器站绪,在初始化時候,直接加載布局

mInflater.inflate(<布局資源的ID>,this);
mIvBack = (ImageView) findViewById(R.id.btn_back);

繼承控件

通過繼承系統(tǒng)已經(jīng)存在的視圖或者視圖容器丽柿,在內(nèi)部改變此視圖或者視圖容器的功能
例如:通過改變ListView添加刪除功能

自定義View步驟

  • 創(chuàng)建類恢准,繼承View及View的子類,并提供相關的構造方法
  • 重寫onMeasure()方法甫题,并調(diào)用setMeasuredDimension(int width, int height)設置控件的大小
  • 重寫onDraw()方法顷歌,實現(xiàn)繪制特定內(nèi)容
  • 重寫onTouchEvent()方式處理觸摸事件
  • 在布局文件中使用<類全名>并設置屬性

自定義View屬性

1.位置:res/values/attrs.xml

2.屬性集

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 聲明屬性集 -->
    <declare-styleable name="LabelView">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color" />
    </declare-styleable>
</resources>

3.指定屬性名及其內(nèi)容格式
例:<attr name="text" format="string" />

string 字符型
integer 整數(shù)型
dimension 尺寸值
color 顏色值
reference 參考某一資源ID
boolean:布爾值

使用自定義View屬性

在布局控件標簽中引用:xmlns:my="http://schemas.android.com/apk/res/{package_name}"
或xmlns:app="http://schemas.android.com/apk/res-auto"
在自定義控件中使用:my:text=““或app:text=""

在自定義View的View(Context context, AttributeSet attrs)構造方法中,獲取自定義屬性的值

//TypedArray是一個用來存放由context.obtainStyledAttributes獲得的屬性的數(shù)組
        //在使用完成后,一定要調(diào)用recycle方法
         TypedArray ta = context.obtainStyledAttributes(attrs,
                    R.styleable.LabelView);

            CharSequence s = ta.getString(R.styleable.LabelView_text);
            if (s != null) {
                setText(s.toString());
            }

            setTextColor(ta.getColor(R.styleable.LabelView_textColor, 0xFF000000));

            int textSize = ta.getDimensionPixelSize(R.styleable.LabelView_textSize, 0);
            if (textSize > 0) {
                setTextSize(textSize);
            }
            ta.recycle();

涉及相關類

View 類

  • View(Context) 動態(tài)實例化控件的構造方法
  • View(Context context, AttributeSet attrs) 布局中使用控件的構造的方法
  • onMeasure(int widthMeasureSpec, int heightMeasureSpec) 自定義控件時重寫的方法幔睬,用于測量控件大小
  • onDraw(Canvas canvas) 在自義控件上繪制相關內(nèi)容
  • onTouchEvent(MotionEvent) 實現(xiàn)觸摸事件處理方法
  • setPadding(int l,int t,int r,int b) 設置內(nèi)部間距
  • layout(int l, int t, int r,int b) 改變控件位置的方法
  • requestLayout() //清除布局眯漩,獲取新的布局空間(刷新UI,重新調(diào)用onDraw()方法繪制UI)
  • invalidate() //重新繪制新的數(shù)據(jù)(刷新UI麻顶,重新調(diào)用onDraw()方法繪制UI)

MeasureSpec 測量空間工具類

  • int MeasureSpec.getMode(mSpec) 獲取控件大小模式
    • MeasureSpec.EXACTLY辅肾,確切空間,布局中的屬性值一般為match_parent或160dp固定值
    • MeasureSpec.AT_MOST 盡量多的空間要尔,布局中的屬性值wrap_content
    • MeasureSpec.UNSPECIFIED 未指定的,一般在父控件中使用
  • MeasureSpec.getSize(mSpec) 獲取控件大小

TypedArray 屬性數(shù)組類

  • TypeArray Context.obtainStyledAttributes(attrs,R.styleable.LabelView) 獲取指定attrs中的所有屬性
  • String getString(R.styleable.LabelView_text) 獲取指定屬性的文本值
  • int getDimensionPixelSize(R.styleable.LabelView_textSize, 0) 獲取指定屬性的間距值
  • int getColor(R.styleable.LabelView_textColor, 0xFF000000) 獲取指定屬性的顏色值

Paint 畫筆類

  • Paint.setAntiAlias(true) 啟用抗鋸齒
  • Paint.setTextSize(int pixes) 設置字體大小既绩,像素饲握,一般轉成sp
  • Paint.setColor(int color) 設置顏色
  • Paint.setStyle(Paint.Style) 設置畫筆樣式
  • float mTextPaint.measureText(String) 測量文字的大小
  • Paint.ascent() 獲取文字基準線以上到文字頂部的間距蚕键,負數(shù)
  • Paint.descent() 獲取文字基準線以下到文字底部的間距

Canvas 畫布類

  • canvas.drawText(String,int x,int y,Paint) 繪制文本
  • canvas.drawRoundRect(RectF,int rx,int ry,Paint) 繪制圓角四邊方形
  • canvas.drawBitmap(bitmap, left, top, paint) 繪制圖片
  • canvas.drawCircle(cx, cy, radius, paint) 繪制圓
  • canvas.drawLine(startX, startY, stopX, stopY, paint) 繪制線條

Xfermode 兩個圖層的轉換模式

Xfermode有三個子類 :
AvoidXfermode 指定了一個顏色和容差锣光,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。
PixelXorXfermode 當覆蓋已有的顏色時骑疆,應用一個簡單的像素異或操作箍铭。
PorterDuffXfermode 這是一個非常強大的轉換模式椎镣,使用它,可以使用圖像合成的16條Porter-Duff規(guī)則的任意一條來控制Paint如何與已有的Canvas圖像進行交互冷守。


要應用轉換模式拍摇,可以使用setXferMode方法,如下所示:

AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID);
borderPen.setXfermode(avoid);

PorterDuff.Mode為枚舉類,一共有16個枚舉值:

1.PorterDuff.Mode.CLEAR
所繪制不會提交到畫布上充活。
2.PorterDuff.Mode.SRC
顯示上層繪制圖片
3.PorterDuff.Mode.DST
顯示下層繪制圖片
4.PorterDuff.Mode.SRC_OVER
正常繪制顯示混卵,上下層繪制疊蓋窖张。
5.PorterDuff.Mode.DST_OVER
上下層都顯示。下層居上顯示赘淮。
6.PorterDuff.Mode.SRC_IN
取兩層繪制交集。顯示上層走诞。
7.PorterDuff.Mode.DST_IN
取兩層繪制交集低剔。顯示下層襟齿。
8.PorterDuff.Mode.SRC_OUT
取上層繪制非交集部分枕赵。
9.PorterDuff.Mode.DST_OUT
取下層繪制非交集部分拷窜。
10.PorterDuff.Mode.SRC_ATOP
取下層非交集部分與上層交集部分
11.PorterDuff.Mode.DST_ATOP
取上層非交集部分與下層交集部分
12.PorterDuff.Mode.XOR
異或:去除兩圖層交集部分
13.PorterDuff.Mode.DARKEN
取兩圖層全部區(qū)域,交集部分顏色加深
14.PorterDuff.Mode.LIGHTEN
取兩圖層全部赋荆,點亮交集部分顏色
15.PorterDuff.Mode.MULTIPLY
取兩圖層交集部分疊加后顏色
16.PorterDuff.Mode.SCREEN
取兩圖層全部區(qū)域窄潭,交集部分變?yōu)橥该魃?/p>

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫉你,一起剝皮案震驚了整個濱河市躏惋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌距误,老刑警劉巖深寥,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惋鹅,死亡現(xiàn)場離奇詭異,居然都是意外死亡闰集,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門爽雄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挚瘟,“玉大人,你說我怎么就攤上這事乘盖°旧妫” “怎么了兜叨?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矛物。 經(jīng)常有香客問我跪但,道長,這世上最難降的妖魔是什么吧雹? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任雄卷,我火速辦了婚禮蛤售,結果婚禮上,老公的妹妹穿的比我還像新娘揣钦。我一直安慰自己漠酿,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布宇姚。 她就那樣靜靜地躺著,像睡著了一般阱持。 火紅的嫁衣襯著肌膚如雪衷咽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天镶骗,我揣著相機與錄音卖词,去河邊找鬼吏夯。 笑死即横,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的跺嗽。 我是一名探鬼主播页藻,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼璃吧,長吁一口氣:“原來是場噩夢啊……” “哼废境!你這毒婦竟也來了?” 一聲冷哼從身側響起噩凹,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤驮宴,失蹤者是張志新(化名)和其女友劉穎逮刨,沒想到半個月后禀忆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡离熏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年戴涝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奸鸯。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡可帽,死狀恐怖映跟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情球恤,我是刑警寧澤荸镊,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布躬存,位于F島的核電站,受9級特大地震影響宛逗,放射性物質(zhì)發(fā)生泄漏钦椭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一侥锦、第九天 我趴在偏房一處隱蔽的房頂上張望恭垦。 院中可真熱鬧,春花似錦唠帝、人聲如沸玄柏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苔悦。三九已至椎咧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蟋座,已是汗流浹背地技。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工莫矗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留砂缩,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓妹懒,卻偏偏與公主長得像眨唬,于是被迫代替她去往敵國和親好乐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

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