国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

View事件機制源碼分析

antz / 1378人閱讀

摘要:當不攔截事件的時候,事件會向下分發交由它的子或進行處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。

目錄介紹

01.Android中事件分發順序

02.Activity的事件分發機制

2.1 源碼分析

2.2 點擊事件調用順序

2.3 得出結論

03.ViewGroup事件的分發機制

3.1 看一下這個案例

3.2 源碼分析

3.3 得出結論

04.View事件的分發機制

4.1 源碼分析

4.2 得出結論

4.3 驗證結論

05.思考一下

5.1 onTouch()和onTouchEvent()的區別

5.2 Touch事件的后續事件傳遞

好消息

博客筆記大匯總【16年3月到至今】,包括Java基礎及深入知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計N篇[近100萬字,陸續搬到網上],轉載請注明出處,謝謝!

鏈接地址:https://github.com/yangchong2...

如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!

View事件系列博客

01.View事件基礎

事件分發的對象是誰?事件在哪些對象間進行傳遞?事件分發過程涉及方法?事件分發機制方法說明?

02.View事件分發場景

事件分發背景描述,事件傳遞情況

03.View事件機制源碼分析

Android中事件分發順序?Activity的事件分發機制?ViewGroup事件的分發機制 ?View事件的分發機制?onTouch()和onTouchEvent()的區別?

04.View事件機制

觸摸事件,分發事件,攔截事件,三個事件機制怎么向其調用者傳遞處理結果,滑動沖突的思路及方法 ,以及具體的滑動沖突解決方案案例

05.View的滑動沖突

通過一個滑動沖突的案例,來講解外部攔截法解決滑動沖突,內部攔截法解決滑動沖突

07.View事件總結1

Android事件分發機制,View和ViewGroup分發事件,onTouch()、onTouchEvent()和onClick()執行順序,View處理事件的優先級,點擊事件傳遞過程,事件傳遞規則要點

08.View事件總結2

View滑動有哪些方法,Activity事件分發過程,Window事件分發過程,DecorView的事件分發,根View的事件分發

01.Android中事件分發順序

Android中事件分發順序:

Activity(Window) -> ViewGroup -> View

其中:

super:調用父類方法

true:消費事件,即事件不繼續往下傳遞

false:不消費事件,事件繼續往下傳遞 / 交由給父控件onTouchEvent()處理

充分理解Android分發機制,本質上是要理解:

Activity對點擊事件的分發機制

ViewGroup對點擊事件的分發機制

View對點擊事件的分發機制

02.Activity的事件分發機制 2.1 源碼分析

當一個點擊事件發生時,事件最先傳到Activity的dispatchTouchEvent()進行事件分發

具體是由Activity的Window來完成

我們來看下Activity的dispatchTouchEvent()的源碼

public boolean dispatchTouchEvent(MotionEvent ev) {
    //第一步
    //一般事件列開始都是DOWN,所以這里基本是true
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        //第二步
        onUserInteraction();
    }
    //第三步
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

第一步

一般事件列開始都是DOWN(按下按鈕),所以這里返回true,執行onUserInteraction()

第二步

先來看下onUserInteraction()源碼

public void onUserInteraction() { 
}

從源碼可以看出:

該方法為空方法

從注釋得知:當此activity在棧頂時,觸屏點擊按home,back,menu鍵等都會觸發此方法

所以onUserInteraction()主要用于屏保

第三步

Window類是抽象類,且PhoneWindow是Window類的唯一實現類

superDispatchTouchEvent(ev)是抽象方法

通過PhoneWindow類中看一下superDispatchTouchEvent()的作用

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
    //mDecor是DecorView的實例
    //DecorView是視圖的頂層view,繼承自FrameLayout,是所有界面的父類
}

接下來我們看mDecor.superDispatchTouchEvent(event):

public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
//DecorView繼承自FrameLayout
//那么它的父類就是ViewGroup
而super.dispatchTouchEvent(event)方法,其實就應該是ViewGroup的dispatchTouchEvent()

}

