2017-03-21 5 views
0

Ich verwende VerticalViewPager und zwei Fragmente darin.Scroll-Verhalten bei RecyclerView in vertikale Ansicht Pager

Eines dieser Fragment enthält RecyclerView mit nur regulären vertikalen Liste. Das Problem ist, dass ich diese Liste zu beenden brauchen und dann Seite bei Ansicht Pager ändern und jetzt Pager immer versuchen, RecyclerView Scroll abzufangen versuchen.

Meine VerticalViewPager Klasse:

public class VerticalViewPager extends ViewPager { 

    public VerticalViewPager(Context context) { 
     super(context); 
     init(); 
    } 

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

    private void init() { 
     setPageTransformer(true, new VerticalPageTransformer()); 
     setOverScrollMode(OVER_SCROLL_NEVER); 
     requestDisallowInterceptTouchEvent(false); 
    } 

    private class VerticalPageTransformer implements ViewPager.PageTransformer { 

     @Override 
     public void transformPage(View view, float position) { 

      if (position < -1) { 
       view.setAlpha(0); 

      } else if (position <= 1) { 
       view.setAlpha(1); 

       view.setTranslationX(view.getWidth() * -position); 

       float yPosition = position * view.getHeight(); 
       view.setTranslationY(yPosition); 

      } else { 
       view.setAlpha(0); 
      } 
     } 
    } 

    private MotionEvent swapXY(MotionEvent ev) { 
     float width = getWidth(); 
     float height = getHeight(); 

     float newX = (ev.getY()/height) * width; 
     float newY = (ev.getX()/width) * height; 

     ev.setLocation(newX, newY); 

     return ev; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); 
     swapXY(ev); 
     return intercepted; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     return super.onTouchEvent(swapXY(ev)); 
    } 

} 

Und mein Layout Baum:

  • -Fragment
  • --ViewPager
  • --- Fragment_A
  • ---- RecyclerView
  • --- Fragment_B

Ich habe bereits versucht, verschiedene Kombinationen von

.setNestedScrollingEnabled(false/true); 
.requestDisallowInterceptTouchEvent(false/true); 

Versuchte RecyclerView mit NestedScrollView zu wickeln, aber Schnecke ist nach wie vor chaotisch und laggy, ViewPager seine Seite zu Beginn Liste ändern oder in der Mitte.

Danke für Ihre Hilfe!

Antwort

0

ich es heraus mit benutzerdefinierten OnTouchListener für meine RecyclerView schreiben:

public class VerticalTouchListener implements View.OnTouchListener { 

     private float lastMotionY = Float.MIN_VALUE; 
     private float downY = Float.MIN_VALUE; 

     private final OnScrollableViewPager scrollableViewPager; 

     public VerticalTouchListener(@NonNull OnScrollableViewPager scrollableViewPager) { 
      this.scrollableViewPager = scrollableViewPager; 
     } 

