Как передать сенсорные события в представление ниже в RelativeLayout?

У меня есть ScrollView поверх другого вида (с Buttons). ScrollView занимает весь экран и закрывает вид под ним.

В какой-то момент в моем приложении мне нужно, чтобы ScrollView был отключен (но все еще был виден) и передал все сенсорные события в Buttons, которые находятся под ScrollView. Как я могу это сделать? Некоторые представления, такие как Buttons, автоматически делают это при отключении, но ScrollView этого не делает.


person roiberg    schedule 11.10.2012    source источник
comment
Как отключить ScrollView? Кроме того, ваша ситуация кажется немного нелогичной, когда ScrollView все еще отображается, а Buttons под ним щелкают.   -  person user    schedule 11.10.2012
comment
Трудно объяснить необходимость такого поведения, но это то, что мне нужно сделать. все, что мне действительно нужно, — это вид прокрутки, который должен быть видимым, но не неуправляемым, поэтому все прикосновения будут переходить к расположенному ниже макету. это возможно?! что касается вашего вопроса, я не отключал просмотр прокрутки, это часть моей проблемы, кому я должен его отключить...   -  person roiberg    schedule 11.10.2012


Ответы (3)


Попробуйте реализовать свой собственный ScrollView, у которого есть флаг для указания статуса (отключено/включено), а также переопределяет onTouchEvent и dispatchTouchEvent, чтобы события касания проходили через ScrollView. Вот пример:

public class DisabledScrollView extends ScrollView {

    private boolean mIsDisable = false;

    // if status is true, disable the ScrollView
    public void setDisableStatus(boolean status) {
        mIsDisable = status;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // no more tocuh events for this ScrollView
        if (mIsDisable) {
            return false;
        }       
        return super.onTouchEvent(ev);
    }

    public boolean dispatchTouchEvent(MotionEvent ev) {
        // although the ScrollView doesn't get touch events , its children will get them so intercept them.
        if (mIsDisable) {
            return false;
        }
        return super.dispatchTouchEvent(ev);
    }

}

Тогда все, что вам нужно сделать, это изменить значение этого флага. Посмотрите, работает ли это.

person user    schedule 11.10.2012

В моем случае мне просто нужно было обработать событие касания в представлении A, которое перекрывало представление B, а затем отправить событие в представление B. Оба представления были дочерними для одного и того же RelativeLayout, но между представлениями A не было отношения родитель-потомок. и Б. Это сработало для меня:

viewA.setOnTouchListener( new OnTouchListener(){

        @Override
        public boolean onTouch(View v, MotionEvent event) {
          // do my stuff here

          viewB.dispatchTouchEvent( event );
        }
}
person Ignacio Roda    schedule 13.07.2015

В этом случае у меня есть recyclerview под прокруткой. Верх прокрутки находится в вертикальной прокрутке, а вид повторного использования - в горизонтальной прокрутке. Вид прокрутки имеет верхнее заполнение, благодаря чему вид повторного использования виден сквозь прозрачность заполнения прокрутки. Я должен сделать это таким образом, потому что при прокрутке окна прокрутки представление повторного использования будет прокручиваться вертикально, как эффект параллакса (этот эффект находится в другом коде). Этот код ниже работает для моего случая, может помочь

scrollView.setOnTouchListener(new View.OnTouchListener() {

        float mDownX,mDownY;
        boolean mIsSwiping,isDown;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(mIsSwiping){
                recyclerView.dispatchTouchEvent(event);
            }
            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    mIsSwiping = false;
                    isDown = true;
                    mDownX = event.getX();
                    mDownY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(isDown){
                        float deltaX = Math.abs(event.getX() - mDownX);
                        float deltaY = Math.abs(event.getY() - mDownY);
                        mDownX = event.getX();
                        mDownY = event.getY();
                        if(deltaX!=deltaY){
                            isDown = false;
                            if(deltaX>deltaY){
                                mIsSwiping = true;
                            }
                        }
                    }
            }

            return mIsSwiping;
        }
    });

это макет

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray0"
android:clipToPadding="false"
android:clipChildren="false"
android:paddingBottom="70dp">
<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="320dp"
    android:orientation="horizontal"
    app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<ScrollView
    android:id="@+id/scrollview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="301.75dp"
    android:paddingBottom="23.5dp"
    android:clipChildren="false"
    android:clipToPadding="false">

. . .

person Gome    schedule 28.08.2017