2013-09-06 8 views
13

Chcę wyłączyć przesuwanie, ale tylko po prawej stronie. Znalazłem działające rozwiązanie w odpowiedzi na this. Niestety kopiuje to całe źródło ViewPager, aby osiągnąć cel. Czy istnieją metody dziedziczące istniejącą klasę, a nie dublowanie?ViewPager wyłącza przesuwanie w określonym kierunku.

+0

Czy używasz wanilii ViewPager? – Shark

+0

Jeśli istnieje lib, który zawiera 'ViewPager' z takim zachowaniem, mogę go używać BTW. Zauważ, że chcę dynamicznie włączać i wyłączać przesuwanie w prawo, a nie tylko wyłączać je statycznie. – WonderCsabo

+0

Przypuśćmy, że możesz spróbować przesłonić TouchEvent lub onInterceptTouchEvent i spróbować odfiltrować zdarzenia dotykowe, na które nie chcesz reagować (i zadzwonić super do reszty). – Karakuri

Odpowiedz

19

nie jestem pewien to jest dokładnie to, czego potrzebujesz: Potrzebowałem wizualizatora dla kreatora z maksymalną stroną, której użytkownik nie może przekazać.

Na koniec rozwiązanie było w adapterze. Zmieniłem rachubę PagerAdapter iw ten sposób blokuje użytkownikowi przechodzenie max strony:

@Override 
public int getCount() { 
    return mProgress; //max page + 1 
} 

Gdy użytkownik przechodzi do następnej strony:

private void setWizardProgress(int progress) { 
    if(progress > mProgress) { 
     mProgress = progress; 
     mWizardPagerAdapter.notifyDataSetChanged(); 
    } 
} 

W ten sposób, gdy użytkownik jest w maksymalna strona nie może przewinąć w prawo.

+1

Dzięki! To jest stare pytanie, już to rozwiązałem (poprzez upuszczenie 'ViewPager' i użycie animacji' Fragment', aby całkowicie kontrolować przepływ). Myślę, że twoje jest dobre rozwiązanie, więc akceptuję to. :) – WonderCsabo

5

Można spróbować następujących czynności:

Krok 1: utworzyć nowy zwyczaj klasa powiedzieć "CustomViewPager". Klasa dziedziczy po "ViewPager" i zawiera nową dostosowaną metodę o nazwie "setPagingEnabled" w celu włączenia/wyłączenia przesuwania w zależności od wymagań.

Krok 2: Zastąp dwie metody: "onTouchEvent" i "onInterceptTouchEvent". Oba zwrócą "false", jeśli stronicowanie ma zostać całkowicie wyłączone.

Krok 3: zastąpić "ViewPager" tag w pliku arkusza doda klasy:

<package_name.customviewpager 
    android:id="@+id/customViewPager" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" /> 

Krok 4: CustomViewPager.java

public class CustomViewPager extends ViewPager { 

private boolean enabled; 

public CustomViewPager(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    this.enabled = true; 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (this.enabled && detectSwipeToRight(event)) { 
     return super.onTouchEvent(event); 
    } 

    return false; 
} 

@Override 
public boolean onInterceptTouchEvent(MotionEvent event) { 
    if (this.enabled && detectSwipeToRight(event)) { 
     return super.onInterceptTouchEvent(event); 
    } 

    return false; 
} 

// To enable/disable swipe 
public void setPagingEnabled(boolean enabled) { 
    this.enabled = enabled; 
} 

// Detects the direction of swipe. Right or left. 
// Returns true if swipe is in right direction 
public boolean detectSwipeToRight(MotionEvent event){ 

int initialXValue = 0; // as we have to detect swipe to right 
final int SWIPE_THRESHOLD = 100; // detect swipe 
boolean result = false; 

     try {     
      float diffX = event.getX() - initialXValue; 

       if (Math.abs(diffX) > SWIPE_THRESHOLD) { 
        if (diffX > 0) { 
         // swipe from left to right detected ie.SwipeRight 
         result = false; 
        } else { 
         // swipe from right to left detected ie.SwipeLeft 
         result = true; 
        } 
       } 
      } 
     catch (Exception exception) { 
      exception.printStackTrace(); 
     } 
     return result; 
    } 
} 
+1

Dzięki! Sprawdź swój kod, nie kompiluje! – WonderCsabo

+0

ya, zaktualizowałem swój post. –

+3

Próbowałem zaktualizowanej odpowiedzi. 'diffX' jest zawsze dodatni, więc metoda nigdy nie zwraca' true'. – WonderCsabo

