自定義視圖組件

Android提供了一個復雜而強大的組件化模型凿可,用于構(gòu)建UI蕾盯,基于基本布局類:ViewViewGroup仁连。
首先,該平臺包括各種預構(gòu)建的ViewViewGroup子類 - 分別稱為小部件和布局 - 可用于構(gòu)建UI径簿。

如果預構(gòu)建的小部件或布局都不符合您的需求,您可以創(chuàng)建自己的View子類嘀韧。如果您只需要對現(xiàn)有窗口小部件或布局進行小的調(diào)整篇亭,則可以簡單地對窗口小部件或布局進行子類化并覆蓋其方法。

創(chuàng)建自己的View子類可以精確控制屏幕元素的外觀和功能锄贷。要了解自定義視圖所獲得的控件译蒂,下面是一些可以使用它們執(zhí)行操作的示例:

  • 您可以創(chuàng)建一個完全自定義渲染的視圖類型,例如使用2D圖形渲染的“音量控制”旋鈕谊却,類似于模擬電子控件柔昼。

  • 您可以將一組View組件組合成一個新的單個組件,可能是為了制作類似ComboBox(彈出列表和自由輸入文本字段的組合)炎辨,雙窗格選擇器控件(左側(cè)和右側(cè)窗格捕透,其中包含一個列表) 每個你可以重新分配哪個項目在哪個列表中),等等。

  • 您可以覆蓋EditText組件在屏幕上呈現(xiàn)的方式(Notepad Tutorial使用它可以很好地創(chuàng)建帶襯里的記事本頁面)乙嘀。

  • 您可以捕獲其他事件末购,如按鍵,并以某種自定義方式處理它們(例如游戲)虎谢。

以下部分介紹了如何創(chuàng)建自定義視圖并在應用程序中使用它們盟榴。 有關詳細參考信息,請參閱View類婴噩。

一擎场、基本方法

以下是開始創(chuàng)建自己的View組件時需要了解的內(nèi)容的高級概述:

  1. 使用您自己的類擴展現(xiàn)有的View類或子類。

  2. 覆蓋超類中的一些方法几莽。 要覆蓋的超類方法以'on'開頭顶籽,例如onDraw()onMeasure()onKeyDown()银觅。 這類似于您為生命周期和其他功能掛鉤覆蓋的ActivityListActivity中的on ...事件礼饱。

3、使用新的擴展類究驴。 完成后镊绪,可以使用新的擴展類來代替它所基于的視圖。

提示:擴展類可以定義為使用它們的活動內(nèi)部的內(nèi)部類洒忧。 這很有用蝴韭,因為它控制對它們的訪問但不是必需的(可能您希望創(chuàng)建一個新的公共視圖以便在您的應用程序中更廣泛地使用)。

二熙侍、完全定制的組件

完全自定義的組件可用于創(chuàng)建您想要的圖形組件榄鉴。 也許是一個圖形VU表,看起來像一個舊的模擬儀表蛉抓,或一個長長的文本視圖庆尘,其中彈跳球沿著單詞移動,所以你可以與卡拉OK機一起唱歌巷送。 無論哪種方式驶忌,無論你如何組合它們,你都需要內(nèi)置組件不會做的事情笑跛。

幸運的是付魔,您可以輕松地以您喜歡的任何方式創(chuàng)建外觀和行為的組件,可能僅限于您的想象力飞蹂,屏幕大小和可用處理能力(請記住几苍,最終您的應用程序可能必須運行在顯著更少的東西上 功率比您的桌面工作站)。

要創(chuàng)建完全自定義的組件:

  1. 您可以擴展的最通用的視圖陈哑,不出所料妻坝,View妖胀,所以您通常會首先擴展它以創(chuàng)建新的超級組件。

  2. 您可以提供一個可以從XML獲取屬性和參數(shù)的構(gòu)造函數(shù)惠勒,您也可以使用自己的屬性和參數(shù)(可能是VU表的顏色和范圍,或者針的寬度和阻尼等)爬坑。

  3. 您可能希望在組件類中創(chuàng)建自己的事件偵聽器纠屋,屬性訪問器和修改器,以及可能更復雜的行為盾计。

  4. 您幾乎肯定想要覆蓋onMeasure()售担,如果您希望組件顯示某些東西,也可能需要覆蓋onDraw()署辉。 雖然兩者都有默認行為族铆,但默認的onDraw()將不執(zhí)行任何操作,默認的onMeasure()將始終設置為100x100的大小 - 這可能不是您想要的哭尝。

  5. 其他on ...方法也可以根據(jù)需要覆蓋哥攘。

