從0到1Android自定義View(二)分類和核心函數(shù)

Android.jpg

前言

這篇主要還是介紹一些知識(shí)點(diǎn)井佑,包括上一篇的知識(shí)點(diǎn)在內(nèi),我們都是需要理解眠寿,只有這樣躬翁,才能更好的制作更多酷炫的自定義 View 。當(dāng)然每一篇文章都會(huì)越來越深入盯拱,一步一個(gè)臺(tái)階盒发,慢慢攀登例嘱。

目錄

從0到1Android自定義View(二) 分類和核心函數(shù).png

一、自定義 View 分類

常見的 Android 自定義 View 主要有兩種類型:

1宁舰、組合控件

通過 Android 的基礎(chǔ)控件(TextView拼卵、ImageView、Button蛮艰、ProgressBar 等)組合而成腋腮,比如下拉刷新、瀑布流控件壤蚜、帶左/右滑功能的控件即寡、視頻控件等,這種自定義View的難點(diǎn)在于程序的邏輯處理

2袜刷、完全自定義控件

繼承自 View聪富、TextureView 或 SurfaceView ,然后重寫核心的回調(diào)方法著蟹,以View 為例墩蔓,按需復(fù)寫其構(gòu)造、onMeasure萧豆、onLayout奸披、onTouchEvent、onDraw炕横、onAttachedToWindow源内、onDetachedFromWindow 等方法,這種自定義 View 的難點(diǎn)在于程序的設(shè)計(jì)份殿、效率優(yōu)化和排版膜钓,比如輸入法中的手寫控件、圖文混排控件(現(xiàn)在很多都是通過webview加載網(wǎng)頁實(shí)現(xiàn)了)卿嘲、個(gè)性化進(jìn)度條颂斜、彈幕顯示控件、Markdown控件拾枣、IDE代碼編輯控件等

注意:

我們需要合理的使用自定義 View 沃疮,千萬不能濫用,不要?jiǎng)硬粍?dòng)就自定義 View 梅肤,基礎(chǔ)控件能完成的工能司蔬,千萬別自定義 View,因?yàn)榛A(chǔ)空間 Android姨蝴,本身就有性能優(yōu)化的俊啼,自定義 View 的價(jià)值在于做到基礎(chǔ)控件無法做到的效果,為應(yīng)用的表現(xiàn)增色左医;授帕,將公用的交互效果提取成自定義控件同木,方便復(fù)用,減少不必要的重復(fù)勞動(dòng)跛十。

二彤路、自定義 View 核心知識(shí)點(diǎn)

這部分主要是介紹自定義 View 的核心知識(shí)點(diǎn),上面提到過芥映,完全自定義 View 通常是繼承 View 洲尊,TextureView,SurfaceView屏轰,所以先來了解下這三者之間的區(qū)別所在颊郎。

1、 View霎苗、SurfaceView姆吭、TextureView 的區(qū)別

View

普通的 View,與宿主窗口共享同一個(gè)繪圖表面唁盏,UI 在主線程中繪制内狸,在有無硬件加速的情況下都能工作(沒有硬件加速的情況下,canvas 的有些方法會(huì)失效)

SurfaceView

繼承自 View厘擂,繪制和顯示效率高昆淡,因?yàn)閾碛歇?dú)立的繪圖表面,UI 在一個(gè)獨(dú)立的線程中進(jìn)行繪制刽严,不會(huì)占用主線程的資源昂灵。SurfaceView 的使用和普通的 View 不一樣,需要結(jié)合 SurfaceHodler 一起使用舞萄。因?yàn)楹退拗鞔翱诓皇枪蚕硗粋€(gè)繪圖表面的原因眨补,對(duì)其做動(dòng)畫操作可能會(huì)得不到想要的效果

TextureView

繼承自 View,與 SurfaceView 相比倒脓,TextureView 不會(huì)創(chuàng)建一個(gè)單獨(dú)的繪圖表面撑螺,這使得它可以像一般的 View 一樣執(zhí)行一些變換操作,比如移動(dòng)崎弃、動(dòng)畫等等甘晤,但 TextureView 必須在硬件加速開啟的窗口中才能正常工作;

2饲做、 幾個(gè)重要的函數(shù)
最后通過自定義 View 的流程圖來了解一下自定義 View 幾個(gè)重要的函數(shù)线婚。

自定義view的流程圖.jpg

(1)構(gòu)造函數(shù)

構(gòu)造函數(shù)是View的入口,可以用于初始化一些的內(nèi)容盆均,和獲取自定義屬性

View的構(gòu)造函數(shù)有四種重載

自定義View的構(gòu)造函數(shù).png

從上面的圖也可以看出酌伊,自定 View 的構(gòu)造函數(shù)的參數(shù)最多有四個(gè),而且有四個(gè)參數(shù)的構(gòu)造函數(shù)只能在 API 21 以上使用缀踪,因此四個(gè)參數(shù)的構(gòu)造函數(shù)先不考慮居砖,不過我們也需要了解這四個(gè)參數(shù)具體代表什么?