得出結果

執行getWindow().superDispatchTouchEvent(ev)實際上是執行了ViewGroup.dispatchTouchEvent(event)

這樣事件就從 Activity 傳遞到了 ViewGroup

2.2 點擊事件調用順序

當一個點擊事件發生時,調用順序如下

1.事件最先傳到Activity的dispatchTouchEvent()進行事件分發

2.調用Window類實現類PhoneWindow的superDispatchTouchEvent()

3.調用DecorView的superDispatchTouchEvent()

4.最終調用DecorView父類的dispatchTouchEvent(),即ViewGroup的dispatchTouchEvent()

2.3 得出結論

當一個點擊事件發生時,事件最先傳到Activity的dispatchTouchEvent()進行事件分發,最終是調用了ViewGroup的dispatchTouchEvent()方法

這樣事件就從 Activity 傳遞到了 ViewGroup

03.ViewGroup事件的分發機制 3.1 看一下這個案例

布局如下:

結果測試

只點擊Button,發現執行順序:btn1,btn2

再點擊空白處,發現執行順序:btn1,btn2,viewGroup

從上面的測試結果發現:

當點擊Button時,執行Button的onClick(),但ViewGroupLayout注冊的onTouch()不會執行

只有點擊空白區域時才會執行ViewGroupLayout的onTouch();

結論:Button的onClick()將事件消費掉了,因此事件不會再繼續向下傳遞。

3.2 源碼分析

ViewGroup的dispatchTouchEvent()源碼分析,該方法比較復雜,截取幾個重要的邏輯片段進行介紹,來解析整個分發流程。

// 發生ACTION_DOWN事件或者已經發生過ACTION_DOWN,并且將mFirstTouchTarget賦值,才進入此區域,主要功能是攔截器
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN|| mFirstTouchTarget != null) {
    //disallowIntercept:是否禁用事件攔截的功能(默認是false),即不禁用
    //可以在子View通過調用requestDisallowInterceptTouchEvent方法對這個值進行修改,不讓該View攔截事件
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    //默認情況下會進入該方法
    if (!disallowIntercept) {
        //調用攔截方法
        intercepted = onInterceptTouchEvent(ev); 
        ev.setAction(action);
    } else {
        intercepted = false;
    }
} else {
    // 當沒有觸摸targets,且不是down事件時,開始持續攔截觸摸。
    intercepted = true;
}

這一段的內容主要是為判斷是否攔截。如果當前事件的MotionEvent.ACTION_DOWN,則進入判斷,調用ViewGroup onInterceptTouchEvent()方法的值,判斷是否攔截。如果mFirstTouchTarget != null,即已經發生過MotionEvent.ACTION_DOWN,并且該事件已經有ViewGroup的子View進行處理了,那么也進入判斷,調用ViewGroup onInterceptTouchEvent()方法的值,判斷是否攔截。如果不是以上兩種情況,即已經是MOVE或UP事件了,并且之前的事件沒有對象進行處理,則設置成true,開始攔截接下來的所有事件。這也就解釋了如果子View的onTouchEvent()方法返回false,那么接下來的一些列事件都不會交給他處理。如果VieGroup的onInterceptTouchEvent()第一次執行為true,則mFirstTouchTarget = null,則也會使得接下來不會調用onInterceptTouchEvent(),直接將攔截設置為true。

當ViewGroup不攔截事件的時候,事件會向下分發交由它的子View或ViewGroup進行處理。

  /* 從最底層的父視圖開始遍歷,
   ** 找尋newTouchTarget,即上面的mFirstTouchTarget
   ** 如果已經存在找尋newTouchTarget,說明正在接收觸摸事件,則跳出循環。
    */
