【06】ViewPager禁止滑动以及它与内层滑动控件事件冲突的解决方法

一、上图

二、场景描述

    近期在做项目的时候,遇到一个怪异的需求,描述如下:

    1、ViewPager中嵌套3个View,当从View1滑动到View2时禁止ViewPager的滑动事件。

    2、通过View2底部改变页面的布局实现滑动到View1和View3.

    3、View2内嵌的View中还存在一个可以左右滑动的View,在其上添加了手势,即支持左右滑动,这里存在事件冲突,需要通过事件分发来进行处理。

 

三、问题解决思路

     1、禁止ViewPager滑动,主要是不让ViewPager执行scrollTo(int x,int y)这个方法,这个参考了网上的做法,即自定义一个ViewPager,通过设置一个开关标志位,来决定是否执行scrollTo方法。代码如下:

 

 

 

package com.example.viewpagerscrollconflict.views;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

public class CustomViewPager extends ViewPager {
	private static final String TAG = "CustomViewPager";

	private boolean isCanScroll = true;

	public CustomViewPager(Context context) {
		super(context);
	}

	public CustomViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public void setScanScroll(boolean isCanScroll) {
		this.isCanScroll = isCanScroll;
	}

	public boolean isCanScroll() {
		return isCanScroll;
	}

	@Override
	public void scrollTo(int x, int y) {
		if (isCanScroll) {
			super.scrollTo(x, y);
		}
	}

	/**
	 * 事件分发
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		Log.i(TAG, "====dispatchTouchEvent====事件分发");
		if(getCurrentItem() == 1){
			isCanScroll = false;
	                this.requestDisallowInterceptTouchEvent(true);

		}
		return super.dispatchTouchEvent(ev);
	}

	/**
	 * 事件拦截
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.i(TAG, "====onInterceptTouchEvent====事件拦截");
		return super.onInterceptTouchEvent(ev);
	}

	/**
	 * 事件响应
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		Log.i(TAG, "====onTouchEvent====事件响应");
		return super.onTouchEvent(event);
	}
}

 

 

 

 

 

    2、要实现View2底部改变页面的布局滑动到View1和View3

    这里主要是为改变页面的布局添加滑动手势来进行滑动切换的。(稍后给出源码)

  

    3、ViewPager与其内嵌的View水平滑动事件冲突解决思路(上主要代码)

          (1)当处在View2页面时,首先让ViewPager禁止滑动。

          (2)将事件分发给View2内嵌的View让其根据用户的手势进行滑动。

	/**
	 * 事件分发
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		Log.i(TAG, "====dispatchTouchEvent====事件分发");
		if(getCurrentItem() == 1){
			isCanScroll = false;
			//告诉ViewPager不要拦截子View中的各种事件
			this.requestDisallowInterceptTouchEvent(true);
                }
		return super.dispatchTouchEvent(ev);
	}

 

三、Activity中的代码

 

package com.example.viewpagerscrollconflict;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.example.viewpagerscrollconflict.adapters.ViewPagerAdapter;
import com.example.viewpagerscrollconflict.gestures.ViewPagerGestureListener;
import com.example.viewpagerscrollconflict.views.CustomViewPager;
import com.example.viewpagerscrollconflict.views.ScrollLinearLayout;

public class MainActivity extends Activity{
	private static final String TAG = "MainActivity";
	private GestureDetector mDetector;
	/**布局加载器**/
	private LayoutInflater inflater;
	private CustomViewPager mVpViewPager;
	private ViewPagerAdapter vpAdapter;
	private View v1, v2, v3;
	private List<View> viewList;
	private ScrollLinearLayout sllChangePage;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mVpViewPager = (CustomViewPager) findViewById(R.id.vp_view_pager);
		inflater = LayoutInflater.from(this);
		v1 = inflater.inflate(R.layout.layout_1, null);
		v2 = inflater.inflate(R.layout.layout_2, null);
		v3 = inflater.inflate(R.layout.layout_3, null);
		
		mDetector = new GestureDetector(this, new ViewPagerGestureListener(mVpViewPager));
		sllChangePage = (ScrollLinearLayout) findViewById(R.id.sll_change_page);
		sllChangePage.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				mDetector.onTouchEvent(event);
				return true;
			}
		});

		viewList = new ArrayList<View>();
		viewList.add(v1);
		viewList.add(v2);
		viewList.add(v3);
		vpAdapter = new ViewPagerAdapter(viewList);
		mVpViewPager.setAdapter(vpAdapter);
		mVpViewPager.setOnPageChangeListener(new MyPageChangeListener());
	}

	class MyPageChangeListener implements OnPageChangeListener {

		@Override
		public void onPageScrollStateChanged(int arg0) {

		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {

		}

		@Override
		public void onPageSelected(int arg0) {
			switch (arg0) {
			case 0:
				Log.i(TAG, "=======page=======" + arg0);
				break;
			case 1:
				Log.i(TAG, "=======page=======" + arg0);
				if (!mVpViewPager.isCanScroll()) {//如果不可以滑动
					Log.i(TAG, "在页面1中,不可以滑动");
					mVpViewPager.setCurrentItem(1);
				}
				break;
			case 2:
				Log.i(TAG, "=======page=======" + arg0);
				if (!mVpViewPager.isCanScroll()) {//如果不可以滑动
					Log.i(TAG, "在页面2中,不可以滑动");
					mVpViewPager.setCurrentItem(1);
				}
				break;
			}
		}

	}

}

 

 

 

