扩大ViewPager触摸区域

3
我的应用程序使用以下的ViewPager

Screenshot

ViewPager的宽度与显示屏相同。
我在xml中为ViewPager添加了边距,以便我可以看到左侧(蓝色)和右侧(灰色)的页面。结果一切正常,但是我只能点击绿色区域来移动页面。
我想将触摸区域扩展到整个屏幕,这样我就可以在任何地方触摸来移动ViewPager
我尝试添加TouchDelegate
binding.pagerContainer.post {
        val rect = Rect()  
        binding.touchArea.getHitRect(rect)
        binding.pagerContainer.touchDelegate = TouchDelegate(rect, binding.viewPager)
    }

在xml中:

 <FrameLayout
        android:id="@+id/pager_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:clipChildren="false">

        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_marginBottom="150dp"
            android:layout_marginLeft="70dp"
            android:layout_marginRight="70dp"
            android:layout_marginTop="150dp"
            android:clipChildren="false"/>

        <View
            android:id="@+id/touchArea"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:alpha="0">
        </View>
    </FrameLayout>
Rect的大小是正确的。 我正在发布一个Runnable,以确保视图被布局。 我已经阅读了TouchDelegate的文档。 我不知道为什么它不起作用。
3个回答

3

好的,我想这次我有了答案。在这里这里进行了一些研究后,我得出了这个答案。不要尝试使用TouchDelegate扩展ViewPager的区域,而是将触摸事件从FrameLayout重新路由到ViewPager。首先,制作自己的FrameLayout。

public class MyFrameLayout extends FrameLayout {

    // make sure to include all the necessary constructors here
    // with calls to super

    // only need to override 1 method
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        ViewPager pager = null;
        int count = getChildCount();
        for(int i=0; i<count; i++) {
            if(getChildAt(i) instanceof ViewPager) {
                pager = (ViewPager)getChildAt(i);
                break;
            }
        }
        if(pager != null) {
            return pager.onTouchEvent(event);
        }
        return super.onTouchEvent(event);
    }
}

如果您知道ViewPager始终位于FrameLayout的相同位置,则可以简化onTouchEvent()
    ViewPager pager = (ViewPager)getChildAt(0); 
    return pager.onTouchEvent(event);

然后您可以在布局文件中使用自定义的FrameLayout。
 <your.package.name.MyFrameLayout
    android:id="@+id/pager_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    etc. etc.

我已经测试过了,这对我来说足够了。希望它对你也有用。

天才!爱你 :) - Appyx

1
在你的layout.xml文件中添加以下行:

android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"

尝试使用这个代码块:

YOURActivityLayout.setOnTouchListener(new View.OnTouchListener() {  
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {

            return true;//always return true 
        }
    });

希望这能够正常工作。

触摸区域视图的XML? - Appyx
请验证您的布局中是否包含@Appyx。 - Ugur Tufekci
我在我的FrameLayout中添加了你的xml。我为我的FrameLayout添加了onTouchListener。没有变化。 - Appyx
顺便说一下,我发送了一个关于 onTouchListener 的代码块,你知道 ActivityLayout.setOnTouchListener 必须改为 YourActivityLayout.setOnTouchListener 吗?@Appyx - Ugur Tufekci
android:clickable="true" @Appyxandroid:clickable="true" @Appyx - Ugur Tufekci

0
我的ViewPager后面有一个作为背景的视图。我注意到,发送到viewpager中活动项左右的非活动项的触摸事件被发送到背景视图。这给了我拦截触摸并使用viewpager的虚拟拖动api的想法。
我为ViewPager2构建了一个扩展函数,如下所示:
fun ViewPager2.receiveFakeDragsFrom(view: View) {
    view.setOnTouchListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                requestDisallowInterceptTouchEvent(true)
                beginFakeDrag()
                true
            }
            MotionEvent.ACTION_MOVE -> {
                if (event.historySize > 0) {
                    fakeDragBy(
                        event.x - event.getHistoricalX(0)
                    )
                }
                true
            }
            MotionEvent.ACTION_UP -> {
                endFakeDrag()
                requestDisallowInterceptTouchEvent(false)
                performClick()
                true
            }
            else -> {
                false
            }
        }
    }
}

然后在我的片段中设置视图页时,我只需调用该函数,并将背景视图作为参数传递:

myViewPager.receiveFakeDragsFrom(vpBackgroundView)

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