33

Ich habe zwei Aktivitäten AppBarLayout mit einem Toolbar und TabLayout von Unterstützungsbibliothek 22ScrollingViewBehavior für Listview

Das Layout sowohl verwenden, ist ziemlich ähnlich: Toolbar A an der Spitze, darunter TabLayout, darunter ein ViewPager 3 enthält, Fragment s.

Fragment Die erste Aktivität hat eine RecyclerView, die Fragment zweite Aktivität eine ListView statt verwendet.

Das rollbare Toolbar Beispiel von https://github.com/chrisbanes/cheesesquare arbeiten an der ersten Aktivität Fein die RecyclerView verwenden, sondern mit den ListView.

Ich habe versucht, eine benutzerdefinierte ListViewScrollBehavior erstellt, die AppBarLayout.ScrollingViewBehavior erweitert, aber bis jetzt kein Glück. Die TouchEvent s werden nur zum horizontalen Scrollen an die benutzerdefinierte Klasse übergeben, aber nicht beim Scrollen des ListView (vertikal).

Gibt es eine Möglichkeit, CoordinatorLayout mit ListView zu verwenden?

+0

Wenn Sie wirklich ein Tag erstellen müssen, dann erstellen Sie mindestens ein richtig benanntes. [tag: coordinator-layout] ist der falsche Name. Wenn du jemals die Tag-Beschreibung von [tag: android] gelesen hättest, wüsstest du: "Wenn du zusätzliche Tags zu Fragen hinzufügst, verwende bitte die Android-spezifischen Tags wie [tag: android-intent] und [tag: android-activity ], nicht [tag: intent] und [tag: activity]. ". Das korrekte Tag sollte also [Tag: android-coordinator-layout] sein und statt [tag: recyclerview] sollten Sie [tag: android-recyclerview] verwenden. –

+0

Das gleiche gilt für [tag: listview], Sie sollen [tag: android-listview] verwenden. –

+0

ok, hab es.Normalerweise benutze ich nur die populärste, und bei der Suche nach diesen Tags waren die ohne 'android-' viel beliebter – marmor

Antwort

35

der einzigen Lösung, um es jetzt funktioniert, dies zu nutzen:

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

Es wird offensichtlich nur auf Lollipop arbeiten.

+2

Interessanter Fund! Ich werde die Antwort akzeptieren, hoffe aber immer noch auf eine rückwärtskompatible Lösung. – marmor

+1

Ich stimme zu. Ein 'NestedScrollingListView' würde wirklich geschätzt werden. –

+0

danke. aber es funktioniert nur für lollypop. Kannst du mir bitte sagen, wie es in niedrigeren Versionen funktioniert? –

11

Ich glaube, dass die CoordinatorLayout nur mit RecyclerView und NestedScrollView arbeitet. Versuchen Sie, Ihre ListView in einem NestedScrollView Einwickeln oder wandeln sie in ein RecyclerView mit einer LinearLayoutManager

+1

Hochschalten Es sieht so aus, als wäre Behavior eine erweiterbare Klasse, die dazu da ist, Unterstützung für die Koordination von mehr Klassen hinzuzufügen, also denke ich, dass es möglich ist. Aber ohne Dokumentation, Samples oder Quellcode, um es zu erklären, finde ich es schwierig zu verstehen, wie es funktioniert. – marmor

+0

Ich habe auf meiner App getestet und 'CoordinatorLayout' funktioniert nur mit' RecyclerView' –

+0

CoordinatorLayout arbeitet mit 'RecyclerView' und jeder anderen Scrollansicht, die' NestedScrollView' unterstützt. Es scheint jedoch Klassen zu geben, die dieses Verhalten auf mehr scrollende Klassen wie "ListView" erweitern. Ich hoffe, dass jemand in der Lage ist, einen funktionierenden Code dafür zu zeigen. Bis jetzt zeigt die akzeptierte Antwort, wie man 'ListView' mit dem Koordinator für API> = Lollipop arbeiten lässt. – marmor

12

Alternative Lösung Nicolas POMEPUY's answer ist ViewCompat.setNestedScrollingEnabled(View, boolean)

ViewCompat.setNestedScrollingEnabled(listView, true); 

Natürlich Verhalten verschachtelt verwenden Scrollen wird nur von Lollipop arbeiten.

+0

Ist die compat-Bibliothek nicht kompatibel mit früheren Versionen? – sivi

+2

Es macht den Code kompiliert und fällt fälschlicherweise in früheren Versionen zurück, in einigen Fällen funktioniert es auch nahtlos, aber das ist nicht immer der Fall. – hidro

5

Um eine Ansicht auf AppBarLayout reagieren zu können, muss NestedScrollingChild implementiert werden. ListView ist nicht. Aber es könnte leicht von einer Delegiertenklasse implementiert werden. Verwenden Sie es, wird es tun, wie das, was RecyclerView tat

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

Wird es unter Lollipop funktionieren? –

+0

Ja, das hängt nicht von der Android-Version ab. Aber wenn wir können, verwendet nur RecyclerView –

+0

Wirklich nicht korrekt auf Pre-Lollipop. Es scrollt die Symbolleiste nur, wenn Sie in der Symbolleiste blättern. Wenn Sie ListView selbst scrollen - es scrollt nicht Symbolleiste, sondern scrollt nur ListView – krossovochkin

1

Listview ScrollingViewBehavior unterstützt nur> = 21

Andernfalls sollten Sie schreiben Code wie unten Art und Weise:

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

interessant, könnte für mich gearbeitet haben, aber ich habe alle meine ListViews auf RecyclerViews eine lange Zeit wegen solcher Einschränkungen geschaltet. – marmor

+0

Ich habe diesen Code für expandableListView verwendet. Aber diese Codes funktionieren auch für ListView & Expandable Listview. Ich benutze auch Recyclerview. und es ist gut für mich. Aber es gibt keine offizielle Bibliothek für expandableRecyclerview. Deshalb benutze ich expandableListView. –