如何防止ScrollView拦截其后面视图的点击/触摸事件?

15

我有一个FrameLayout,里面包含了一个ScrollView和一个ImageView。这个ImageView在ScrollView的后面。

我的ScrollView中有一个透明的空间(高度为925px的LinearLayout s_layout_transparent)。

因此,我的ImageView可以通过这个透明的空间被看到,但不能被点击

我尝试给ScrollView添加一些属性值(android:clickable="false" android:focusable=" android:focusableInTouchMode="false"),以防止它拦截ImageView的点击事件,但这并没有起作用。

这是我的布局:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
<LinearLayout
        android:gravity="top|center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingRight="10dp"
        >
    <ImageView
            android:visibility="visible"
            android:id="@+id/s_imgv_splash"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/temp_detail_screen_splash"
            android:adjustViewBounds="true"
            android:scaleType="fitXY"/>
</LinearLayout>
<com.dreambox.android.saven.Views.ScrollView
        android:id="@+id/s_scrollview_event_detail"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="none"
        android:visibility="visible"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        >
    <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="false"
            android:focusableInTouchMode="false"
            android:focusable="false">
        <LinearLayout
                android:id="@+id/s_layout_transparent"
                android:layout_gravity="center_vertical"
                android:layout_width="match_parent"
                android:layout_height="925px"
                android:orientation="horizontal"
                android:background="@color/trasparent"
                android:clickable="false"
                android:focusableInTouchMode="false"
                android:focusable="false">
        </LinearLayout>
        <LinearLayout...>
        <LinearLayout...>
    </LinearLayout>
</com.dreambox.android.saven.Views.ScrollView>
</FrameLayout>

制作自定义滚动视图 - Tushar Gogna
等等,划掉。只需将ImageView移动到ScrollView内部的LinearLayout中即可。 - Tushar Gogna
我故意将ImageView留在后面,因为我希望当ScrollView向上滚动时,ImageView会慢慢被ScrollView内容覆盖。注意:ScrollView不仅具有透明的LinearLayout,还有一些位于下方的LinearLayout(您可以在我的布局<LinearLayout...>中看到)。 - NghiaDao
谢谢,但这个也不行。 - NghiaDao
@SHASHIDHAR MANCHUKONDA 我想让我的ImageView可点击。现在,它无法被点击。 - NghiaDao
显示剩余4条评论
7个回答

15

如果您可以将透明部分填充为空视图(我们称之为 dummyView),那么您可以做如下操作...

dummyView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        // pass on the touch event to the ImageView
        s_imgv_splash.dispatchTouchEvent(event);
        // returning true because we handled the event
        return true;
    }
});

6
我解决了这个问题。为了帮助其他人,我在此分享我的解决方法。感谢Mahesh提供的建议。根据Mahesh的建议,我采取了以下步骤。这是我的layout.xml文件。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scroll_view"
    android:background="#ffffff"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/bg_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TestView"
        android:layout_marginTop="5dip"/>

    <View android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/background_dark"
        android:alpha="0"
        />

    <ScrollView
        android:id="@+id/sv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        >

       <LinearLayout
            android:id="@id+/wrapper"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@android:color/transparent"
            android:orientation="vertical" >

           <LinearLayout
               android:id="@+id/dummy"
                android:layout_width="fill_parent"
                android:background="@android:color/transparent"
                android:layout_height="500dip"
                android:orientation="vertical"/>

           <LinearLayout
               android:id="@+id/scroll_"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >

             ................
             ................


          </LinearLayout>

        </LinearLayout>

    </ScrollView>

</RelativeLayout>

在添加LinearLayouts @id/dummy和@id/scroll_之后,我无法单击TextView @id/bg_tv。以下代码解决了我的问题。
//dispatch touch events
mDummyView = findViewById(R.id.dummy);
mDummyView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        mTextView.dispatchTouchEvent(motionEvent);
        return true;
    }
});

mLayout = (LinearLayout)findViewById(R.id.scroll_);
mLayout.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (scrollPercent <= 0.25f) {
            mTextView.dispatchTouchEvent(motionEvent);
            return true;
        }
        return false;
    }
});

在mLayout的情况下,仅当scrollView滚动到屏幕底部后才会触发TouchEvents事件。
PS:这是我第一次写答案。如果您发现格式非常糟糕或者答案没有按照应该的方式编写,我深感抱歉。

1

检查事件的坐标是否在你想要接收事件的视图范围内。如果匹配,则使用performClick方法将事件传递给所需的视图。以下是一个示例:

override fun onCreate(savedInstanceState: Bundle?) {
    ....
    val viewUnderDummySpace = findViewById<View>(R.id.your_textview_or_button_or_image)
    val dummySpace = scrollView.findViewById<View>(R.id.dummy_space)
    dummySpace.setOnTouchListener(object : View.OnTouchListener {
        override fun onTouch(p0: View?, event: MotionEvent?): Boolean {
            event?.let {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (inViewInBounds(viewUnderDummySpace, event.rawX.toInt(), event.rawY.toInt())) {
                        //Click performed within bounds of the desired view
                        viewUnderDummySpace.performClick()
                    }
                }
            }

            return true
        }
    })
}

private var outRect = Rect()
private var location = IntArray(2)

private fun inViewInBounds(view: View, x: Int, y: Int): Boolean {
    view.getDrawingRect(outRect)
    view.getLocationOnScreen(location)
    outRect.offset(location[0], location[1])
    return outRect.contains(x, y)
}

1

我无法提供确切的解决方案

检查一下,可能会有帮助

yourscrollview.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(touch exists inside imageview boundaries)
                {
                    do imageview click action
                }
                return false;
            }
        })

1
ScrollView位于FrameLayout的最后,因此它具有优先权。
当您激活带有ImageView的LinearLayout时,您需要说
findViewById(R.id.s_scrollview_event_detail).setVisibility(View.INVISIBLE)

反之,当ScrollView被激活时,“兄弟”布局视图必须设置为不可见。


0
我还使用了滚动偏移量,并且在点击事件中得到了完美的结果。
blockingViewInScroll.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        event.offsetLocation(-scrollView.getScrollX(), -scrollView.getScrollY());
        blockedViewUnderScroll.dispatchTouchEvent(event);
        return true;
    }
});

0
如果您的自定义视图在其onTouchEvent中调用requestDisallowInterceptTouchEvent(true),并且操作为ACTION_DOWN,则滚动视图及其父级都不会拦截触摸事件,直到您使用false调用requestDisallowInterceptTouchEvent。
您可以从此视频中了解更多信息: https://www.youtube.com/watch?v=EZAoJU-nUyI

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接