41

Ci sono comunque per rendere più scorrevole l'animazione collassata della libreria di supporto di Android Design durante lo scorrimento? Quando rilascio lo scorrimento, si interrompe improvvisamente. Ma quello che voglio è: l'animazione collassante continuerà senza intoppi anche se smetti di scorrere. Android-ObservableScrollView e Scrollable sono le librerie che stanno crollando senza intoppi.Smooth Barra degli strumenti collassabile animata con libreria di supporto di progettazione Android

+1

A [domanda simile] (http://stackoverflow.com/questions/30923889/flinging-with -recyclerview-appbarlayout) è stato chiesto, che rimanda a [questo problema] (https://code.google.com/p/android/issues/detail?id=177729). Sembra quindi che questo sia un bug che verrà risolto quando verrà rilasciata la versione 23 della libreria. –

+0

Cerca di capire il codice di questa libreria [Smooth App Bar] (https://github.com/henrytao-me/smooth-app-bar-layout). –

risposta

6

Questo è abbastanza nuovo, ma l'AppBarLayout è stato aggiornato di recente per gestire esattamente quello che stai cercando con un nuovo layout_scrollFlag chiamato snap.

Usage:

app:layout_scrollFlags="scroll|snap" 

proverò a cercare la mia fonte e aggiornare la mia risposta quando lo faccio.

Modifica: Naturalmente, è dal android developer blog.

2

codice aggiuntivo

app:layout_scrollFlags="scroll|enterAlways" 

nella vista all'interno del AppBarLayout. Questo è il mio codice demo che comprime la barra degli strumenti con Android Design Support Library.

<android.support.design.widget.AppBarLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/ThemeOverlay.AppCompat.Dark"> 
     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:layout_scrollFlags="scroll|enterAlways"> 

      <bubee.inews.Items.ItemMenu 
       android:id="@+id/itemMenu" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" /> 
     </android.support.v7.widget.Toolbar> 
    </android.support.design.widget.AppBarLayout> 
+0

Perfetto, finalmente avere una scroll scorrevole. –

+0

Questo non sta comprimendo la barra degli strumenti. –

0

Sto lavorando su questo problema troppo e sono venuto su con non può molto soluzione ottimizzata, ma si può migliorare it.Once miglioro che mi sarà sicuramente modificare la risposta fino al dare un'occhiata a questo.

public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { 
private static final String TAG = "app_AppBarStateChange"; 
public enum State { 
    EXPANDED, 
    COLLAPSED, 
    IDLE 
} 

private State mCurrentState = State.IDLE; 
private int mInitialPosition = 0; 
private boolean mWasExpanded; 
private boolean isAnimating; 
@Override 
public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { 
    if (i == 0) { 
     if (mCurrentState != State.EXPANDED) { 
      onStateChanged(appBarLayout, State.EXPANDED); 
     } 
     mCurrentState = State.EXPANDED; 
     mInitialPosition = 0; 
     mWasExpanded = true; 
     Log.d(TAG, "onOffsetChanged 1"); 
     isAnimating = false; 
     appBarLayout.setEnabled(true); 
    } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { 
     if (mCurrentState != State.COLLAPSED) { 
      onStateChanged(appBarLayout, State.COLLAPSED); 
     } 
     mCurrentState = State.COLLAPSED; 
     mInitialPosition = appBarLayout.getTotalScrollRange(); 
     mWasExpanded = false; 
     Log.d(TAG, "onOffsetChanged 2"); 
     isAnimating = false; 
     appBarLayout.setEnabled(true); 
    } else { 
     Log.d(TAG, "onOffsetChanged 3"); 
     int diff = Math.abs(Math.abs(i) - mInitialPosition); 
     if(diff >= appBarLayout.getTotalScrollRange()/3 && !isAnimating) { 
      Log.d(TAG, "onOffsetChanged 4"); 
      isAnimating = true; 
      appBarLayout.setEnabled(false); 
      appBarLayout.setExpanded(!mWasExpanded,true); 
     } 
     if (mCurrentState != State.IDLE) { 
      onStateChanged(appBarLayout, State.IDLE); 
     } 
     mCurrentState = State.IDLE; 
    } 
} 

public abstract void onStateChanged(AppBarLayout appBarLayout, State state); 

public State getCurrentState() { 
    return mCurrentState; 
} 

}

Creare questa classe e la chiamata seguente codice

private AppBarStateChangeListener mAppBarStateChangeListener = new AppBarStateChangeListener() { 
    @Override 
    public void onStateChanged(AppBarLayout appBarLayout, State state) { 
     Log.d(TAG, "ToBeDeletedActivity.onStateChanged :: " + state); 
     if(state == State.EXPANDED || state == State.IDLE) { 
      getSupportActionBar().setTitle(""); 
     } else { 
      getSupportActionBar().setTitle("Hello World"); 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       mAppBarLayout.setElevation(0); 
      } 
     } 
    } 


}; 

mAppBarLayout.addOnOffsetChangedListener(mAppBarStateChangeListener); 

Nota che non impostato annonymous classe OffsetChangedListener in quanto questo viene mantenuto come riferimento debole e saranno raccolti da GC.I trovato me stesso in modo duro.

Si prega di esplorare questo codice e migliorarla (nessuno) e ri-share .thanks

10

È possibile utilizzare la nuova layout_scrollFlag scatto per scorrere liscia all'interno degli stati AppBarLayout. Ma quello che ho sperimentato è che, quando RecyclerView raggiunge il massimo, lo scorrimento si interrompe. Il CollapseingToolbarLayout non verrà espanso senza un altro scorrimento. Per il RecyclerView per scorrere senza problemi ed espandere il CollapsingToolbarLayout ho usato un ScrollListener su recyclerview.

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 
     int scrollDy = 0; 
     @Override 
     public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
      scrollDy += dy; 
     } 

     @Override 
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
      super.onScrollStateChanged(recyclerView, newState); 
      if(scrollDy==0&&(newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE)) 
      { 
       AppBarLayout appBarLayout = ((AppBarLayout) view.findViewById(R.id.app_bar)); 

       appBarLayout.setExpanded(true); 
      } 
     } 
    }); 

Ho usato "scroll | exitUntilCollapsed" come layout_scrollFlags.

<android.support.design.widget.CollapsingToolbarLayout 
      android:id="@+id/collapsing_toolbar_layout" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:fitsSystemWindows="true" 
      android:minHeight="80dp" 
      app:layout_collapseMode="none" 
      app:layout_scrollFlags="scroll|exitUntilCollapsed"> 
+1

Buona soluzione ma c'è una differenza di velocità tra lo scroll e l'espansione :) –

+1

Soluzione troppo buona. Risolto il mio problema ... Grazie –

+1

Grazie fratello, è una buona soluzione, hai risparmiato il mio tempo – FarshidABZ

0

Prova ad aggiungere il seguente codice:

app:layout_scrollFlags="scroll|snap" 
3

lo sto facendo attraverso AppBarLayout. ignorando onNestedFling e onNestedPreScroll.

Il trucco è di riconsiderare l'evento di fling se il figlio superiore di ScrollingView è vicino all'inizio dei dati in Adapter.

Fonte Flinging with RecyclerView + AppBarLayout

public final class FlingBehavior extends AppBarLayout.Behavior { 
private static final int TOP_CHILD_FLING_THRESHOLD = 3; 
private boolean isPositive; 

public FlingBehavior() { 
} 

public FlingBehavior(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 
@Override 
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) { 
    if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) { 
     velocityY = velocityY * -1; 
    } 
    if (target instanceof RecyclerView && velocityY < 0) { 
     final RecyclerView recyclerView = (RecyclerView) target; 
     final View firstChild = recyclerView.getChildAt(0); 
     final int childAdapterPosition = recyclerView.getChildAdapterPosition(firstChild); 
     consumed = childAdapterPosition > TOP_CHILD_FLING_THRESHOLD; 
    } 
    return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); 
} 

@Override 
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { 
    super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); 
    isPositive = dy > 0; 
    } 
} 

quindi impostare il comportamento layout FlingBehavior classe

<android.support.design.widget.AppBarLayout 
app:layout_behavior="package.FlingBehavior" 
android:id="@+id/appbar" 
android:layout_width="match_parent" 
android:layout_height="250dip" 
android:fitsSystemWindows="true">