for (int i = childrenCount - 1; i >= 0; i--) {
  final int childIndex = customOrder
    ? getChildDrawingOrder(childrenCount, i) : i;
  final View child = (preorderedList == null)
    ? children[childIndex] : preorderedList.get(childIndex);

  // 如果當前視圖無法獲取用戶焦點,則跳過本次循環
  if (childWithAccessibilityFocus != null) {
     if (childWithAccessibilityFocus != child) {
        continue;
     }
     childWithAccessibilityFocus = null;
     i = childrenCount - 1;
  }
  //如果view不可見,或者觸摸的坐標點不在view的范圍內,則跳過本次循環
  if (!canViewReceivePointerEvents(child) 
      || !isTransformedTouchPointInView(x, y, child, null)) {
    ev.setTargetAccessibilityFocus(false);
    continue;
    }

   newTouchTarget = getTouchTarget(child);
   // 已經開始接收觸摸事件,并退出整個循環。
   if (newTouchTarget != null) {
       newTouchTarget.pointerIdBits |= idBitsToAssign;
       break;
    }

    //重置取消或抬起標志位
    //如果觸摸位置在child的區域內,則把事件分發給子View或ViewGroup
    if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
        // 獲取TouchDown的時間點
        mLastTouchDownTime = ev.getDownTime();
        // 獲取TouchDown的Index
        if (preorderedList != null) {
           for (int j = 0; j < childrenCount; j++) {
               if (children[childIndex] == mChildren[j]) {
                    mLastTouchDownIndex = j;
                    break;
                }
           }
         } else {
                 mLastTouchDownIndex = childIndex;
                }

      //獲取TouchDown的x,y坐標
      mLastTouchDownX = ev.getX();
      mLastTouchDownY = ev.getY();
      //添加TouchTarget,則mFirstTouchTarget != null。
      newTouchTarget = addTouchTarget(child, idBitsToAssign);
      //表示以及分發給NewTouchTarget
      alreadyDispatchedToNewTouchTarget = true;
      break;
}

dispatchTransformedTouchEvent()方法實際就是調用子元素的dispatchTouchEvent()方法。

其中dispatchTransformedTouchEvent()方法的重要邏輯如下:

if (child == null) {
    handled = super.dispatchTouchEvent(event);
} else {
    handled = child.dispatchTouchEvent(event);
}

由于其中傳遞的child不為空,所以就會調用子元素的dispatchTouchEvent()。如果子元素的dispatchTouchEvent()方法返回true,那么mFirstTouchTarget就會被賦值,同時跳出for循環。

//添加TouchTarget,則mFirstTouchTarget != null。
newTouchTarget = addTouchTarget(child, idBitsToAssign);
 //表示以及分發給NewTouchTarget
 alreadyDispatchedToNewTouchTarget = true;

其中在addTouchTarget(child, idBitsToAssign);內部完成mFirstTouchTarget被賦值。如果mFirstTouchTarget為空,將會讓ViewGroup默認攔截所有操作。如果遍歷所有子View或ViewGroup,都沒有消費事件。ViewGroup會自己處理事件。

3.3 得出結論

Android事件分發是先傳遞到ViewGroup,再由ViewGroup傳遞到View

在ViewGroup中通過onInterceptTouchEvent()對事件傳遞進行攔截

1.onInterceptTouchEvent方法返回true代表攔截事件,即不允許事件繼續向子View傳遞;

2.返回false代表不攔截事件,即允許事件繼續向子View傳遞;(默認返回false)

3.子View中如果將傳遞的事件消費掉,ViewGroup中將無法接收到任何事件。

04.View事件的分發機制 4.1 源碼分析

View中dispatchTouchEvent()的源碼分析

public boolean dispatchTouchEvent(MotionEvent event) {  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return true;  
    }  
    return onTouchEvent(event);  
}

從上面可以看出:

只有以下三個條件都為真,dispatchTouchEvent()才返回true;否則執行onTouchEvent(event)方法

第一個條件:mOnTouchListener != null;
第二個條件:(mViewFlags & ENABLED_MASK) == ENABLED;
第三個條件:mOnTouchListener.onTouch(this, event);

