Android-控件框架、View的分發(fā)機(jī)制和自定義View

看了一天的書,再在網(wǎng)上搜了一些知識(shí)點(diǎn),對(duì)View的一些知識(shí)點(diǎn)還是有一些不太清晰的地方,做了一些筆記

控件框架

控件分成兩類
  • ViewGroup控件
  • View控件
    ViewGroup可以作為父控件包含多個(gè)View,并管理。上層控件負(fù)責(zé)下層子控件的測(cè)量與繪制,并傳遞交互事件。頂層是一個(gè)ViewParent對(duì)象,所有交互管理事件都由它來統(tǒng)一調(diào)度和分配,從而可以對(duì)整個(gè)視圖進(jìn)行整體控制。

布局

在Activity中使用setContentView()方法來設(shè)置一個(gè)布局,只有調(diào)用該方法布局內(nèi)容才會(huì)顯示出來。
UI界面架構(gòu)圖:

DecorView作為窗口界面的頂層視圖,封裝了一些窗口操作的通用方法。里面所有View的監(jiān)聽事件,都通過WindowManagerService來接收,并通過Activity對(duì)象來回調(diào)相應(yīng)的Listener。

  • TitleView是標(biāo)題欄。
  • ContentView是一個(gè)Framelayout。
  • 設(shè)置requestWindowFeature(Window.FEATURE_NO_TITLE)來設(shè)置隱藏標(biāo)題欄全屏顯示,一定要在setContentView()方法之前調(diào)用才能生效。

在onCreat()方法中調(diào)用setContentView()后,ActivityManagerService會(huì)回調(diào)onResume()方法,此時(shí)系統(tǒng)才會(huì)把整個(gè)DecorView添加進(jìn)PhoneWindow中,并讓其顯示出來,從而最終完成界面的繪制。


View的位置參數(shù)

View的位置由top、left、right、bottom決定,分別對(duì)應(yīng)左上角縱坐標(biāo)、左上角橫坐標(biāo)、右下角橫坐標(biāo)、右下角縱坐標(biāo)。坐標(biāo)是相對(duì)與父容器來說。
從3.0開始,增加了幾個(gè)參數(shù)
x、y、translationX、translationY,分別對(duì)應(yīng)View左上角坐標(biāo)和View的左上角相對(duì)于父容器的偏移量。
x=left+translationX
y=top+translationY
View在平移的過程中,top和left表示的是原始左上角的位置信息,其值不會(huì)發(fā)生改變,此時(shí)改變的是x、y、translationX、translationY。(這就是為什么View的動(dòng)畫執(zhí)行后真身還在原來的地方的原因)


View的事件體系

幾個(gè)對(duì)象
  • MotionEvent:手指接觸屏幕后所產(chǎn)生的一系列事件
    • ACTION_DOWN:手指剛接觸屏幕
    • ACTION_MOVE:手指在屏幕上移動(dòng)
    • ACTION_UP:手指從屏幕松開的一瞬間
    • 幾個(gè)方法:
      • getX/getY:返回相對(duì)于當(dāng)前View左上角的x、y坐標(biāo)
      • getRawX/getRawY:返回相對(duì)于手機(jī)屏幕左上角的x、y坐標(biāo)
  • TouchSlop:是系統(tǒng)所能識(shí)別出的被認(rèn)為是滑動(dòng)的最小距離,是一個(gè)常量,和設(shè)備有關(guān),不同設(shè)備可能不同
    • 獲取這個(gè)常量:ViewConfiguration.get(getContext()).getScaledTouchSlop()
  • VelocityTracker:速度追蹤,用于追蹤手指在滑動(dòng)過程的速度,包括水平和豎直方向的速度。
//在View的onTouchEvent方法中追蹤當(dāng)前單擊事件的速度
VelocityTracker velocityTracker=VelocityTracker.obtain();
velocityTracker.addMovement(event);
//想知道當(dāng)前的滑動(dòng)速度
velocityTracker.computeCurrentVelocity(1000);//獲取速度必須先計(jì)算速度,這里指的是1000毫秒內(nèi)的速度
int xVelocityTracker=(int)velocityTracker.getXVelocity();
int yVelocityTracker=(int)velocityTracker.getYVelocity();
//往右滑和往下滑速度是正值,反之則是負(fù)值。
  • GestureDetector:手勢(shì)檢測(cè)
    • onSingleTapUp:?jiǎn)螕?/li>
    • onFling:快速滑動(dòng)
    • onScroll:滑動(dòng)
    • onLongPress:長(zhǎng)按
    • onDoubleTap:雙擊
//首先創(chuàng)建一個(gè)GestureDetector對(duì)象并實(shí)現(xiàn)OnGestureListener或者OnDoubleTapListener接口
GestureDetector mGestureDetector=new GestureDetector(this);
//解決長(zhǎng)按屏幕后無法拖動(dòng)的現(xiàn)象
//托管View的onTouchEvent方法,在方法里添加
boolean consume=mGestureDetector.onTouchEvent(event);
return consume;
  • Scroller:彈性滑動(dòng)對(duì)象.Scroller本身無法讓View彈性滑動(dòng),需要VIew和computeScroll配合使用。
//這個(gè)是模版
Scroller scroller=new Scroller(context);
private void smoothScrollTo(int destX,int destY){
    int scrollX=getScrollX();
    int deltaX=destX-scrollX;//滑動(dòng)的距離
    scroller.startScroll(scrollX,0,deltaX,0,1000);
    invalidate();//重繪
}
@Override
public void computeScroll(){//重繪會(huì)調(diào)用這個(gè)方法,是空實(shí)現(xiàn),由我們來實(shí)現(xiàn)
    if(scroller.computeScrollOffset()){//根據(jù)時(shí)間的流逝和剩下要滑動(dòng)的距離計(jì)算currX的和currY的值,返回true代表滑動(dòng)未完成
        scrollerTo(scroller.getCurrX(),scroller.getCurrY());
        postInvalidate();//滑動(dòng)未完成,繼續(xù)重繪
    }
}

View的滑動(dòng)
  • 使用scrollTo/scrollBy
  • 使用動(dòng)畫
  • 改變布局參數(shù)

View的事件分發(fā)機(jī)制
  • 思維導(dǎo)圖
View的事件分發(fā)機(jī)制思維導(dǎo)圖
  • 過程邏輯


    View的事件分發(fā)機(jī)制過程邏輯

自定義View

  • 思維導(dǎo)圖


    自定義View思維導(dǎo)圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容