33

Ho due attività utilizzando AppBarLayout con un Toolbar e TabLayout dalla libreria di supporto 22.ScrollingViewBehavior per ListView

Il layout di entrambi è abbastanza simile: A Toolbar in alto, sotto TabLayout, sotto un ViewPager contenente 3 Fragment s.

Il primo attività Fragment ha un RecyclerView, del secondo Fragment attività sta usando un ListView invece.

L'scorrevole Toolbar esempio da https://github.com/chrisbanes/cheesesquare funzioni bene al primo all'attività utilizzando il RecyclerView, ma con la ListView.

Ho provato a creare un numero personalizzato ListViewScrollBehavior che si estende AppBarLayout.ScrollingViewBehavior, ma finora senza fortuna. Gli sTouchEvent vengono passati alla classe personalizzata solo per lo scorrimento orizzontale, ma non quando si scorre lo ListView (in verticale).

Un modo per utilizzare uno CoordinatorLayout con ListView?

+0

Se devi davvero creare un tag, crea almeno un nome appropriato. [tag: coordinator-layout] è il nome sbagliato. Se avessi mai letto la descrizione del tag [tag: android], allora sapresti: "Quando aggiungi tag aggiuntivi alle domande, utilizza i tag specifici di Android come [tag: android-intent] e [tag: android-activity ], non [tag: intent] e [tag: activity]. ". Quindi il tag corretto dovrebbe essere [tag: android-coordinator-layout] e invece di [tag: recyclerview] dovresti usare [tag: android-recyclerview]. –

+0

Lo stesso vale per [tag: listview], dovresti usare [tag: android-listview]. –

+0

ok, capito.Di solito uso solo il più popolare, e quando cercavo questi tag quelli con 'android-' erano molto più popolari – marmor

risposta

35

L'unica soluzione per farlo funzionare è ora di usare questo:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    listView.setNestedScrollingEnabled(true); 
} 

Sarà ovviamente funziona solo su Lollipop.

+2

Scoperta interessante! Accetterò la risposta, ma spero ancora che qualcuno possa fornire una soluzione più compatibile con le versioni precedenti. – marmor

+1

Sono d'accordo. Un 'NestedScrollingListView' sarebbe molto apprezzato. –

+0

grazie. ma funziona solo per lollypop. puoi dirmi come farlo funzionare nelle versioni inferiori –

11

Credo che lo CoordinatorLayout funzioni solo con RecyclerView e NestedScrollView. Provare avvolgendo il ListView in un NestedScrollView o convertirlo in un RecyclerView con un LinearLayoutManager

+1

E ' sembra che Behaviour sia una classe estendibile che serve per aggiungere supporto al coordinamento di più classi, quindi penso che sia possibile. Tuttavia, senza alcuna documentazione, esempi o codice sorgente per spiegarlo, trovo difficile capire come funziona. – marmor

+0

Ho provato la mia app e 'CoordinatorLayout' funziona solo con' RecyclerView' –

+0

CoordinatorLayout funziona con 'RecyclerView' e qualsiasi altra vista a scorrimento che supporta' NestedScrollView'. Tuttavia, sembrano esserci classi che forniscono questo comportamento per estendere a più classi di scorrimento come 'ListView', spero che qualcuno possa essere in grado di mostrare un codice funzionante per questo. Finora la risposta accettata mostra come far funzionare 'ListView' con Coordinator per API> = Lollipop. – marmor

12

soluzione alternativa al Nicolas POMEPUY's answer è quello di utilizzare ViewCompat.setNestedScrollingEnabled(View, boolean)

ViewCompat.setNestedScrollingEnabled(listView, true); 

Naturalmente annidato scorrimento comportamento funzionerà solo da Lollipop.

+0

La libreria compatibile non lo rende compatibile con le versioni precedenti? – sivi

+2

Rende il codice compilato e con grazia ricade nelle versioni precedenti, in alcuni casi può anche funzionare perfettamente, ma non è sempre così. – hidro

5

Per una vista in grado di reagire su AppBarLayout, è necessario implementare NestedScrollingChild. ListView no. Ma potrebbe essere implementato facilmente da una classe di delegati. Usalo, lo farà come quello che ha fatto RecyclerView

public class NestedScrollingListView extends ListView implements NestedScrollingChild { 
private NestedScrollingChildHelper mNestedScrollingChildHelper; 

public NestedScrollingListView(final Context context) { 
    super(context); 
    initHelper(); 
} 

public NestedScrollingListView(final Context context, final AttributeSet attrs) { 
    super(context, attrs); 
    initHelper(); 
} 

public NestedScrollingListView(final Context context, final AttributeSet attrs, final int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    initHelper(); 
} 

@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
public NestedScrollingListView(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) { 
    super(context, attrs, defStyleAttr, defStyleRes); 
    initHelper(); 
} 

private void initHelper() { 
    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this); 
    setNestedScrollingEnabled(true); 
} 

@Override 
public void setNestedScrollingEnabled(final boolean enabled) { 
    mNestedScrollingChildHelper.setNestedScrollingEnabled(enabled); 
} 

@Override 
public boolean isNestedScrollingEnabled() { 
    return mNestedScrollingChildHelper.isNestedScrollingEnabled(); 
} 

@Override 
public boolean startNestedScroll(final int axes) { 
    return mNestedScrollingChildHelper.startNestedScroll(axes); 
} 

@Override 
public void stopNestedScroll() { 
    mNestedScrollingChildHelper.stopNestedScroll(); 
} 

@Override 
public boolean hasNestedScrollingParent() { 
    return mNestedScrollingChildHelper.hasNestedScrollingParent(); 
} 

@Override 
public boolean dispatchNestedScroll(final int dxConsumed, final int dyConsumed, final int dxUnconsumed, final int dyUnconsumed, final int[] offsetInWindow) { 
    return mNestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); 
} 

@Override 
public boolean dispatchNestedPreScroll(final int dx, final int dy, final int[] consumed, final int[] offsetInWindow) { 
    return mNestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); 
} 

@Override 
public boolean dispatchNestedFling(final float velocityX, final float velocityY, final boolean consumed) { 
    return mNestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); 
} 

@Override 
public boolean dispatchNestedPreFling(final float velocityX, final float velocityY) { 
    return mNestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); 
} 

}

+1

Funzionerà sotto Lollipop? –

+0

Sì, non dipende dalla versione di Android. Ma se possiamo, utilizza solo RecyclerView –

+0

In realtà non funziona correttamente su pre-lollipop. Scorre la barra degli strumenti solo quando si scorre sulla barra degli strumenti. Quando si scorre listView stesso - non scorre la barra degli strumenti, ma scorre solo listaView – krossovochkin

1

ListView ScrollingViewBehavior supporta solo> = codice 21.

In caso contrario si dovrebbe scrivere come di seguito modo:

private int mPreviousVisibleItem; 


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    listView.setNestedScrollingEnabled(true); 
} else { 
    listView.setOnScrollListener(new AbsListView.OnScrollListener() { 
     @Override 
     public void onScrollStateChanged(AbsListView view, int scrollState) { 
     } 
     @Override 
     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
      if (firstVisibleItem > mPreviousVisibleItem) { 
       appBarLayout.setExpanded(false, true); 
      } else if (firstVisibleItem < mPreviousVisibleItem) { 
       appBarLayout.setExpanded(true, true); 
      } 
      mPreviousVisibleItem = firstVisibleItem; 
     } 
    }); 
} 
+1

interessante, potrebbe aver funzionato per me, ma ho passato tutte le mie ListViews a RecyclerViews a lungo a causa di tali limitazioni. – marmor

+0

Ho usato quel codice per espandibileListView. Ma questo codice funziona anche per listview e expandablelistview. Sto anche usando anche recyclerview. e va bene per me. Ma non ci sono librerie ufficiali per Expandecyclerview. Ecco perché sto usando expandableListView. –