1
private float initialXValue; 
@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (this.mEnabled) { 
     return super.onTouchEvent(event); 
    } 
    if(event.getAction()==MotionEvent.ACTION_DOWN){ 
     initialXValue = event.getX(); 
    }else if(event.getAction()==MotionEvent.ACTION_MOVE){ 
     if(detectSwipeToRight(event)){ 
      System.out.println("right swipe detected"); 
     } 
    } 
    return true; 
} 

private boolean detectSwipeToRight(MotionEvent event) { 
    final int SWIPE_THRESHOLD = 100; // detect swipe 
    boolean result = false; 

    try { 
     float diffX = event.getX() - initialXValue; 
     if (Math.abs(diffX) > SWIPE_THRESHOLD) { 
      if (diffX < 0) { 
       // swipe from right to left detected ie.SwipeLeft 
       result = true; 
      } 
     } 
    } catch (Exception exception) { 
     exception.printStackTrace(); 
    } 
    return result; 
} 
+1

To byłaby znacznie lepsza odpowiedź, jeśli wyjaśnisz kod nieco więcej. – skrrgwasme

0

Można użyć metod beginFakeDrag() i endFakeDrag().

beginFakeDrag() jeśli chcesz wyłączyć przesunięcie i endFakeDrag(), jeśli chcesz ponownie włączyć.

Jak to: viewPager.beginFakeDrag();

+1

Nie, nie będzie działać ... Nadal przewija się przez chwilę ... – ichalos

13

Tu pracuje klasę ViewPager z możliwością wyłączenia jakiegokolwiek stronicowania kierunek. Sprawdź wszystkie answer here.

public class CustomViewPager extends ViewPager { 
    private float initialXValue; 
    private SwipeDirection direction; 

    public CustomViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.direction = SwipeDirection.all; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (this.IsSwipeAllowed(event)) { 
      return super.onTouchEvent(event); 
     } 

     return false; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     if (this.IsSwipeAllowed(event)) { 
      return super.onInterceptTouchEvent(event); 
     } 

     return false; 
    } 

    private boolean IsSwipeAllowed(MotionEvent event) { 
     if(this.direction == SwipeDirection.all) return true; 

     if(direction == SwipeDirection.none)//disable any swipe 
      return false; 

     if(event.getAction()==MotionEvent.ACTION_DOWN) { 
      initialXValue = event.getX(); 
      return true; 
     } 

     if(event.getAction()==MotionEvent.ACTION_MOVE) { 
      try { 
       float diffX = event.getX() - initialXValue; 
       if (diffX > 0 && direction == SwipeDirection.right) { 
        // swipe from left to right detected 
        return false; 
       }else if (diffX < 0 && direction == SwipeDirection.left) { 
        // swipe from right to left detected 
        return false; 
       } 
      } catch (Exception exception) { 
       exception.printStackTrace(); 
      } 
     } 

     return true; 
    } 

    public void setAllowedSwipeDirection(SwipeDirection direction) { 
     this.direction = direction; 
    } 
+0

To coś działa. (Chociaż styl składni jest bardzo zły) – vedant1811

+0

@ vedant1811 co jest złego w tym? – lelloman

+0

@lelloman prawdopodobnie oznacza brak autoformatowania, IsSwipeAllowed z wielką pierwszą literą, try-catch, gdzie nie jest zgłaszany wyjątek, a także printStackTrace tam, i "to" w niepotrzebnych miejscach (i overriden metody mogą być rzeczywiście inline). Ale i tak odpowiedź jest pomocna. – 0101100101

6

Innym prostym sposobem jest użycie setCurrentItem(), aby przejść z powrotem do żądanej slajdu, jeśli trafisz pewną pozycję.Na przykład, pozwoli to tylko do przodu przesuwając:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
    @Override 
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} 

    @Override 
    public void onPageSelected(int position) { 
     if(position < mProgress) { 
      mViewPager.setCurrentItem(mProgress, true); 
     } else { 
      mProgress = position; 
     } 
    } 

    @Override 
    public void onPageScrollStateChanged(int state) {} 
}); 

Lub jeśli chcesz mieć max slajd:

if(position > 4) { 
    mViewPager.setCurrentItem(4, true); 
} 

Rozwiązanie to technicznie nie całkowicie wyłączyć bezstykowa, jak będziesz jeszcze zobaczyć mała część niedozwolonego slajdu po wykonaniu ruchu machnięcia. Ale w przypadku niektórych aplikacji może to być preferowane.