借助support-v4库22.1.0,android支持嵌套滚动(早于android 5.0)。不幸的是,这个特性并没有真正的文档化。有两个接口(NestedScrollingParent和NestedScrollingChild)以及两个助手委托类(NestedScrollingChildHelper和NestedScrollingParentHelper)。
有没有人在安卓系统上使用过NestedScrolling?
我试着设置了一个小示例,其中我使用了同时实现NestedScrollingParent和NestedScrollingChild的NestedScrollView。
我的布局如下所示:
<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>我想在父级(id = NestedScrollView )中显示一个子级和另一个子级(id = NestedScrollView )。
其想法是,在运行时通过使用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并实现了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根本不会滚动。所有的触摸事件都会被父滚动视图捕获。
发布于 2015-07-15 05:18:16
我在这上面花了相当多的时间,只是检查了安卓代码,试图弄清楚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作为子元素,父元素作为下面的元素。这不能很好地处理我想要的,这是一项正在进行中的工作。
https://stackoverflow.com/questions/29885067
复制相似问题