擴展onDraw()和onMeasure()

onDraw()方法為您提供了一個Canvas,您可以在其上實現(xiàn)任何您想要的東西:2D圖形材鹦,其他標準或自定義組件逝淹,樣式文本或您能想到的任何其他內(nèi)容。

注意:這不適用于3D圖形桶唐。 如果要使用3D圖形栅葡,則必須擴展SurfaceView而不是View,并從單獨的線程中繪制尤泽。 有關詳細信息欣簇,請參閱GLSurfaceViewActivity示例。

onMeasure()更多涉及坯约。onMeasure()是組件與其容器之間的渲染合同的關鍵部分熊咽。 應該重寫onMeasure()以高效準確地報告其包含部分的測量值。 根據(jù)父級的限制要求(傳入onMeasure()方法)以及一旦計算出的測量寬度和高度調(diào)用setMeasuredDimension()方法的要求闹丐,這會稍微復雜一些网棍。 如果您未能從重寫的onMeasure()方法調(diào)用此方法,則結(jié)果將是測量時的異常妇智。

在較高的層次上滥玷,實現(xiàn)onMeasure()看起來像這樣:

  1. 使用寬度和高度測量規(guī)范(widthMeasureSpecheightMeasureSpec參數(shù),都是表示尺寸的整數(shù)代碼)調(diào)用重寫的onMeasure()方法巍棱,應將其視為對應生成的寬度和高度測量的限制的要求惑畴。 可以在View.onMeasure(int,int)下的參考文檔中找到這些規(guī)范可能需要的限制的完整參考(此參考文檔也非常好地解釋了整個測量操作)航徙。

  2. 組件的onMeasure()方法應計算渲染組件所需的測量寬度和高度如贷。 它應該盡量保持在傳入的規(guī)范內(nèi),盡管它可以選擇超過它們(在這種情況下,父級可以選擇做什么杠袱,包括剪切尚猿,滾動,拋出異常楣富,或者讓onMeasure()再試一次凿掂, 也許有不同的測量規(guī)格)。

  3. 計算寬度和高度后纹蝴,必須使用計算的測量值調(diào)用setMeasuredDimension(int width庄萎,int height)方法。 如果不這樣做將導致拋出異常塘安。

三糠涛、復合控制

如果您不想創(chuàng)建完全自定義的組件,而是希望將由一組現(xiàn)有控件組成的可重用組件放在一起兼犯,那么創(chuàng)建復合組件(或復合控件)可能符合要求忍捡。 簡而言之,這將更多原子控件(或視圖)集合到一個邏輯組項中切黔,這些項可以作為單個事物處理锉罐。 例如,組合框可以被認為是單行EditText字段和具有附加PopupList的相鄰按鈕的組合绕娘。 如果按下按鈕并從列表中選擇一些內(nèi)容脓规,它會填充EditText字段,但如果用戶愿意险领,用戶也可以直接在EditText中輸入內(nèi)容侨舆。

Android中,實際上有兩個其他視圖可供使用:SpinnerAutoCompleteTextView绢陌,但無論如何挨下,組合框的概念是一個易于理解的例子。