     @Override 
     public boolean onTouch(@NonNull View v, @NonNull MotionEvent event) { 
      switch (event.getAction()) { 
       case MotionEvent.ACTION_DOWN: 
        downY = event.getRawY(); 
        break; 
       case MotionEvent.ACTION_MOVE: 
        if (downY == Float.MIN_VALUE && lastMotionY == Float.MIN_VALUE) { 
         downY = event.getRawY(); 
         break; 
        } 

        float diff = event.getRawY() - (lastMotionY == Float.MIN_VALUE ? downY : lastMotionY); 
        lastMotionY = event.getRawY(); 

        if (scrollableViewPager.getScrollX() != scrollableViewPager.getBaseScrollX()) { 
         if (fakeDragVp(v, event, diff)) return true; 
        } else { 
         if (ViewCompat.canScrollVertically(v, (-diff) > 0 ? 1 : -1)) { 
          break; 
         } else { 
          scrollableViewPager.beginFakeDrag(); 
          fakeDragVp(v, event, diff); 
          adjustDownMotion(v, event); 
          return true; 
         } 
        } 

        break; 
       case MotionEvent.ACTION_UP: 
       case MotionEvent.ACTION_CANCEL: 
        if (scrollableViewPager.isFakeDragging()) { 
         try { 
          scrollableViewPager.endFakeDrag(); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 


       } 
       reset(); 
       break; 
     } 

     return false; 
    } 

    private boolean fakeDragVp(@NonNull View v, @NonNull MotionEvent e, float diff) { 
     if (scrollableViewPager.isFakeDragging()) { 
      float step = diff; 
      int expScrollX = (int) (scrollableViewPager.getScrollX() - step); 
      if (isDiffSign(expScrollX - scrollableViewPager.getBaseScrollX(), scrollableViewPager.getScrollX() - scrollableViewPager.getBaseScrollX())) { 
       step = scrollableViewPager.getScrollX() - scrollableViewPager.getBaseScrollX(); 
      } 
      scrollableViewPager.fakeDragBy(step); 
      adjustDownMotion(v, e); 

      return true; 
     } 
     return false; 
    } 

    private void adjustDownMotion(@NonNull View v, @NonNull MotionEvent e) { 
     MotionEvent fakeDownEvent = MotionEvent.obtain(e); 
     fakeDownEvent.setAction(MotionEvent.ACTION_DOWN); 
     v.dispatchTouchEvent(fakeDownEvent); 
    } 

    private boolean isDiffSign(float a, float b) { 
     return Math.abs(a + b) < Math.abs(a - b); 
    } 


    private void reset() { 
     downY = Float.MIN_VALUE; 
     lastMotionY = Float.MIN_VALUE; 
    } 

    public interface OnScrollableViewPager { 
     int getScrollX(); 

     int getBaseScrollX(); 

     boolean isFakeDragging(); 

     boolean beginFakeDrag(); 

     void fakeDragBy(float step); 

     void endFakeDrag(); 
    } 
} 

und änderte meine VerticalViewPager:

public class VerticalViewPager extends ViewPager implements VerticalTouchListener.OnScrollableViewPager { 

     private int baseScrollX; 

     public VerticalViewPager(@NonNull Context context) { 
      super(context); 
      init(); 
     } 

     public VerticalViewPager(@NonNull Context context, @NonNull AttributeSet attrs) { 
      super(context, attrs); 
      init(); 
     } 

     private void init() { 
      setPageTransformer(false, new VerticalTransformer()); 
      setOverScrollMode(OVER_SCROLL_NEVER); 
      addOnPageChangeListener(new SimpleOnPageChangeListener() { 
       @Override 
       public void onPageScrollStateChanged(int state) { 
        super.onPageScrollStateChanged(state); 
        if (state == ViewPager.SCROLL_STATE_IDLE) { 
         baseScrollX = getScrollX(); 
        } 
       } 
      }); 
     } 

     @Override 
     public boolean onInterceptTouchEvent(MotionEvent event) { 
      return false; 
     } 

     @Override 
     public boolean onTouchEvent(MotionEvent ev) { 
      return super.onTouchEvent(swapXY(ev)); 
     } 

     @Override 
     public int getBaseScrollX() { 
      return baseScrollX; 
     } 

     private MotionEvent swapXY(MotionEvent ev) { 
      float width = getWidth(); 
      float height = getHeight(); 

      float newX = (ev.getY()/height) * width; 
      float newY = (ev.getX()/width) * height; 

      ev.setLocation(newX, newY); 

      return ev; 
     } 

     private class VerticalTransformer implements ViewPager.PageTransformer { 
      @Override 
      public void transformPage(@NonNull View view, float position) { 
       float alpha = 0; 

       if (0 <= position && position <= 1) { 


       alpha = 1 - position; 
      } else if (-1 < position && position < 0) { 
       alpha = position + 1; 
      } 

      view.setAlpha(alpha); 
      view.setTranslationX(view.getWidth() * -position); 
      view.setTranslationY(position * view.getHeight()); 
     } 

    } 
} 

Diese repo half mir ein wenig.

Verwandte Themen