5

Come rilevare se l'azione nidificata si è interrotta completamente utilizzando CoordinatorLayout.Behavior? Non esiste questa api che può darmi il richiamo quando l'immagine del riciclatore si ferma completamente.Come rilevare l'apertura nidificata arrestata in CoordinatorLayout.Behavior?

+0

Non è possibile ottenere lo stesso con 'SCROLL_STATE_IDLE'? –

+0

Non esiste alcun metodo come onScrollStateChanged (vista AbsListView, int scrollState) in CoordinatorLayout.Behavior che può darmi scrollState. C'è un metodo chiamato onStopNestedScroll ma viene chiamato prima che l'elenco si interrompa completamente. – shekar

+0

Intendevo 'onScrollChanged()' per 'RecyclerView' –

risposta

6

Ho iniziato questa tana del coniglio mentre cercavo di nascondere uno Floating Action Button (FAB) quando uno RecyclerView veniva fatto scorrere. Il modo corretto per in base a più sources è di estendere FloatingActionButton.Behavior, sovrascrivere i metodi onStartNestedScroll e onStopNestedScroll e agganciare il comportamento al FAB, ad es. app:layout_behavior="com.justingarrick.ui.ScrollAwareFabBehavior". Questo funziona per gli eventi di scorrimento normale (lento), ma onStopNestedScroll non viene chiamato quando termina un'avventura.

Attualmente, sembra esserci un numero di issues aperto con comportamenti di scorrimento e scorrimento; la soluzione per me era implementare un OnScrollListener per il mio RecyclerView e cambiare semplicemente lo stato del FAB a livello di codice, ad es.

public class MyFragment extends Fragment { 

    @Bind(R.id.account_list) RecyclerView recyclerView; 
    @Bind(R.id.button_fab) FloatingActionButton fab; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_accounts, container, false); 
     ButterKnife.bind(this, view); 

     recyclerView.setLayoutManager(layoutManager); 
     recyclerView.setAdapter(adapter); 
     recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 
      @Override 
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
       super.onScrollStateChanged(recyclerView, newState); 
       if (newState == RecyclerView.SCROLL_STATE_DRAGGING) 
        fab.hide(); // or hideFab(), see below 
       else if (newState == RecyclerView.SCROLL_STATE_IDLE) 
        fab.show(); // or showFab(), see below 
      } 
     }); 

     return view; 
    } 
} 

UPDATE: Questo funziona correttamente il 99% del tempo, ma se si utilizza il show() e hide() metodi dalla versione 22.2.1 della libreria di progettazione, si incorrerà in problemi quando si tenta di scorrere nella parte superiore di RecyclerView o nella parte inferiore di RecyclerView poiché la visualizzazione del riciclatore sta passando da RecyclerView.SCROLL_STATE_DRAGGING a RecyclerView.SCROLL_STATE_IDLE così rapidamente da creare una condizione di competizione in FloatingActionButtonHoneycombMr1#show(). Pertanto, per risolvere il problema (sospiro), devi passare alle chiamate setVisibility() se non ti interessa le animazioni o implementare nuovamente le animazioni senza condizioni di competizione, ad es.

private void hideFab() { 
    fab.animate().scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setDuration(200L).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() { 
     @Override 
     public void onAnimationEnd(Animator animation) { 
      fab.setVisibility(View.GONE); 
     } 
    }); 
} 

private void showFab() { 
    fab.animate().scaleX(1.0F).scaleY(1.0F).alpha(1.0F).setDuration(200L).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() { 
     @Override 
     public void onAnimationStart(Animator animation) { 
      fab.setVisibility(View.VISIBLE); 
     } 
    }); 
} 
+0

Grazie per la risposta, almeno non sono solo chi ha affrontato questo problema. – shekar

+0

Brillante soluzione semplice! Avevo bisogno di mostrare il FAB solo quando una vista specifica nella vista di scorrimento era visibile e nascosta quando quella vista era fuori dallo schermo. Con il Comportamento, era impossibile gestire i lanci ... Con l'ascoltatore di scroll funziona perfettamente! –

0

Uso ScrollerCompat con metodo ScrollerCompat.fling (..) per gestire gli stati intermedi di scorrimento. Quindi so quando lo scorrimento è finito.

@Override 
public boolean onNestedFling(final CoordinatorLayout coordinatorLayout, final AppBarLayout child, final View target, final float velocityX, final float velocityY, final boolean consumed) { 
    final int scrollY = target.getScrollY(); 
    final double distance = mFlingHelper.getSplineFlingDistance(velocityY); 

    fling(
      child, 
      (int) distance + scrollY, 
      velocityY, 
      scrollY); 

    return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); 
} 

private void fling(final View pChild, final int pMaxOffset, final float pVelocityY, final int pStartY) { 
    stopFling(pChild); 
    mIsFlingRunning = true; 

    if (mScroller == null) { 
     mScroller = ScrollerCompat.create(mContext); 
    } 

    mScroller.fling(
     0, pStartY, // current 
     0, Math.round(pVelocityY), // velocity. 
     0, 0, // x 
     0, pMaxOffset); // y 

    if (mScroller.computeScrollOffset()) { 
     mFlingRunnable = new FlingRunnable(pChild); 
     ViewCompat.postOnAnimation(pChild, mFlingRunnable); 
    } 

} 

private void stopFling(final View pChild) { 
    if (mFlingRunnable != null) { 
     pChild.removeCallbacks(mFlingRunnable); 
     mFlingRunnable = null; 
    } 
} 




private class FlingRunnable implements Runnable { 

    private final View mView; 

    FlingRunnable(final View pView) { 
     mView = pView; 
    } 

    @Override 
    public void run() { 
     if (mView != null && mScroller != null) { 
      if (mScroller.computeScrollOffset()) { 
       mIsFlingRunning = true; 
       // Post ourselves so that we run on the next animation 
       ViewCompat.postOnAnimation(mAppBarLayout, this); 
      } 
     } else { 
      mIsFlingRunning = false; 
     } 
    } 
}