簡體   English   中英

將觸摸事件傳遞給父視圖

[英]Passing touch events to the parent view

我有一個自定義ViewSwitcher ,我在其中實現了觸摸事件,因此我可以使用觸摸屏滾動屏幕。

我的布局層次結構如下所示:

<ViewSwitcher>

    <LinearLayout>
        <ListView />
    </LinearLayout>

    <LinearLayout>
        <ListView />
    </LinearLayout>

</ViewSwitcher>

現在,問題是ListViews正在使用觸摸事件,我無法切換視圖。 當我沒有ListViews時,它工作正常。 我需要能夠滾動視圖並滾動ListView

我該如何解決這個問題?

編輯 :我還需要ListView項目可點擊。

提前致謝!

謝謝大家回答這個問題。 但我能夠以更簡單的方式解決這個問題。 由於我的ViewSwitcher沒有檢測到觸摸事件,我攔截了觸摸事件,稱為onTouchEvent()並返回false 這里:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    onTouchEvent(ev);
    return false;
}

通過重寫onInterceptTouchEvent() ,我能夠攔截活動中的觸摸事件。 然后我稱為onTouchEvent()ViewSwitcher它處理的切換ListViews 最后返回false ,確保ViewGroup不消耗該事件。

將子視圖的TouchEvent傳遞給父視圖的最簡單方法是將其添加到子視圖:

@Override
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event);
    return false;
}

在我的父布局中,我發現阻止子進程捕獲觸摸事件的唯一方法是重寫onInterceptTouchEvent以返回true。

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    return true;
}

我認為沒有一種簡單的方法可以做到這一點。

它並不復雜,但您需要創建自己的視圖來擴展ListView。 然后,您可以覆蓋onTouch處理程序並決定(取決於觸摸事件)是否要處理它(並返回true)或將其傳遞給父視圖。

問題還在於,一旦View處理觸摸事件,它就會獲得所有剩余的事件......

Android文檔

onTouch() - 返回一個布爾值,指示您的偵聽器是否使用此事件。 重要的是這個事件可以有多個相互跟隨的動作。 因此,如果在收到向下操作事件時返回false,則表示您尚未使用該事件,並且對此事件的后續操作也不感興趣。 因此,您不會在事件中調用任何其他操作,例如手指手勢或最終的上行動作事件

因此,例如,如果您希望垂直移動以滾動列表並在同一觸摸事件期間(不抬起手指),您希望水平移動切換視圖,這將是非常具有挑戰性的。

但是,如果您可以使用手勢或處理自定義視圖中的所有內容,並根據MotionEvent的內容,將命令發送到ViewSwitcher。

我所做的是在viewswitcher的listview上設置toucheventlistener,處理事件,檢測fling動作並調用viewswitcher的metchod。 有用。

你也可以插入一個呼叫處理toucheventdispatchTouchEvent ,但在這種情況下,你必須也覆蓋onTouchEvent返回true,否則只有第一個MotionEvent手勢的DOWN將被傳遞。

這是可觸摸的包裝容器:

<?xml version="1.0" encoding="utf-8"?>
<view xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.example.myapp.FragmentContainer$TouchableWrapper" />

和班級:

public static class TouchableWrapper extends FrameLayout {
    private GestureDetector gestureDetector;
    public void setGestureDetector(GestureDetector gestureDetector) {
        this.gestureDetector = gestureDetector;
    }

    // these constructors for the XML inflater
    public TouchableWrapper(Context context) {
        super(context);
    }
    public TouchableWrapper(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public TouchableWrapper(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        Log.d(TAG, "onInterceptTouchEvent " + event.toString());
        return false; // true for intercept, false è default and pass on to children View
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d(TAG, "dispatchTouchEvent " + event.toString());
        gestureDetector.onTouchEvent(event);
        return super.dispatchTouchEvent(event);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "onTouchEvent " + event.toString());
        return true; //return super.onTouchEvent(event); 
    }
}

這是GestureDetector參考:

private GestureDetector gestureDetector;

這是GestureListener

private GestureDetector.SimpleOnGestureListener sOGL = new GestureDetector.SimpleOnGestureListener() {
    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        goToRight(); // onSwipeRight();
                    } else {
                        goToLeft(); // onSwipeLeft();
                    }
                }
                result = true;
            } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                if (diffY > 0) {
                    // onSwipeBottom();
                } else {
                    // onSwipeTop();
                }
            }
            result = true;

        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result; // return false indicate event not handled
    }
};

使用Ant來加載可觸摸的容器片段和包含的片段:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView()");
    View view = inflater.inflate(R.layout.fragmentcontainer, container, false);

    gestureDetector = new GestureDetector(view.getContext(), sOGL);
    ((FragmentContainer.TouchableWrapper) view).setGestureDetector(gestureDetector);

    FragmentManager fm = this.getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.pager, frag).commit();

    return view;
}

有必要在父視圖中使用autoLink =“三”來處理TextView中的觸摸。這樣做:

private LinearLayout mParentView;
private TextView mTextView;
private View.OnTouchListener mParentListener = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ......
        return false;
    }
};
mParentView.setOnTouchListener(mParentListener);

mTextView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mParentListener.onTouch(mParentView, event);
        return false;
    }
};

您是否嘗試將ListView項設置為不可單擊,如下所示:listView.setClickable(false); 這應該向上傳播click事件。

如果您的視圖想要傳遞事件,請確保在onTouchEvent中返回false。 否則,平台認為您使用了該事件,無需進一步處理。

暫無
暫無

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

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