溫故而知新件豌,系統(tǒng)整理一下疮方。
1. View是什么?
1). View類是所有用來構(gòu)建用戶界面的組件的基類
2). ViewGroup是View的一個子類, 是各種布局的基類,它是包含其它View或ViewGroup和定義這些孩子布局參數(shù)的容器
3). 一個View(ViewGroup)占用屏幕上的一個矩形區(qū)域, 它負(fù)責(zé)界面的繪制和事件處理
4). 手機(jī)屏幕上所有看得見摸得著的都是View(包括ViewGroup)
2. View的分類
1). 不能包含子View的View: 一般的View
TextView Button ImageView EditText/RadioButton/Checkbox
2). 可以包含子View的View: ViewGroup
FrameLayout RelativeLayout LinearLayout ScrollView ListView GridView
3. ViewGroup
1). ViewGroup extends View implements ViewParent, ViewManager
2). ViewManager: 用來添加、刪除茧彤、更新布局
addView(View v)
removeView(View v)
updateViewLayout(View v)
3). ViewParent: 提供了一系列操作子View的方法
4. 關(guān)于View和ViewGroup
1). 整個界面只會有一個根View
a. 得到它: window.getDecorview() PhoneWindow$decorView
b. 本質(zhì)類型: FrameLayout
c. setContentView()添加的視圖不是整個界面的根view FrameLayout(id=content)
2). 一個View只會有一個父View(ViewGroup), 一個ViewGroup可以有多個子View
a. 得到父視圖: view.getParent(), 可以將返回的ViewParent強(qiáng)轉(zhuǎn)為指定的ViewGroup
b. 不是所有的View都能添加子view, 只有ViewGroup及其子類才能添加
5. 區(qū)別View與Activity?
1). Activity是四大組件中唯一能與用戶進(jìn)行直接交互的組件
2). Activity只是控制和管理View, 真正顯示和處理事件的是View本身來完成
3). Activity內(nèi)部有一個window對象, window對象(Phonewindow)中包含一個FramLayout類型的decorView
在Activity中setContentView(view)實(shí)質(zhì)上是將view添加到decorView中
手機(jī)屏幕中顯示的根布局就是decorView
6. 顯示ContentView的3種方式:
1). setContentView(R.layout.activity_main);
2). View view = View.inflate(this, R.layout.activity_main, null);
setContentView(view);
3). MyTextView tv = new MyTextView(this);
setContentView(tv);
7. View的生命周期過程:
1). 創(chuàng)建View對象
a. 存在2種創(chuàng)建的方式: 加載布局文件創(chuàng)建和直接new構(gòu)造方法創(chuàng)建
b. 布局文件方式的本質(zhì): 解析布局xml, 根據(jù)標(biāo)簽名創(chuàng)建對應(yīng)的View對象, 并將標(biāo)簽屬性設(shè)置到對象中(構(gòu)造方法)
c. 布局文件方式: 在所有的View對象都創(chuàng)建好了后, 會調(diào)用onFinishInflate()
d. 在視圖對象都創(chuàng)建好后, 調(diào)用onAttachedToWindow(), 表明view對象關(guān)聯(lián)到window上了
2). 測量(多大?)
a.方法執(zhí)行: measure()--->onMeasure()--->setMeasuredDimension()
b. measure(): 用來確定當(dāng)前View的大小, 它是final的方法不能重寫, 它內(nèi)部調(diào)用了onMeasure()
c.onMeasure(): 一般重寫此方法, 根據(jù)我們的實(shí)際需求, 對View進(jìn)行測量, 并保存寬高
d. setMeasuredDimension(): onMeasure()中必須調(diào)用些方法保存當(dāng)前View測試出的寬度和高度
3). 布局(在哪?)
a. 方法執(zhí)行: layout()--->onLayout()
b. layout(l, t, r, b):
①. 指定View的左上角點(diǎn)的坐標(biāo)和右下角點(diǎn)的坐標(biāo)
②. 比較原有的l,t,r,b與當(dāng)前的l,t,r,b, 如果有變化了或請求重新layout, 就會調(diào)用onLayout(l,t,r,b)
③. 不會重寫些方法, 只會調(diào)用些方法來指定當(dāng)前View在父View中的位置
c. onLayout(changed, l, t, r, b)
①. 決定當(dāng)前view在父ViewGroup中的位置
②. 在View類中只是空實(shí)現(xiàn), View還不知道在此方法中做什么工作, 需要子View來去重寫此方法實(shí)現(xiàn)所需要的
③. 在ViewGroup類中用來指定子View的位置, 但是abstract
FrameLayout
LinearLayout
RelativeLayout
④. LinearLayout的實(shí)現(xiàn):
判斷自身是橫屏還是豎屏? 遍歷所有的子View, 為它們準(zhǔn)備l,t,r,b 如果是垂直: A (0,0,width1,height1), B (0,height1,width2,height1+height2), C (0,height1+height2,width3,height1+height2+height3) 如果是水平: (0,0,width1,height1), (height1,0,height1+width2,height2), (height1+height2,0,height1+height2+width3,height3)
d. 可以通過requestLayout()的方式來強(qiáng)制重新layout
4). 繪制(啥樣?)
a. 方法執(zhí)行: draw()--->onDraw()
b. draw():
①. 畫一些通用的東西(如背景,滾動條等), 一般不會去重寫此方法
1>. Draw the background(畫背景)
2>. Draw view's content(畫內(nèi)容)
3>. Draw children(畫子View)
4>. Draw decorations scrollbars (畫滾動條)
②. 如果是View, 使用onDraw(canvas)來畫界面
③. 如果是ViewGroup, 使用dispatchDraw(canvas)---分發(fā)給子View繪制
c. onDraw(Canvas canvas)
①. 所有特定的View(比如:TextView/ImageView)都重寫了此方法來繪制自己的樣子
②. 主要使用Paint和Canvas來繪制
d. 可以通過調(diào)用inValidate()或postInValidate()來強(qiáng)制重繪
5). 事件處理:
a. 相關(guān)方法:
onTouchEvent(MotionEvent): 觸摸事件的回調(diào)方法
OnTouchListener--->onTouch(View v, MotionEvent event) : 觸摸事件的監(jiān)聽器
b. 事件的分發(fā)和處理過程
6). 死亡:
b. 相關(guān)方法: onDetachedFromWindow()
c. 當(dāng)Activity退出或當(dāng)前View被移除觸發(fā)
8. 總結(jié):
creation
二種方式 : new 構(gòu)造方法(context) , 定義布局文件再加載(setContentView()/View.inflate()---(context, AttributeSet))
全類名<TextView> <com.atguigu.MyTextView>
所有View對象都創(chuàng)建好了--->onFinishInflate()[必須是布局文件]--->onAttachToWindow() --->getViewAt(int position)
measure(多大?)
-->measure()--->onMearsure() 產(chǎn)生一個測量的尺寸(寬高) --->getMearsureHeight() getMearsureWidth() -->onResume()
layout(在哪?)
--->layout(l, t, r, b)--->onLayout(boolean change, l, t, r, b)
requestLayout(): 強(qiáng)制重新布局
draw(撒樣?)
draw()--->onDraw()
invalidate()/postInvalidate(): 強(qiáng)制重繪
event deal
onTouchEvent()
return true; 消費(fèi)事件 --->攔截事件
die
onDetachedFromWindow()
------相關(guān)資料推薦
自定義View骡显,有這一篇就夠了
Android自定義控件,你們是如何系統(tǒng)學(xué)習(xí)的
Android中View繪制流程以及invalidate()等相關(guān)方法分析
Android 自定義控件實(shí)現(xiàn)刮刮卡效果 真的就只是刮刮卡么
Android自定義軟鍵盤的實(shí)現(xiàn)