如何在android中使用scrollview实现“快速返回”

时间:2016-03-15 12:50:40

标签: android scrollview

我想用ScrollView实现'Quick return header'。我的标题不是工具栏,它是FrameLayout ..

1 个答案:

答案 0 :(得分:4)

基本上您需要使用select new ParentRecord { ParentID = item.ParentID, Name = item.Name, Age = item.Age, MyNestedChildRecords = (from ns in item.MyNestChildRecords select ns).ToList(); }.ToList(); (在API 21中添加)。此功能允许孩子(滚动的孩子)与他的父母(通常是Nested Scrolling)进行交流。但是,为了进行嵌套滚动,您需要:

  1. 父视图必须实现NestedScrollingParent interface
  2. 子视图必须实现NestedScrollingChild interface
  3. CoordinatorLayout实现了CoordinatorLayout,但不幸的是,NestedScrollingParent没有实现ScrollView接口。

    所以,你不能使用SCROLLVIEW进行嵌套滚动(在API 21之前:查看底部的EDIT部分)。但是,您可以使用基本为NestedScrollingChild的{​​{1}}来实现NestedScrollView接口。

    之后,您需要创建自定义ScrollView并覆盖方法NestedScrollingChildCoordinatorLayout.BehavioronStartNestedScroll。您可以在下面看到符合您需求的代码(我从this example获取了一些更改)。

    假设您查看的是onNestedPreScroll,您可以在布局中执行以下操作:

    onNestedScroll

    正如您所看到的,FramLayout附加了自定义行为。然后,您需要以这种方式修改上述QuickHideBehavior示例:

    <android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
            </LinearLayout>
        </android.support.v4.widget.NestedScrollView>
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="84dp"
            android:background="#FF0000"
            app:layout_behavior=".QuickHideBehavior">
        </FrameLayout>
    </android.support.design.widget.CoordinatorLayout>
    

    你已经完成了。

    我建议您查看更多示例here或{em>戴夫史密斯

    <{3}}

    编辑:实际上,自API 21起,FrameLayout(或public class QuickHideBehavior extends CoordinatorLayout.Behavior<View> { private static final int DIRECTION_UP = 1; private static final int DIRECTION_DOWN = -1; /* Tracking direction of user motion */ private int mScrollingDirection; /* Tracking last threshold crossed */ private int mScrollTrigger; /* Accumulated scroll distance */ private int mScrollDistance; /* Distance threshold to trigger animation */ private int mScrollThreshold; private ObjectAnimator mAnimator; //Required to instantiate as a default behavior public QuickHideBehavior() { } //Required to attach behavior via XML public QuickHideBehavior(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme() .obtainStyledAttributes(new int[] {R.attr.actionBarSize}); //Use half the standard action bar height mScrollThreshold = a.getDimensionPixelSize(0, 0) / 2; a.recycle(); } //Called before a nested scroll event. Return true to declare interest @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { //We have to declare interest in the scroll to receive further events return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; } //Called before the scrolling child consumes the event // We can steal all/part of the event by filling in the consumed array @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { //Determine direction changes here if (dy > 0 && mScrollingDirection != DIRECTION_UP) { mScrollingDirection = DIRECTION_UP; mScrollDistance = 0; } else if (dy < 0 && mScrollingDirection != DIRECTION_DOWN) { mScrollingDirection = DIRECTION_DOWN; mScrollDistance = 0; } } //Called after the scrolling child consumes the event, with amount consumed @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { //Consumed distance is the actual distance traveled by the scrolling view mScrollDistance += dyConsumed; if (mScrollDistance > mScrollThreshold && mScrollTrigger != DIRECTION_UP) { //Hide the target view mScrollTrigger = DIRECTION_UP; restartAnimator(child, getTargetHideValue(coordinatorLayout, child)); } else if (mScrollDistance < -mScrollThreshold && mScrollTrigger != DIRECTION_DOWN) { //Return the target view mScrollTrigger = DIRECTION_DOWN; restartAnimator(child, 0f); } } //Called after the scrolling child handles the fling @Override public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) { //We only care when the target view is already handling the fling if (consumed) { if (velocityY > 0 && mScrollTrigger != DIRECTION_UP) { mScrollTrigger = DIRECTION_UP; restartAnimator(child, getTargetHideValue(coordinatorLayout, child)); } else if (velocityY < 0 && mScrollTrigger != DIRECTION_DOWN) { mScrollTrigger = DIRECTION_DOWN; restartAnimator(child, 0f); } } return false; } /* Helper Methods */ //Helper to trigger hide/show animation private void restartAnimator(View target, float value) { if (mAnimator != null) { mAnimator.cancel(); mAnimator = null; } mAnimator = ObjectAnimator .ofFloat(target, View.TRANSLATION_Y, value) .setDuration(250); /*mAnimator = ObjectAnimator.ofFloat(target, "alpha", 0f, 1f).setDuration(250);*/ mAnimator.start(); } private float getTargetHideValue(ViewGroup parent, View target) { if(target instanceof FrameLayout) return -target.getHeight(); return 0f; } } )支持嵌套滚动,但您需要启用它:

    ScrollView

    当然,您需要设置

    ListView