要創(chuàng)建復合組件:

  1. 通常的起點是某種布局脐湾,因此創(chuàng)建一個擴展布局的類臭笆。 也許在組合框的情況下,我們可能使用具有水平方向的LinearLayout秤掌。 請記住愁铺,其他布局可以嵌套在內(nèi)部,因此復合組件可以是任意復雜和結(jié)構(gòu)化的闻鉴。 請注意茵乱,就像使用Activity一樣,您可以使用聲明式(基于XML)方法來創(chuàng)建包含的組件孟岛,也可以從代碼中以編程方式嵌套它們瓶竭。

  2. 在新類的構(gòu)造函數(shù)中督勺,獲取超類所需的任何參數(shù),并首先將它們傳遞給超類構(gòu)造函數(shù)斤贰。 然后智哀,您可以設置其他視圖以在新組件中使用; 這是您創(chuàng)建EditText字段和PopupList的位置。 請注意荧恍,您還可以在XML中引入自己的屬性和參數(shù)瓷叫,這些屬性和參數(shù)可以由構(gòu)造函數(shù)提取和使用。

  3. 您還可以為包含的視圖可能生成的事件創(chuàng)建偵聽器块饺,例如,List Item的偵聽器方法單擊Listener以在創(chuàng)建列表時更新EditText的內(nèi)容雌芽。

  4. 您還可以使用訪問器和修飾符創(chuàng)建自己的屬性授艰,例如,允許在組件中最初設置EditText值世落,并在需要時查詢其內(nèi)容淮腾。

  5. 在擴展布局的情況下,您不需要覆蓋onDraw()onMeasure()方法屉佳,因為布局將具有可能正常工作的默認行為谷朝。 但是,如果需要武花,您仍然可以覆蓋它們圆凰。

  6. 你可以覆蓋其他on ...方法,比如onKeyDown()体箕,或者在按下某個鍵時從組合框的彈出列表中選擇某些默認值专钉。

總而言之,使用布局作為自定義控件的基礎具有許多優(yōu)點累铅,包括:

  • 您可以使用聲明性XML文件指定布局跃须,就像使用活動屏幕一樣,或者您可以以編程方式創(chuàng)建視圖并將它們嵌入到代碼的布局中娃兽。

  • onDraw()onMeasure()方法(以及其他大多數(shù)on ......方法)可能具有合適的行為菇民,因此您不必覆蓋它們。

  • 最后投储,您可以非车诹罚快速地構(gòu)造任意復雜的復合視圖,并將它們重新使用玛荞,就像它們是單個組件一樣复旬。

四、修改現(xiàn)有視圖類型

創(chuàng)建自定義視圖有一個更簡單的選項冲泥,這在某些情況下很有用驹碍。 如果某個組件已經(jīng)非常類似于您想要的組件壁涎,則只需擴展該組件并覆蓋您想要更改的行為即可。 您可以使用完全自定義的組件執(zhí)行所有操作志秃,但是從View層次結(jié)構(gòu)中的更專業(yè)的類開始怔球,您還可以免費獲得許多可能完全符合您需要的行為。

作為示例浮还,NotePad應用程序演示了使用Android平臺的許多方面竟坛。 其中包括擴展EditText視圖以制作帶襯里的記事本。 這不是一個完美的例子钧舌,用于這樣做的API可能會改變担汤,但它確實證明了這些原則。

如果您還沒有這樣做洼冻,請將NotePad示例導入Android Studio(或者使用提供的鏈接查看源代碼)崭歧。 特別要注意NoteEditor.java文件中LinedEditText的定義。

以下是此文件中需要注意的事項:

  1. 定義

該類定義如下:

public static class LinedEditText extends EditText
  • LinedEditText被定義為NoteEditor活動中的內(nèi)部類撞牢,但它是公共的率碾,因此如果需要,它可以從NoteEditor類的外部作為NoteEditor.LinedEditText訪問屋彪。

  • 它是靜態(tài)的所宰,這意味著它不會生成允許它從父類訪問數(shù)據(jù)的所謂“合成方法”,這反過來意味著它實際上表現(xiàn)為一個單獨的類而不是與NoteEditor強烈相關的東西畜挥。 如果它們不需要從外部類訪問狀態(tài)仔粥,保持生成的類很小,并允許從其他類中輕松使用它蟹但,那么這是創(chuàng)建內(nèi)部類的更簡潔方法件炉。

  • 它擴展了EditText,這是我們在這種情況下選擇自定義的View矮湘。 完成后斟冕,新類將能夠替換正常的EditText視圖。

  1. 類初始化

與往常一樣缅阳,超級首先被稱為磕蛇。 此外,這不是默認構(gòu)造函數(shù)十办,而是參數(shù)化構(gòu)造函數(shù)秀撇。 當EditTextXML布局文件中膨脹時,會使用這些參數(shù)創(chuàng)建EditText向族,因此呵燕,我們的構(gòu)造函數(shù)需要同時接受它們并將它們傳遞給超類構(gòu)造函數(shù)。

  1. 重寫方法

