使用support-v4庫22.1.0 android支持嵌套滾動(pre android 5.0)。不幸的是,這個功能沒有真正的記錄。有兩個接口(NestedScrollingParent
和NestedScrollingChild
)以及兩個輔助代表類(NestedScrollingChildHelper
和NestedScrollingParentHelper
)。如何在Android上實現NestedScrolling?
有沒有人在Android上使用NestedScrolling?
我試圖設置一個小例子,我使用NestedScrollView,它實現了NestedScrollingParent
和NestedScrollingChild
。
我的佈局是這樣的:
<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>
我想顯示在NestedScrollView
(ID =父),一個header view
和另一NestedScrollView
(ID =小孩)。
的想法是,通過使用調整在運行時子滾動視圖的高度的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;
}
});
}
}
所以頭部視圖將被滾動遠部分,40個像素將保持可見,因爲我設置嵌套子滾動視圖的高度爲parentScroll.getHeight() - 40
。 好了,在運行時設置高度並滾動父滾動視圖就像預期一樣工作(滾動標題,40像素保持可見,然後子滾動視圖填充標題下方的屏幕的其餘部分)。我希望「NestedScrolling」意味着我可以在屏幕上的任何位置製作一個滾動手勢(由父滾動視圖捕獲的觸摸事件),並且如果父滾動視圖已到達結尾,則嵌套的子滾動視圖開始滾動。 然而,似乎不是這種情況(既不是簡單的滾動手勢也不是爲了打手勢)。
觸摸事件始終由嵌套的子滾動視圖處理,如果觸摸事件在其邊界開始,否則由父滾動視圖開始。
這是「嵌套滾動」的預期行爲還是有一個選項來更改該行爲?
我也嘗試用NestedRecyclerView
替換嵌套的子滾動視圖。我子類RecyclerView
,並在那裏我所有的委託方法來實現NestedScrollingChildHelper
NestedScrollingChild
:
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);
}
}
但NestedRecyclerView
根本不會滾動。所有觸摸事件都由父滾動視圖捕獲。
我面臨同樣的問題,並認爲這個小部件應該改進,以允許父代未使用滾動到其子。 –
我認爲使回收視圖成爲nestedScrollingChild並不容易,因爲它使用LayoutManager滾動和放置其項目。因此,只有在使用NestedScrollingChildHelper實現NestedScrollingChild時將不起作用,因爲在滾動期間不會調用這些函數。 –
林不知道。我想NestedScrollingParent/NestedScrollingChild用於轉發觸摸事件。我希望'NestedScrollingChild'在內部做到這一點,我看不出有什麼理由爲什麼它應該爲'ScrollView'而不是'RecyclerView'工作......'LayoutManager'不應該是一個問題... – sockeqwe