使用support-v4库22.1.0 android支持嵌套滚动(pre android 5.0)。不幸的是,这个功能并没有真正记录。有两个接口(NestedScrollingParent
和NestedScrollingChild
)以及两个辅助委托类(NestedScrollingChildHelper
和NestedScrollingParentHelper
)。
有没有人在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>
我想在header view
(id = parent)中显示NestedScrollView
和另一个NestedScrollView
(id = child)。
想法是,使用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;
}
});
}
}
因此,标题视图将部分滚动,因为我将嵌套子滚动视图的高度设置为parentScroll.getHeight() - 40
,所以仍然可以看到40个像素。
好的,在运行时设置高度并滚动父滚动视图就像预期的那样工作(标题滚出,40像素仍然可见,然后子滚动视图填充标题下方的屏幕其余部分)。
我希望&#34; NestedScrolling&#34;意味着我可以在屏幕上的任何位置制作滚动手势(触摸由父滚动视图捕获的事件),如果父滚动视图已到达结尾,则嵌套的子滚动视图开始滚动。 然而,似乎并非如此(对于简单的滚动手势和投掷手势都不是这样)。
如果触摸事件在其边界开始,则触摸事件始终由嵌套子scrollview处理,否则由父卷轴视图处理。
这是&#34;嵌套滚动的预期行为&#34;或者是否有改变这种行为的选择?
我还尝试用NestedRecyclerView
替换嵌套的子滚动视图。我将RecyclerView
子类化并实施NestedScrollingChild
,我将所有方法委托给NestedScrollingChildHelper
:
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
根本没有滚动。所有触摸事件都由父滚动视图捕获。
答案 0 :(得分:3)
我花了很多时间来解决这个问题,只是通过Android代码试图弄清楚NestedScrollView中发生了什么。以下应该有效。
public abstract class ParentOfNestedScrollView extends NestedScrollView{
public ParentOfNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/*
Have this return the range you want to scroll to until the
footer starts scrolling I have it as headerCard.getHeight()
on most implementations
*/
protected abstract int getScrollRange();
/*
This has the parent do all the scrolling that happens until
you are ready for the child to scroll.
*/
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed){
if (dy > 0 && getScrollY() < getScrollRange()) {
int oldScrollY = getScrollY();
scrollBy(0, dy);
consumed[1] = getScrollY() - oldScrollY;
}
}
/*
Sometimes the parent scroll intercepts the event when you don't
want it to. This prevents this from ever happening.
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
我的一些代码是从question借来的。从这里我只需要根据需要扩展这个类。我的xml将子节点作为NestedScrollView作为子节点,父节点作为子节点。这并不像我想的那样处理甩尾,这是一项正在进行中的工作。