下面,我們來看看下這三個判斷條件:

第一個條件:mOnTouchListener!= null

//mOnTouchListener是在View類下setOnTouchListener方法里賦值的
public void setOnTouchListener(OnTouchListener l) { 

//即只要我們給控件注冊了Touch事件,mOnTouchListener就一定被賦值(不為空)
    mOnTouchListener = l;  
}

第二個條件:(mViewFlags & ENABLED_MASK) == ENABLED

該條件是判斷當前點擊的控件是否enable

由于很多View默認是enable的,因此該條件恒定為true

第三個條件:mOnTouchListener.onTouch(this, event)

回調控件注冊Touch事件時的onTouch方法

//手動調用設置
button.setOnTouchListener(new OnTouchListener() {  
    @Override  
    public boolean onTouch(View v, MotionEvent event) {  
        return false;  
    }  
});

如果在onTouch方法返回true,就會讓上述三個條件全部成立,從而整個方法直接返回true。

如果在onTouch方法里返回false,就會去執行onTouchEvent(event)方法。

接下來,我們繼續看:onTouchEvent(event)的源碼分析

public boolean onTouchEvent(MotionEvent event) {  
    final int viewFlags = mViewFlags;  
    if ((viewFlags & ENABLED_MASK) == DISABLED) {  
        // A disabled view that is clickable still consumes the touch  
        // events, it just doesn"t respond to them.  
        return (((viewFlags & CLICKABLE) == CLICKABLE ||  
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));  
    }  
    if (mTouchDelegate != null) {  
        if (mTouchDelegate.onTouchEvent(event)) {  
            return true;  
        }  
    }  
     //如果該控件是可以點擊的就會進入到下兩行的switch判斷中去;

    if (((viewFlags & CLICKABLE) == CLICKABLE ||  
            (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {  
    //如果當前的事件是抬起手指,則會進入到MotionEvent.ACTION_UP這個case當中。

        switch (event.getAction()) {  
            case MotionEvent.ACTION_UP:  
                boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;  
               // 在經過種種判斷之后,會執行到關注點1的performClick()方法。
               //請往下看關注點1
                if ((mPrivateFlags & PRESSED) != 0 || prepressed) {  
                    // take focus if we don"t have it already and we should in  
                    // touch mode.  
                    boolean focusTaken = false;  
                    if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {  
                        focusTaken = requestFocus();  
                    }  
                    if (!mHasPerformedLongPress) {  
                        // This is a tap, so remove the longpress check  
                        removeLongPressCallback();  
                        // Only perform take click actions if we were in the pressed state  
                        if (!focusTaken) {  
                            // Use a Runnable and post this rather than calling  
                            // performClick directly. This lets other visual state  
                            // of the view update before click actions start.  
                            if (mPerformClick == null) {  
                                mPerformClick = new PerformClick();  
                            }  
                            if (!post(mPerformClick)) {  
            //關注點1
            //請往下看performClick()的源碼分析
                                performClick();  
                            }  
                        }  
                    }  
                    if (mUnsetPressedState == null) {  
                        mUnsetPressedState = new UnsetPressedState();  
                    }  
                    if (prepressed) {  
                        mPrivateFlags |= PRESSED;  
                        refreshDrawableState();  
                        postDelayed(mUnsetPressedState,  
                                ViewConfiguration.getPressedStateDuration());  
                    } else if (!post(mUnsetPressedState)) {  
                        // If the post failed, unpress right now  
                        mUnsetPressedState.run();  
                    }  
                    removeTapCallback();  
                }  
                break;  
            case MotionEvent.ACTION_DOWN:  
                if (mPendingCheckForTap == null) {  
                    mPendingCheckForTap = new CheckForTap();  
                }  
                mPrivateFlags |= PREPRESSED;  
                mHasPerformedLongPress = false;  
                postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());  
                break;  
            case MotionEvent.ACTION_CANCEL:  
                mPrivateFlags &= ~PRESSED;  
                refreshDrawableState();  
                removeTapCallback();  
                break;  
            case MotionEvent.ACTION_MOVE:  
                final int x = (int) event.getX();  
                final int y = (int) event.getY();  
                // Be lenient about moving outside of buttons  
                int slop = mTouchSlop;  
                if ((x < 0 - slop) || (x >= getWidth() + slop) ||  
                        (y < 0 - slop) || (y >= getHeight() + slop)) {  
                    // Outside button  
                    removeTapCallback();  
                    if ((mPrivateFlags & PRESSED) != 0) {  
                        // Remove any future long press/tap checks  
                        removeLongPressCallback();  
                        // Need to switch from pressed to not pressed  
                        mPrivateFlags &= ~PRESSED;  
                        refreshDrawableState();  
                    }  
                }  
                break;  
        }  
//如果該控件是可以點擊的,就一定會返回true
        return true;  
    }  
//如果該控件是不可以點擊的,就一定會返回false
    return false;  
}

關注點1:

performClick()的源碼分析

public boolean performClick() {  
    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);  

    if (mOnClickListener != null) {  
        playSoundEffect(SoundEffectConstants.CLICK);  
        mOnClickListener.onClick(this);  
        return true;  
    }  
    return false;  
}

只要mOnClickListener不為null,就會去調用onClick方法;

那么,mOnClickListener又是在哪里賦值的呢?請繼續看:

public void setOnClickListener(OnClickListener l) {  
    if (!isClickable()) {  
        setClickable(true);  
    }  
    mOnClickListener = l;  
}

當我們通過調用setOnClickListener方法來給控件注冊一個點擊事件時,就會給mOnClickListener賦值(不為空),即會回調onClick()。

4.2 得出結論

1.onTouch()的執行高于onClick()

2.每當控件被點擊時:

如果在回調onTouch()里返回false,就會讓dispatchTouchEvent方法返回false,那么就會執行onTouchEvent();如果回調了setOnClickListener()來給控件注冊點擊事件的話,最后會在performClick()方法里回調onClick()。

onTouch()返回false(該事件沒被onTouch()消費掉) = 執行onTouchEvent() = 執行OnClick()

如果在回調onTouch()里返回true,就會讓dispatchTouchEvent方法返回true,那么將不會執行onTouchEvent(),即onClick()也不會執行;

onTouch()返回true(該事件被onTouch()消費掉) = dispatchTouchEvent()返回true(不會再繼續向下傳遞) = 不會執行onTouchEvent() = 不會執行OnClick()

4.3 驗證結論

在回調onTouch()里返回true

TextView textView = findViewById(R.id.tv_13);
//設置OnTouchListener()
textView.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("小楊逗比","執行了onTouch(), 動作是:" + event.getAction());
        return true;
    }
});
//設置OnClickListener
textView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("小楊逗比","執行了onClick()");
    }
});

