Solution and Principle of Conflict between RecycleView and ViewPager in Android

  • 2021-09-12 02:26:58
  • OfStack

1. Overview

In actual development, we often encounter the need to add ViewPager to ListView or RecycleView header to achieve Banner carousel effect, and need to add pull-down refresh and pull-up loading functions.

However, when sliding ViewPager laterally, the focus will be lost if it is slightly offset.

2. Solutions

We know the sequence of event interceptions. The parent ViewGroup first receives the interception and then passes it on to the child ViewGroup or the child View. The processing sequence of events is that the child ViewGroup or the child View is processed first, if the child ViewGroup is processed, the parent ViewGroup is not processed, and if the child ViewGroup is not processed, it is passed to the parent ViewGroup for processing.

According to the principle of event interception, ViewPager and RecycleView conflict with each other, RecycleView is equivalent to parent ViewGroup, ViewPager is equivalent to child View, ViewPager and RecycleView conflict with each other, so the parent View is transmitted to ViewPager for processing, and View Pager is rewritten. Using parent class methods requestDisallowInterceptTouchEvent(true) Used by the child View to tell the parent container not to block our events.

(1) Rewrite ViewPager


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

/**
 * Developer : chunsoft on 2016/10/31 16:04
 * Email : chun_soft@qq.com
 * Content : viewPager And RecycleView Conflict with each other, and the parent View Spread ViewPager Inside 
 *  Using parent class methods requestDisallowInterceptTouchEvent(true)
 *  Used for View That tells the parent container not to block our events 
 */

public class DecoratorViewPager extends ViewPager{
 private ViewGroup parent;
 public DecoratorViewPager(Context context) {
 super(context);
 }

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

 public void setNestedpParent(ViewGroup parent) {
 this.parent = parent;
 }


 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
 if (parent != null){
  parent.requestDisallowInterceptTouchEvent(true);
 }
 return super.dispatchTouchEvent(ev);
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
 if (parent != null){
  parent.requestDisallowInterceptTouchEvent(true);
 }
 return super.onInterceptTouchEvent(ev);
 }

 @Override
 public boolean onTouchEvent(MotionEvent ev) {
 if (parent != null){
  parent.requestDisallowInterceptTouchEvent(true);
 }
 return super.onTouchEvent(ev);
 }
}

(2) In Activity:


DecoratorViewPager mPager = (DecoratorViewPager) mHeaderView.findViewById(R.id.viewpager);

 mPager.setNestedpParent((ViewGroup) mPager.getParent());

(3) In the layout file:


<com.chunsoft.baseframework.utils.view.DecoratorViewPager
 android:id="@+id/viewpager"
 android:layout_width="match_parent"
 android:layout_height="180dp" />

Dealing with ViewPager nested RecycleView jamming problem

Three Fragment are added to ViewPager, and RecycleView is added to Fragment. It is found that the left and right sliding switching of ViewPager is very unsmooth and there is sliding conflict. External interception is used to deal with so easy ~ ~ ~


/**
* Created by magic on 2017/6/12 0012. External interception processing ViewPager Nesting RecycleView Slide left and right to switch Fragment Caton problem 
*/

public class MyViewPager extends ViewPager {

float x, y;

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

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

@Override
public boolean onInterceptHoverEvent(MotionEvent event) {

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
return super.onInterceptHoverEvent(event);
case MotionEvent.ACTION_MOVE:
if (Math.abs(x - event.getX()) > Math.abs(y - event.getY()))
return true;
else return false;
case MotionEvent.ACTION_UP:
return super.onInterceptHoverEvent(event);
}
return super.onInterceptHoverEvent(event);
}
}

Note: Do not return false directly in ACTION_DOWN and ACTION_UP super.onInterceptHoverEvent(event) Because ViewGroup does some basic processing for event interception methods.

Summarize


Related articles: