ViewPager或RecyclerView嵌套MediaController的滚动问题
在Android的UI设计中,很容易遇到在ViewPager的某个Fragment中使用了ViewView,或者在RecyclerView嵌套了一个视频列表(使用VideoView),而VideoView中会使用MediaController的进度条控件,如果不做任何调整,会发现视频进度条没有办法拖动(Scroll),每次Scroll都是滑动ViewPager,或者误滑动了RecyclerView。这里就分享一下如何解决这个问题。
以下没有贴所有的代码,可能有信息缺失引起歧义,可以发送邮件到hugh@inner-peace.cn 咨询和探讨。
问题的主要原因是因为Scroll事件的传递问题,由于Scroll事件被更外层的控件给截获阻断,导致内层的MediaController无法获取到Scroll事件,导致出现问题。所以只要外层不处理或者透传,既可以解决问题。
而上面提到的Scroll事件,并不是直接有个什么onScroll这种方式,而是由两个比较重要的Touch事件影响:onTouchEvent和onInterceptTouchEvent。
public class MyViewPager extends ViewPager {
public MyViewPager(@NonNull Context context) {
super(context);
}
public MyViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 这里的Adapter是我自定义的Adapter,继承于FragmentPagerAdapter,不是重点,所以不展开
ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
if (adapter == null) {
return super.onInterceptTouchEvent(ev);
}
// isVideoControllerShown是自定义的函数,用来获取MediaController是否处于展示可滑动的状态
return (!adapter.isVideoControllerShown()) && super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
if (adapter == null) {
return super.onTouchEvent(ev);
}
return (!adapter.isVideoControllerShown()) && super.onTouchEvent(ev);
}
}
以上这段代码的意思是,在自定义的MyViewPager控件中的一个Fragment里面有一个视频播放器,在MediaController(进度条)展示的时候,ViewPager不允许滑动,这样就不会出现用户在滑动进度条时,出现Fragment切换。这两个事件什么意思,简单归纳一下:
- onTouchEvent:响应触摸事件,包含ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL一些事件,如果不处理就返回False。如果返回True则不会向下传递;
- onInterceptTouchEvent:是否阻拦Touch事件,如果返回False则不阻拦。
所以根据adapter中获取MediaController的状态,如果处于展示状态,那么ViewPager不能滑动Fragment,并且将Touch事件传递到MediaController。