Mit Unterstützung-v4-Bibliothek 22.1.0 Android unterstützt geschachteltes Scrollen (Pre-Android 5.0). Leider ist diese Funktion nicht wirklich dokumentiert. Es gibt zwei Schnittstellen (NestedScrollingParent
und NestedScrollingChild
) sowie zwei Helfer-Delegate-Klassen (NestedScrollingChildHelper
und NestedScrollingParentHelper
).Wie Implementiere NestedScrolling auf Android?
Hat jemand mit NestedScrolling auf Android gearbeitet?
Ich habe versucht, ein kleines Beispiel einzurichten, wo ich NestedScrollView verwende, die beide NestedScrollingParent
und NestedScrollingChild
implementiert.
Mein Layout sieht wie folgt aus:
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/header"
android:layout_width="match_parent" android:layout_height="100dp"
android:background="#AF1233"/>
<android.support.v4.widget.NestedScrollView
android:id="@+id/child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#12AF33"
android:text="@string/long_text"/>
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
ich eine header view
und andere NestedScrollView
(id = Kind) in einer NestedScrollView
(id = parent) angezeigt werden sollen.
Die Idee war, unter Verwendung einer der Höhe der Kind Scroll-Ansicht zur Laufzeit anpassen OnPredrawListener
:
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final NestedScrollView parentScroll = (NestedScrollView) findViewById(R.id.parent);
final NestedScrollView nestedScroll = (NestedScrollView) findViewById(R.id.child);
parentScroll.setNestedScrollingEnabled(false);
final View header = findViewById(R.id.header);
parentScroll.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override public boolean onPreDraw() {
if (parentScroll.getHeight() > 0) {
parentScroll.getViewTreeObserver().removeOnPreDrawListener(this);
nestedScroll.getLayoutParams().height = parentScroll.getHeight() - 40;
nestedScroll.setLayoutParams(nestedScroll.getLayoutParams());
nestedScroll.invalidate();
return false;
}
return true;
}
});
}
}
So wird die Kopfansicht teilweise gescrollt entfernt wird, werden 40 Pixel sichtbar bleiben, da ich die eingestellte Höhe der geschachtelten untergeordneten Ansicht von unter parentScroll.getHeight() - 40
. In Ordnung, die Höhe zur Laufzeit und Scrollen der übergeordneten Bildlaufansicht funktioniert wie erwartet (Header scrollt heraus, 40 Pixel bleiben sichtbar und dann füllt der untergeordnete scrollview den Rest des Bildschirms unterhalb der Kopfzeile).
Ich würde erwarten, dass „NestedScrolling“ bedeutet, dass ich irgendwo eine Scroll-Geste auf dem Bildschirm machen kann (Touch-Ereignis gefangen durch Scroll-Ansicht Elternteil) und wenn die übergeordnete Ansicht blättern, das Ende des verschachtelte Kind Scroll-Ansicht beginn blättern erreicht hat . Dies scheint jedoch nicht der Fall zu sein (weder für einfache Scroll-Gesten noch für Fling-Gesten).
Das Berührungsereignis wird immer von verschachtelten untergeordneten Scrollviews behandelt, wenn das Berührungsereignis in seinen Grenzen beginnt, andernfalls vom übergeordneten Scrollview.
Ist das das erwartete Verhalten von "verschachteltem Scrollen" oder gibt es eine Option, dieses Verhalten zu ändern?
Ich habe auch versucht, die verschachtelte untergeordnete Ansicht mit einem NestedRecyclerView
zu ersetzen. Ich subclassed RecyclerView
und umgesetzt NestedScrollingChild
, wo ich alle Methoden zu NestedScrollingChildHelper
delegieren:
public class NestedRecyclerView extends RecyclerView implements NestedScrollingChild {
private final NestedScrollingChildHelper scrollingChildHelper =
new NestedScrollingChildHelper(this);
public void setNestedScrollingEnabled(boolean enabled) {
scrollingChildHelper.setNestedScrollingEnabled(enabled);
}
public boolean isNestedScrollingEnabled() {
return scrollingChildHelper.isNestedScrollingEnabled();
}
public boolean startNestedScroll(int axes) {
return scrollingChildHelper.startNestedScroll(axes);
}
public void stopNestedScroll() {
scrollingChildHelper.stopNestedScroll();
}
public boolean hasNestedScrollingParent() {
return scrollingChildHelper.hasNestedScrollingParent();
}
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
return scrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed, offsetInWindow);
}
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return scrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return scrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return scrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}
}
aber die NestedRecyclerView
gar nicht bewegen. Alle Berührungsereignisse werden von der übergeordneten Bildlaufansicht abgefangen.
Ich habe das gleiche Problem und denke, dass dieses Widget verbessert werden sollte, um Eltern zu ermöglichen, unverbrauchten Scroll zu seinem Kind zu schicken. –
Ich denke, Recycler-View zu einem NestedScrollingChild machen ist nicht so einfach, da es den LayoutManager zum Scrollen und Positionieren seines Elements verwendet. Daher funktioniert nur die Implementierung von NestedScrollingChild mit NestedScrollingChildHelper nicht, da diese Funktionen beim Scrollen nicht aufgerufen werden. –
Ich bin mir nicht sicher. Ich nehme an, dass NestedScrollingParent/NestedScrollingChild verwendet wird, um das Touch-Ereignis weiterzuleiten. Ich hoffe, dass 'NestedScrollingChild' dies intern tut, ich kann keinen Grund sehen, warum es für' ScrollView' funktionieren sollte, aber nicht für 'RecyclerView' ...' LayoutManager' sollte kein Problem sein ... – sockeqwe