Context: View 中隨處都會(huì)用到
AttributeSet: XML 屬性(從 XML inflate 的時(shí)候使用)
int defStyleAttr: 應(yīng)用到 View 的默認(rèn)風(fēng)格(定義在主題中)
int defStyleRes: 如果沒有使用 defStyleAttr驴娃,應(yīng)用到 View 的默認(rèn)風(fēng)格

那么這里就有個(gè)問題了奏候,有四種構(gòu)造函數(shù),我們該怎么選擇呢唇敞?

比如上面圖片顯示的自定義的 MyView 蔗草,繼承 View 對(duì)象,如果我們想在普通的代碼中新建一個(gè) MyView疆柔,可以直接使用一個(gè)參數(shù)的構(gòu)造函數(shù)咒精,這也是大多數(shù)選擇使用的。

一個(gè)參數(shù)的構(gòu)造函數(shù).png

那么兩個(gè)參數(shù)的構(gòu)造函數(shù)什么時(shí)候使用呢旷档?比如有時(shí)候在 xml 中添加一個(gè)自定義 View 模叙,并且加了一些布局屬性,寬高屬性以及 margin 屬性鞋屈,這些屬性會(huì)存放在第二個(gè)構(gòu)造函數(shù)的 AttributeSet 參數(shù)里范咨。

兩個(gè)參數(shù)的構(gòu)造函數(shù).png

有三個(gè)參數(shù)的構(gòu)造函數(shù)比第二個(gè)構(gòu)造函數(shù)多了一個(gè) int 型的值,名字叫 defStyleAttr 厂庇,從名稱上判斷渠啊,這是一個(gè)關(guān)于自定義屬性的參數(shù)。第三個(gè)構(gòu)造函數(shù)不會(huì)被系統(tǒng)默認(rèn)調(diào)用权旷,而是需要我們自己去顯式調(diào)用替蛉,比如在第二個(gè)構(gòu)造函數(shù)里調(diào)用調(diào)用第三個(gè)函數(shù),并將第三個(gè)參數(shù)設(shè)為0 拄氯。defStyleAttr 指定的是在Theme style 定義的一個(gè) attr躲查,它的類型是 reference 主要生效在 obtainStyledAttributes 方法里,obtainStyledAttributes 方法有四個(gè)參數(shù)坤邪,第三個(gè)參數(shù)是 defStyleAttr 熙含,第四個(gè)參數(shù)是自己指定的一個(gè) style ,當(dāng)且僅當(dāng) defStyleAttr 為 0 或者在 Theme 中找不到 defStyleAttr 指定的屬性時(shí)艇纺,第四個(gè)參數(shù)才會(huì)生效怎静,這些指的都是默認(rèn)屬性,當(dāng)在 xml 里面定義的黔衡,就以在 xml 文件里指定的為準(zhǔn)蚓聘,所以優(yōu)先級(jí)大概是:xml>style>defStyleAttr>defStyleRes>Theme 指定,當(dāng)defStyleAttr 為 0 時(shí)盟劫,就跳過 defStyleAttr 指定的 reference 夜牡,所以一般用 0 就能滿足一些基本開發(fā)。

(2)onMeasure(測量 View 大小)

這個(gè)函數(shù)有什么用呢塘装?將這個(gè)問題轉(zhuǎn)化一下急迂,就是問為什么要測量 View 的大小呢?

因?yàn)?View 的大小不僅由自身所決定蹦肴,同時(shí)也會(huì)受到父控件的影響僚碎,為了我們的控件能更好的適應(yīng)各種情況,一般會(huì)自己進(jìn)行測量

onMeasure.png

MeasureSpce 的 mode 有三種:EXACTLY, AT_MOST阴幌,UNSPECIFIED勺阐,除去 UNSPECIFIED 不談,其他兩種 mode:

當(dāng)父布局是 EXACTLY 時(shí)矛双,子控件確定大小或者 match_parent渊抽,mode 都是 EXACTLY,子控件是 wrap_content 時(shí)议忽,mode 為 AT_MOST懒闷;

當(dāng)父布局是 AT_MOST 時(shí),子控件確定大小徙瓶,mode 為 EXACTLY毛雇,子控件 wrap_content 或者 match_parent 時(shí),mode 為 AT_MOST侦镇。

所以在確定控件大小時(shí)灵疮,需要判斷 MeasureSpec 的 mode,不能直接用 MeasureSpec 的 size壳繁。在進(jìn)行一些邏輯處理以后震捣,調(diào)用 setMeasureDimension() 方法,將測量得到的寬高傳進(jìn)去供 layout 使用闹炉。

onMeasure流程.png

在實(shí)際運(yùn)用之中只需要記住有測量模式有三種蒿赢,用 MeasureSpec 的 getSize是獲取數(shù)值, getMode是獲取模式即可渣触。如果對(duì) View 的寬高進(jìn)行修改了羡棵,不要調(diào)用 super.onMeasure( widthMeasureSpec, heightMeasureSpec); 要調(diào)用 setMeasuredDimension( widthsize, heightsize); 這個(gè)函數(shù)。

(3)onSizeChanged(確定 View 大行嶙辍)

那么這個(gè)函數(shù)又是什么時(shí)候調(diào)用呢皂冰?