打印日志如下所示

注意action為0是ACTION_DOWN,為2是ACTION_MOVE,為1是ACTION_UP。

2019-04-04 13:37:58.301 13616-13616/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:0
2019-04-04 13:37:58.315 13616-13616/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:2
2019-04-04 13:37:58.405 13616-13616/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:2
2019-04-04 13:37:58.408 13616-13616/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:1

在回調onTouch()里返回false

打印結果如下所示

2019-04-04 13:41:26.961 14006-14006/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:0
2019-04-04 13:41:26.978 14006-14006/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:2
2019-04-04 13:41:27.072 14006-14006/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:2
2019-04-04 13:41:27.074 14006-14006/org.yczbj.ycrefreshview D/小楊逗比: 執行了onTouch(), 動作是:1
2019-04-04 13:41:27.076 14006-14006/org.yczbj.ycrefreshview D/小楊逗比: 執行了onClick()

總結:onTouch()返回true就認為該事件被onTouch()消費掉,因而不會再繼續向下傳遞,即不會執行OnClick()。

05.思考一下 5.1 onTouch()和onTouchEvent()的區別

這兩個方法都是在View的dispatchTouchEvent中調用,但onTouch優先于onTouchEvent執行。

如果在onTouch方法中返回true將事件消費掉,onTouchEvent()將不會再執行。

