簡體   English   中英

如何在子視圖組和父視圖組觸摸事件之間變化

[英]How to vary between child and parent view group touch events

我決定發布這個問題並回答這個問題的評論
如何處理子視圖中的點擊,以及父視圖組中的觸摸?

我將在此處粘貼評論:

假設我只想覆蓋觸摸事件來處理一些孩子,我可以在這個函數中做什么才能讓它工作? 我的意思是,對於一些孩子來說,它會像往常一樣工作,而對於一些孩子來說,父視圖將決定他們是否會得到觸摸事件。

所以問題是:如何防止父onTouchEvent()覆蓋某些子元素的onTouchEvent() ,同時讓它覆蓋其他子元素的那些?

  1. 嵌套視圖組的onTouchEvents()可以由boolean onInterceptTouchEvent管理。

OnInterceptTouchEvent的默認值為 false。

在孩子之前收到父母的onTouchEvent 如果OnInterceptTouchEvent返回 false,它會將運動事件沿鏈向下發送到孩子的OnTouchEvent處理程序。 如果它返回 true,則父級將處理觸摸事件。

然而,有時我們希望一些子元素管理OnTouchEvent而一些子元素由父視圖(或可能是父視圖的父視圖)管理。

這可以通過多種方式進行管理。

  1. 保護子元素免受父元素OnInterceptTouchEvent一種方法是實現requestDisallowInterceptTouchEvent

public void requestDisallowInterceptTouchEvent (boolean disallowIntercept)

如果元素啟用了事件處理程序,這將阻止任何父視圖管理此元素的OnTouchEvent

  1. 如果OnInterceptTouchEvent為 false,則將評估子元素的OnTouchEvent 如果子元素中有處理各種觸摸事件的方法,則禁用的任何相關事件處理程序都會將 OnTouchEvent 返回給父元素。

這個答案:
https://stackoverflow.com/a/13540006/3956566很好地展示了觸摸事件的傳播方式:
parent -> child|parent -> child|parent -> child views.

  1. 另一種方法是從父對象的OnInterceptTouchEvent返回不同的值。

此示例取自 在 ViewGroup 中管理觸摸事件,並演示了如何在用戶滾動時攔截孩子的OnTouchEvent

4a.

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    /*
     * This method JUST determines whether we want to intercept the motion.
     * If we return true, onTouchEvent will be called and we do the actual
     * scrolling there.
     */


    final int action = MotionEventCompat.getActionMasked(ev);

    // Always handle the case of the touch gesture being complete.
    if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
        // Release the scroll.
        mIsScrolling = false;
        return false; // Do not intercept touch event, let the child handle it
    }

    switch (action) {
        case MotionEvent.ACTION_MOVE: {
            if (mIsScrolling) {
                // We're currently scrolling, so yes, intercept the 
                // touch event!
                return true;
            }

            // If the user has dragged her finger horizontally more than 
            // the touch slop, start the scroll

            // left as an exercise for the reader
            final int xDiff = calculateDistanceX(ev); 

            // Touch slop should be calculated using ViewConfiguration 
            // constants.
            if (xDiff > mTouchSlop) { 
                // Start scrolling!
                mIsScrolling = true;
                return true;
            }
            break;
        }
        ...
    }

    // In general, we don't want to intercept touch events. They should be 
    // handled by the child view.
    return false;
}

編輯:回答評論。
這是同一鏈接中的一些代碼,顯示了如何在元素周圍創建矩形的參數:
4b.

// The hit rectangle for the ImageButton
myButton.getHitRect(delegateArea);

// Extend the touch area of the ImageButton beyond its bounds
// on the right and bottom.
delegateArea.right += 100;
delegateArea.bottom += 100;

// Instantiate a TouchDelegate.
// "delegateArea" is the bounds in local coordinates of 
// the containing view to be mapped to the delegate view.
// "myButton" is the child view that should receive motion
// events.
TouchDelegate touchDelegate = new TouchDelegate(delegateArea, myButton);

// Sets the TouchDelegate on the parent view, such that touches 
// within the touch delegate bounds are routed to the child.
if (View.class.isInstance(myButton.getParent())) {
    ((View) myButton.getParent()).setTouchDelegate(touchDelegate);
}

讓我們修改這個問題。

你碰巧有一個有一群孩子的 ViewGroup。 您想攔截此 ViewGroup 中所有內容的觸摸事件,但有一些孩子除外。

很長一段時間以來,我一直在尋找同一個問題的答案。 沒有設法找到任何合理的東西,因此我自己提出了以下解決方案。

以下代碼片段概述了 ViewGroup 的相關代碼,該代碼攔截所有觸摸,但來自恰好具有特殊標記集的視圖的除外(您應該在代碼中的其他位置設置它)。

private static int NO_INTERCEPTION;

private boolean isWithinBounds(View view, MotionEvent ev) {
    int xPoint = Math.round(ev.getRawX());
    int yPoint = Math.round(ev.getRawY());
    int[] l = new int[2];
    view.getLocationOnScreen(l);
    int x = l[0];
    int y = l[1];
    int w = view.getWidth();
    int h = view.getHeight();
    return !(xPoint < x || xPoint > x + w || yPoint < y || yPoint > y + h);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    for (int i=0; i<floatingMenuItems.getChildCount(); i++){
        View child = floatingMenuItems.getChildAt(i);
        if (child == null || child.getTag(NO_INTERCEPTION) == null) {
            continue;
        }
        if(isWithinBounds(child, ev)){
            return false;
        }
    }
    return true;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM