2014-07-21 6 views
6

Ho un ListView avere fastScroll sempre abilitato e SwipeRefresh implementazione. Quando faccio scorrere la lista verso il basso, aggiorna la lista. Il mio problema è fastScroll. Se l'elenco ha il suo primo elemento visibile o dice nella sua parte superiore iniziale, quindi se si scorre lo fastScrollThumb verso il basso, l'effetto Swipe non lo scorrimento verso il basso. C'è comunque/soluzione che se premo il fastScrollThumb, quindi non dovrebbe fare l'effetto di aggiornamento Swipe piuttosto dovrebbe scorrere verso il basso come comportamento naturale.Evitare SwipeRefresh mentre fastScrolling in Android

enter image description here

CURA mio XML Layout è la seguente:

<?xml version="1.0" encoding="utf-8"?> 
    <android.support.v4.widget.SwipeRefreshLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/swipe_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@color/white" > 

    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" > 

     <RelativeLayout 
      android:id="@+id/buttons_layout" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerHorizontal="true" 
      android:layout_marginTop="10dp"> 

      <ImageView 
       android:id="@+id/SubmitButton" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:background="@drawable/neoo_tab_selector" /> 

     </RelativeLayout> 


     <ListView 
      android:id="@id/android:list" 
      style="@style/NeeoContactListView" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_below="@+id/buttons_layout" 
      android:layout_marginTop="10dp" /> 
    </RelativeLayout> 

</android.support.v4.widget.SwipeRefreshLayout> 

mio Logic for onScroll per abilitare/disabilitare la SwipeRefresh è:

getListView().setOnScrollListener(new OnScrollListener() { 

    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) { 
    } 

    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
     boolean enable = false; 
     if(getListView() != null && getListView().getChildCount() > 0){ 
      // check if the first item of the list is visible 
      boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0; 
      // check if the top of the first item is visible 
      boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0; 
      // enabling or disabling the refresh layout 
      enable = firstItemVisible && topOfFirstItemVisible; 
     } 
     if(enable){ 
      enableSwipe(); 

     }else{ 
      disableSwipe(); 

     } 
    } 
}); 
+0

tuo ListView dovrebbe avere quindi> 'listView.setOnScrollListener (...)' – deadfish

+0

Sono già usando 'listView .setOnScrollListener (...) 'in cui m usando il metodo' onScroll' menzionato sopra. –

risposta

4

Ho appena guardato in the documentation del SwipeRefreshLayout e penso accennano quello che stai cercando:

... Se l'ascoltatore determina non ci dovrebbe essere un aggiornamento, deve chiamata setRefreshing(false) di annullare qualsiasi indicazione visiva di un aggiornamento . Se un'attività vuole mostrare solo l'animazione di avanzamento, lo deve chiamare setRefreshing(true). Per disattivare il gesto e l'animazione di avanzamento , chiamare setEnabled(false) sulla vista.

in modo da avere un paio di opzioni, vorrei in primo luogo provare a giocare con setEnabled() o setRefreshing(), ma usare correttamente questi metodi abbiamo prima bisogno di essere in grado di rilevare se il ListView è veloce scorrimento. Non c'è nessun ascoltatore o altro per lo scorrimento veloce, ma puoi ottenere lo stato attraverso il riflesso! Sulla base di this excellent and seriously underrated answer Ho scritto un FastScrollListener che può essere utilizzato come un OnScrollListener:

this.listView.setFastScrollEnabled(true); 
this.listView.setOnScrollListener(new FastScrollListener(this.listView) { 

    @Override 
    protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) { 
     // This line disabled the SwipeRefreshLayout 
     // whenever the user is fast scrolling 
     swipeRefreshLayout.setEnabled(state != FastScrollState.DRAGGING); 
    } 

    @Override 
    protected void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

    } 
}); 

Si potrebbe anche provare a chiamare setRefreshing() invece di setEnabled() se setEnabled() non funziona.

E qui è il codice del FastScrollListener:

public abstract class FastScrollListener implements AbsListView.OnScrollListener { 

    private final int STATE_DRAGGING; 
    private final int STATE_VISIBLE; 
    private final int STATE_NONE; 

    public enum FastScrollState { 
     DRAGGING, 
     VISIBLE, 
     NONE, 
     UNKNOWN 
    } 

    private FastScrollState fastScrollState = FastScrollState.UNKNOWN; 
    private Field stateField; 
    private Object mFastScroller; 

    public FastScrollListener(AbsListView listView) { 
     try { 
      final Field fastScrollerField = AbsListView.class.getDeclaredField("mFastScroller"); 
      fastScrollerField.setAccessible(true); 
      mFastScroller = fastScrollerField.get(listView); 

      final Field stateDraggingField = mFastScroller.getClass().getDeclaredField("STATE_DRAGGING"); 
      stateDraggingField.setAccessible(true); 
      STATE_DRAGGING = stateDraggingField.getInt(mFastScroller); 

      final Field stateVisibleField = mFastScroller.getClass().getDeclaredField("STATE_VISIBLE"); 
      stateVisibleField.setAccessible(true); 
      STATE_VISIBLE = stateVisibleField.getInt(mFastScroller); 

      final Field stateNoneField = mFastScroller.getClass().getDeclaredField("STATE_NONE"); 
      stateNoneField.setAccessible(true); 
      STATE_NONE = stateNoneField.getInt(mFastScroller); 

      stateField = mFastScroller.getClass().getDeclaredField("mState"); 
      stateField.setAccessible(true); 
      fastScrollState = getFastScrollState(); 

     } catch (NoSuchFieldException e) { 
      throw new IllegalStateException("Could not find required fields for fast scroll detection!", e); 
     } catch (IllegalAccessException e) { 
      throw new IllegalStateException("Could not find required fields for fast scroll detection!", e); 
     } 
    } 

    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) { 
     updateFastScrollState(view); 
    } 

    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
     updateFastScrollState(view); 
     updateFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); 
    } 

    private void updateFastScrollState(AbsListView view) { 
     if (stateField != null) { 
      final FastScrollState state = getFastScrollState(); 
      if (fastScrollState != state) { 
       fastScrollState = state; 
       onFastScrollStateChanged(view, state); 
      } 
     } 
    } 

    private void updateFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
     if(fastScrollState == FastScrollState.DRAGGING) { 
      onFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); 
     } 
    } 

    private FastScrollState getFastScrollState() { 

     try { 
      final int state = stateField.getInt(mFastScroller); 

      if (state == STATE_DRAGGING) { 
       return FastScrollState.DRAGGING; 
      } 

      if (state == STATE_VISIBLE) { 
       return FastScrollState.VISIBLE; 
      } 

      if (state == STATE_NONE) { 
       return FastScrollState.NONE; 
      } 

      return FastScrollState.UNKNOWN; 
     } catch (IllegalAccessException e) { 
      throw new IllegalStateException("Could not read fast scroll state!", e); 
     } 
    } 

    protected abstract void onFastScrollStateChanged(AbsListView view, FastScrollState state); 

    protected abstract void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount); 
} 

Spero di poter aiutare e se avete ulteriori domande non esitate a chiedere!


EDIT: Prova questo, ma dubito che funzionerà:

@Override 
protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) { 
    boolean enable = false; 
    if (getListView().getChildCount() > 0) { 
     boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0; 
     boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0; 
     enable = firstItemVisible && topOfFirstItemVisible; 
    } 
    refreshLayout.setEnabled(enable); 
} 
+0

Errore su public enum FastScrollStat {...} ** "L'enum membro FastScrollState deve essere definito all'interno di un tipo di membro statico" ** –

+0

Questo perché hai annidato "FastScrollListener" all'interno di un'altra classe. Se vuoi nidificare 'FastScrollListener' devi renderlo statico come questo:' public static abstract class FastScrollListener implements AbsListView.OnScrollListener {...} '. –

+0

Ora, quando trascino, il 'pollice' rimane bloccato a **' A' **/posizione iniziale e non scende mai –

Problemi correlati