自定義View知識

1. View是什麼?
     1). View類是所有用來構建用戶界面的組件的基類
     2). ViewGroup是View的一個子類, 是各種佈局的基類, 
          它是包含其它View或ViewGroup和定義這些孩子佈局參數的容器
     3). 一個View(ViewGroup)佔用屏幕上的一個矩形區域, 它負責界面的繪製和事件處理
     4). 手機屏幕上所有看得見摸得着的都是View(包括ViewGroup)

2. View的分類
    1).  不能包含子View的View
          TextView: 顯示文本(它也可以帶圖片)
          Button: 按鈕
          ImageView: 顯示圖片
    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. 關於View和ViewGroup
     1). 整個界面只會有一個根View
          a. 得到它: window.getDecorview()      PhoneWindow$decorView
          b. 本質類型: FrameLayout
          c. setContentView()添加的視圖不是整個界面的根view       FrameLayout(id=content)  
     2). 一個View只會有一個父View(ViewGroup), 一個ViewGroup可以有多個子View
          a. 得到父視圖: view.getParent(), 可以將返回的ViewParent強轉爲指定的ViewGroup
          b. 不是所有的View都能添加子view, 只有ViewGroup及其子類才能添加

5. 區別View與Activity?
     1). Activity是四大組件中唯一能與用戶進行交互的組件
     2). Activity只是控制和管理View, 真正顯示和處理事件的是View本身來完成
     3). Activity內部有一個window對象, window對象(Phonewindow)中包含一個FramLayout類型的decorView
          在Activity中setContentView(view)實質上是將view添加到decorView中
          手機屏幕中顯示的就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);

View的生命週期過程:
     1). 創建View對象
          a. 存在2種創建的方式: 加載佈局文件創建和直接new構造方法創建
          b. 佈局文件方式的本質: 解析佈局xml, 根據標籤名創建對應的View對象, 並將標籤屬性設置到對象中
          c. 佈局文件方式: 在所有的View對象都創建好了後, 會調用onFinishInflate()
          d. 在視圖對象都創建好後, 調用onAttachedToWindow(), 表明view對象關聯到window上了
     2). 測量(多大?)
          a.方法執行: measure()--->onMeasure()--->setMeasuredDimension()
          b. measure(): 用來確定當前View的大小, 它是final的方法不能重寫, 它內部調用了onMeasure()
          c.onMeasure(): 一般重寫此方法, 根據我們的實際需求, 對View進行測量
          d. setMeasuredDimension(): onMeasure()中必須調用些方法保存當前View測試出的寬度和高度
     3). 佈局(在哪?)
          a. 方法執行: layout()--->onLayout()
          b. layout(l, t, r, b): 
               ①. 指定View的左上角點的座標和右下角點的座標
               ②. 比較原有的l,t,r,b與當前的l,t,r,b, 如果有變化了或請求重新layout, 就會調用onLayout(l,t,r,b)
               ③. 不會重寫些方法, 只會調用些方法來指定當前View在父View中的位置
          c. onLayout(changed, l, t, r, b)
               ①. 決定當前view在父ViewGroup中的位置
               ②. 在View類中只是空實現, 因爲一個View的位置是由父View來指定的
               ③. 在ViewGroup類中用來指定子View的位置, 但是abstract
                         FrameLayout
                         LinearLayout
                         RelativeLayout
               ④. LinearLayout的實現:
          判斷自身是橫屏還是豎屏?
               遍歷所有的子View, 爲它們準備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()的方式來強制重新layout
     4). 繪製(啥樣?)
          a. 方法執行: draw()--->onDraw()
          b. draw(): 
               ①. 畫一些通用的東西(如背景,滾動條等), 一般不會去重寫此方法
                    1>. Draw the background(畫背景)
                    2>. Draw view's content(畫內容)
                    3>. Draw children(畫子View)
                    4>. Draw decorations scrollbars (畫滾動條)
               ②. 如果是View, 使用onDraw(canvas)來畫界面
               ③. 如果是ViewGroup, 使用dispatchDraw(canvas)---分發給子View繪製
          c. onDraw(Canvas canvas)
               ①. 所有特定的View(比如:TextView/ImageView)都重寫了此方法來繪製自己的樣子
               ②. 主要使用Paint和Canvas來繪製
          d. 可以通過調用inValidate()postInValidate()來強制重繪
     5). 事件處理: 
          a. 相關方法: 
               onTouchEvent(MotionEvent): 觸摸事件的回調方法
               OnTouchListener--->onTouch(View v, MotionEvent event) : 觸摸事件的監聽器
          b. 事件的分發和處理過程
     6). 死亡:
          b. 相關方法: onDetachedFromWindow()
          c. 當Activity退出或當前View被移除觸發

總結: 
creation
     二種方式 : new 構造方法(context) ,  定義佈局文件再加載(setContentView()/View.inflate()---(context, AttributeSet))      全類名<TextView> <com.atguigu.MyTextView>
     所有View對象都創建好了--->onFinishInflate()[必須是佈局文件]--->onAttachToWindow()  --->getViewAt(int position)
measure(多大?)
     -->measure()--->onMearsure()    產生一個測量的尺寸(寬高)  --->getMearsureHeight()  getMearsureWidth()     -->onResume()
layout(在哪?)
     --->layout(l, t, r, b)--->onLayout(boolean change, l, t, r, b)
     requestLayout(): 強制重新佈局
draw(撒樣?)
     draw()--->onDraw()       
     invalidate()/postInvalidate(): 強制重繪
event deal
     onTouchEvent()
          return true;  消費事件     --->攔截事件
die
     onDetachedFromWindow()




























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章