特別注意:請看下面代碼

//&&為短路與,即如果前面條件為false,將不再往下執行
//所以,onTouch能夠得到執行需要兩個前提條件:
//1. mOnTouchListener的值不能為空
//2. 當前點擊的控件必須是enable的。
mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
        mOnTouchListener.onTouch(this, event)

因此如果你有一個控件是非enable的,那么給它注冊onTouch事件將永遠得不到執行。對于這一類控件,如果我們想要監聽它的touch事件,就必須通過在該控件中重寫onTouchEvent方法來實現。

5.2 Touch事件的后續事件(MOVE、UP)層級傳遞

如果給控件注冊了Touch事件,每次點擊都會觸發一系列action事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP等)

當dispatchTouchEvent在進行事件分發的時候,只有前一個事件(如ACTION_DOWN)返回true,才會收到后一個事件(ACTION_MOVE和ACTION_UP)

即如果在執行ACTION_DOWN時返回false,后面一系列的ACTION_MOVE和ACTION_UP事件都不會執行

從上面對事件分發機制分析知:

dispatchTouchEvent()和 onTouchEvent()消費事件、終結事件傳遞(返回true)

而onInterceptTouchEvent 并不能消費事件,它相當于是一個分叉口起到分流導流的作用,對后續的ACTION_MOVE和ACTION_UP事件接收起到非常大的作用

請記住:接收了ACTION_DOWN事件的函數不一定能收到后續事件(ACTION_MOVE、ACTION_UP)

這里給出ACTION_MOVE和ACTION_UP事件的傳遞結論

如果在某個對象(Activity、ViewGroup、View)的dispatchTouchEvent()消費事件(返回true),那么收到ACTION_DOWN的函數也能收到ACTION_MOVE和ACTION_UP

如果在某個對象(Activity、ViewGroup、View)的onTouchEvent()消費事件(返回true),那么ACTION_MOVE和ACTION_UP的事件從上往下傳到這個View后就不再往下傳遞了,而直接傳給自己的onTouchEvent()并結束本次事件傳遞過程。

其他介紹 01.關于博客匯總鏈接

1.技術博客匯總

2.開源項目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關于我的博客

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡書:http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽書:http://www.ximalaya.com/zhubo...

開源中國:https://my.oschina.net/zbj161...

泡在網上的日子:http://www.jcodecraeer.com/me...

郵箱:yangchong211@163.com

segmentfault頭條:https://segmentfault.com/u/xi...

掘金:https://juejin.im/user/593943...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77846.html

相關文章

  • View事件機制分析

    摘要:注意,事件分發是向下傳遞的,也就是父到子的順序。事件分發機制的本質是要解決,點擊事件由哪個對象發出,經過哪些對象,最終達到哪個對象并最終得到處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。 目錄介紹 01.Android中事件分發順序 1.1 事件分發的對象是誰 1.2 事件分發的本質 1.3 事件在哪些對象間進行傳遞 1.4 事件分發過程涉及方法 1.5 Androi...

    bergwhite 評論0 收藏0
  • Activity、Window、View三者關系

    摘要:在代碼中的直接應用是或者是。就像一個控制器,統籌視圖的添加與顯示,以及通過其他回調方法,來與以及進行交互。創建需要通過創建,通過將加載其中,并將交給,進行視圖繪制以及其他交互。創建機制分析實例的創建中執行,從而生成了的實例。 目錄介紹 01.Window,View,子Window 02.什么是Activity 03.什么是Window 04.什么是DecorView 05.什么是Vi...

    Cristic 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<