四、项目源码下载链接

     http://download.csdn.net/detail/xiogjie_67/8897119

 



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以通过以下两种方法禁止ViewPager滑动: 1. 自定义ViewPager类,重写onTouchEvent方法,不处理触摸事件即可。 2. 使用ViewPager的setOnTouchListener方法,监听触摸事件,当触摸事件发生时,返回true,即可禁止ViewPager滑动。 具体实现方法可以参考以下代码: 1. 自定义ViewPager类: ``` public class NoScrollViewPager extends ViewPager { public NoScrollViewPager(Context context) { super(context); } public NoScrollViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent ev) { return false; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } } ``` 2. 使用setOnTouchListener方法: ``` viewPager.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); ``` ### 回答2: Android中的ViewPager是一个非常流行的View,它提供了一种灵活的方式来切换不同的视图。默认情况下,ViewPager可以通过手势水平滑动来切换视图。然而,在某些情况下,您可能需要禁止用户手动滑动,而只是依靠代码来处理切换视图。 一种方法是使用ViewPager的setEnabled()方法来禁用ViewPager的手势滑动。将setEnabled()方法的参数设置为false即可。但是这种方法还可以让ViewPager仍然可以通过代码来进行切换视图,这可能并不是您想要的。 另一种方法是,您可以通过自定义ViewPager来禁止手势滑动,但仍保持使用代码来实现视图切换。 自定义ViewPager主要涉及两个方面。 第一方面涉及ViewPager的手势控制,默认情况下ViewPager具有手势控制功能,我们需要禁用这些手势控制。我们可以通过重写ViewPager的onInterceptTouchEvent和onTouchEvent方法来实现。在这两个方法中,我们可以判断用户的操作类型,如果是手势滑动,我们就不需要将事件传递给父View或子View,以此来禁用ViewPager的手势滑动。 第二个方面涉及ViewPager的动画效果。为了保证视图的切换效果,ViewPager默认添加了一些动画效果。而我们禁用了手势滑动后,这些动画效果可能会变得不协调或不适合我们的需求。因此,我们需要重写ViewPager的onPageScrolled方法来取消动画效果。 通过以上两个操作,我们就可以实现自定义ViewPager,并禁用手势滑动。但是需要注意的是,这样可能会影响用户的交互体验,因此在开发中需要根据具体情况慎重考虑是否要禁用手势滑动。 ### 回答3: 在 Android 中,如果想要禁止 ViewPager 的滑动,可以通过以下三种方法实现: 1. 自定义 ViewPager 可以自定义一个继承自 ViewPager 的类,重写它的 onTouchEvent() 方法和 onInterceptTouchEvent() 方法,在这两个方法中判断是否禁止滑动,如果禁止了,则不执行父类的 onTouchEvent() 和onInterceptTouchEvent() 方法。示例代码如下: ``` public class NonSwipeableViewPager extends ViewPager { private boolean isSwipeEnabled = false; public NonSwipeableViewPager(@NonNull Context context) { super(context); } public NonSwipeableViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent ev) { return isSwipeEnabled && super.onTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return isSwipeEnabled && super.onInterceptTouchEvent(ev); } public void setSwipeEnabled(boolean enabled) { isSwipeEnabled = enabled; } } ``` 2. 给 ViewPager 设置监听器 可以在 Activity 或 Fragment 中给 ViewPager 设置 onPageChangeListener,然后在 onPageScrollStateChanged() 方法中判断是否禁止滑动,如果禁止了,则将其返回到初始位置。示例如下: ``` viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { int currentItem = viewPager.getCurrentItem(); if (currentItem == 0) { viewPager.setCurrentItem(0, false); } else if (currentItem == viewPager.getAdapter().getCount() - 1) { viewPager.setCurrentItem(viewPager.getAdapter().getCount() - 1, false); } } } }); ``` 3. 通过 layout 参数禁止滑动 在 XML 中设置 ViewPager 的 `android:layout_width` 属性为 0dp,可以禁止它的滑动。示例代码如下: ``` <ViewPager android:id="@+id/viewPager" android:layout_width="0dp" android:layout_height="wrap_content" /> ``` 以上是三种禁止 ViewPager 滑动方法,开发者可以根据实际需求选用合适的方法来实现自己需要的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值