如何在Android上实现NestedScrolling?

与支持v4库22.1.0 android支持嵌套滚动(预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>

我想在NestedScrollView(id = parent)中显示一个标题视图和另一个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;
          }
        });

  }
}

所以头部视图将被部分滚动,40像素将保持可见,因为我设置嵌套的子滚动视图的高度为parentScroll.getHeight() – 40。
好吧,在运行时设置高度和滚动父滚动视图工作原理像预期(标题滚出,40像素保持可见,然后子滚动查看填充屏幕下面的标题下方的其余部分)。

我希望“NestedScrolling”意味着我可以在屏幕上的任何地方(触摸由父滚动视图捕获的事件)滚动手势,如果父滚动视图已到达结束,嵌套的子滚动视图开始滚动。
然而,似乎不是这种情况(既不是简单的滚动手势也不是fling手势)。

如果触摸事件在其边界开始,否则通过父滚动视图,触摸事件总是由嵌套子级scrollview处理。

是“嵌套滚动”的预期行为还是有可以更改该行为的选项?

我也试图用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根本不滚动。所有触摸事件都由父滚动视图捕获。

我花了相当多的时间这只是通过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作为一个孩子和父作为这个。这不处理flings,以及我想,这是一个正在进行中的工作。

http://stackoverflow.com/questions/29885067/how-to-implement-nestedscrolling-on-android

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:如何在Android上实现NestedScrolling?