扩展 ViewPager 的触摸区域
Expanding the touch area of a ViewPager
我的应用程序使用以下 ViewPager
:
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
.
的文档
我不知道为什么它不起作用。
在 yourlayout.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
}
});
希望这会奏效
好的。我想这次我得到了。经过一些研究 here and here,我得出了这个答案。我没有尝试使用 TouchDelegate 扩展 ViewPager 的区域,而是将触摸事件从 FrameLayout 重新路由到 ViewPager。 1、制作你自己的 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.
我已经测试过了,这个适合我。希望对你有用。
我的 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
}
}
}
}
然后在我的片段中设置 viewpager 时,我只是用背景视图作为参数调用了该函数:
myViewPager.receiveFakeDragsFrom(vpBackgroundView)
我的应用程序使用以下 ViewPager
:
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
.
我不知道为什么它不起作用。
在 yourlayout.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
}
});
希望这会奏效
好的。我想这次我得到了。经过一些研究 here and here,我得出了这个答案。我没有尝试使用 TouchDelegate 扩展 ViewPager 的区域,而是将触摸事件从 FrameLayout 重新路由到 ViewPager。 1、制作你自己的 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.
我已经测试过了,这个适合我。希望对你有用。
我的 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
}
}
}
}
然后在我的片段中设置 viewpager 时,我只是用背景视图作为参数调用了该函数:
myViewPager.receiveFakeDragsFrom(vpBackgroundView)