這個(gè)函數(shù)在視圖大小發(fā)生改變時(shí)調(diào)用。

那么問題又來了养篓,上面的 onMeasure 函數(shù)中不是說對(duì) View 的寬高進(jìn)行了修改后秃流,要調(diào)用 setMeasuredDimension 嗎?調(diào)用這個(gè)方法后柳弄,View 的大小基本已經(jīng)確定了啊舶胀,View 的視圖大小還會(huì)發(fā)生變化嗎?這是因?yàn)?View 的大小不僅僅只是由其本身來決定的,也受它的父控件影響嚣伐,所以在確定 View 大小的時(shí)候最好使用系統(tǒng)提供的 onSizeChanged 回調(diào)函數(shù)糖赔。

onSizeChanged.png

(4)onLayout(確定子 View 布局位置)

確定布局的函數(shù)是 onLayout ,它用于確定子 View 的位置纤控,在自定義 ViewGroup 中會(huì)用到挂捻,他調(diào)用的是子 View 的 layout 函數(shù)。比如船万,有時(shí)候我們自定義 View 的時(shí)候,需要獲取 View 的一些信息就需要用到這個(gè)函數(shù)骨田。當(dāng)然耿导,如果是單純的 View 就沒與必要重寫這個(gè)方法,為什么這么說呢态贤?

因?yàn)閱渭兊?View 舱呻,不是一個(gè) View 容器,沒有子 View 悠汽,而 onLayout 方法里主要是具體擺放子View 的位置箱吕,水平擺放或者垂直擺放,所以在單純的自定義 View 是不需要重寫 onLayout 方法柿冲。不過需要注意的一點(diǎn)是茬高,子 View 的 margin 屬性是否生效就要看 parent 是否在自身的 onLayout 方法進(jìn)行處理,而 View 的 padding 屬性是在 onDraw 方法中生效的

(5)onDraw(繪制內(nèi)容)

重頭戲假抄,onDraw怎栽,也就是是實(shí)際繪制的部分。

onDraw.png

一般自定義控件耗費(fèi)心思最多的就是這個(gè)方法了宿饱,需要在這個(gè)方法里熏瞄,用 Paint 在 Canvas 上畫出你想要的圖案。如果是直接繼承的 View谬以,那么在重寫 onDraw 的方法是時(shí)候完全可以把 super.ondraw(canvas) 刪掉强饮,因?yàn)樗哪J(rèn)實(shí)現(xiàn)是空。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末为黎,一起剝皮案震驚了整個(gè)濱河市邮丰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碍舍,老刑警劉巖柠座,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異片橡,居然都是意外死亡妈经,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吹泡,“玉大人骤星,你說我怎么就攤上這事”疲” “怎么了洞难?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長揭朝。 經(jīng)常有香客問我队贱,道長,這世上最難降的妖魔是什么潭袱? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任柱嫌,我火速辦了婚禮,結(jié)果婚禮上屯换,老公的妹妹穿的比我還像新娘编丘。我一直安慰自己,他們只是感情好彤悔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布嘉抓。 她就那樣靜靜地躺著,像睡著了一般晕窑。 火紅的嫁衣襯著肌膚如雪抑片。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天幕屹,我揣著相機(jī)與錄音蓝丙,去河邊找鬼。 笑死望拖,一個(gè)胖子當(dāng)著我的面吹牛渺尘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播说敏,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼鸥跟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盔沫?” 一聲冷哼從身側(cè)響起医咨,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎架诞,沒想到半個(gè)月后拟淮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谴忧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年很泊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了角虫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡委造,死狀恐怖戳鹅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昏兆,我是刑警寧澤枫虏,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站爬虱,受9級(jí)特大地震影響隶债,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饮潦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一燃异、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧继蜡,春花似錦、人聲如沸逛腿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽单默。三九已至碘举,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搁廓,已是汗流浹背引颈。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留境蜕,地道東北人蝙场。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像粱年,于是被迫代替她去往敵國和親售滤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

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

  • 目錄 從0到1Android自定義View(二) 分類和核心函數(shù).png 一台诗、自定義 View 分類 常見的 An...
    justCode_閱讀 641評(píng)論 0 3
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,791評(píng)論 25 707
  • 作者微博: @GcsSloop 【本系列相關(guān)文章】 經(jīng)歷過前面三篇啰啰嗦嗦的基礎(chǔ)篇之后完箩,終于到了進(jìn)階篇,正式進(jìn)入解...
    GcsSloop閱讀 1,328評(píng)論 2 24
  • 一拉队、前言 標(biāo)題起得屌了點(diǎn)弊知,文章只能給大家?guī)砝碚撝R(shí),能不能上天還是得各位親自實(shí)踐粱快。文中涉及到很多自己的理解秩彤,能力...
    張明云閱讀 8,763評(píng)論 1 138
  • 我獨(dú)自靜坐在窗前叔扼,望著窗外飄著的雨,此刻我便想起了你呐舔,想起了和你共度的那段夢幻般的浪漫雨季币励。 那是一個(gè)飄雨的日子,...
    老凌閱讀 359評(píng)論 1 2