此示例僅覆蓋一個方法onDraw()件相,但您可能需要在創(chuàng)建自己的自定義組件時覆蓋其他方法再扭。

對于此示例氧苍,重寫onDraw()方法允許我們在EditText視圖畫布上繪制藍線(畫布將傳遞到重寫的onDraw()方法)。 在方法結(jié)束之前調(diào)用super.onDraw()方法泛范。 應該調(diào)用超類方法让虐,在這種情況下,我們在繪制了要包含的行之后最后執(zhí)行它罢荡。

  1. 使用自定義組件

我們現(xiàn)在有自定義組件赡突,但我們?nèi)绾问褂盟?在NotePad示例中,自定義組件直接從聲明性布局中使用区赵,因此請查看res / layout文件夾中的note_editor.xml惭缰。

<view xmlns:android="http://schemas.android.com/apk/res/android"
    class="com.example.android.notepad.NoteEditor$LinedEditText"
    android:id="@+id/note"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:padding="5dp"
    android:scrollbars="vertical"
    android:fadingEdge="vertical"
    android:gravity="top"
    android:textSize="22sp"
    android:capitalize="sentences"
/>
  • 自定義組件在XML中創(chuàng)建為通用視圖,并使用完整包指定類笼才。 另請注意漱受,我們定義的內(nèi)部類是使用NoteEditor $ LinedEditText表示法引用的,這是一種在Java編程語言中引用內(nèi)部類的標準方法患整。

如果未將自定義View組件定義為內(nèi)部類拜效,則可以使用XML元素名稱聲明View組件喷众,并排除class屬性各谚。 例如:

 <com.example.android.notepad.LinedEditText   
id="@+id/note"  
... />

請注意,LinedEditText類現(xiàn)在是一個單獨的類文件到千。 當類嵌套在NoteEditor類中時昌渤,此技術將不起作用。

  • 定義中的其他屬性和參數(shù)是傳遞給自定義組件構(gòu)造函數(shù)的屬性和參數(shù)憔四,然后傳遞給EditText構(gòu)造函數(shù)膀息,因此它們與用于EditText視圖的參數(shù)相同。 請注意了赵,也可以添加自己的參數(shù)潜支,我們將在下面再次討論。

這就是它的全部柿汛。 不可否認冗酿,這是一個簡單的案例,但重點是 - 創(chuàng)建自定義組件只是你需要的那么復雜络断。

更復雜的組件可能會覆蓋更多on ...方法并引入一些自己的輔助方法裁替,從根本上定制其屬性和行為。 唯一的限制是你的想象力以及你需要組件做什么貌笨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弱判,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子锥惋,更是在濱河造成了極大的恐慌昌腰,老刑警劉巖开伏,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剥哑,居然都是意外死亡硅则,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門株婴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怎虫,“玉大人,你說我怎么就攤上這事困介〈笊螅” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵座哩,是天一觀的道長徒扶。 經(jīng)常有香客問我,道長根穷,這世上最難降的妖魔是什么姜骡? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮屿良,結(jié)果婚禮上圈澈,老公的妹妹穿的比我還像新娘。我一直安慰自己尘惧,他們只是感情好康栈,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喷橙,像睡著了一般啥么。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贰逾,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天悬荣,我揣著相機與錄音,去河邊找鬼疙剑。 笑死氯迂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的核芽。 我是一名探鬼主播囚戚,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼轧简!你這毒婦竟也來了驰坊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤哮独,失蹤者是張志新(化名)和其女友劉穎拳芙,沒想到半個月后察藐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡舟扎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年分飞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睹限。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡譬猫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出羡疗,到底是詐尸還是另有隱情染服,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布叨恨,位于F島的核電站柳刮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏痒钝。R本人自食惡果不足惜秉颗,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望送矩。 院中可真熱鬧蚕甥,春花似錦、人聲如沸益愈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒸其。三九已至,卻和暖如春库快,著一層夾襖步出監(jiān)牢的瞬間摸袁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工义屏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留靠汁,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓闽铐,卻偏偏與公主長得像蝶怔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子兄墅,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

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