如何为 google MapView 制作具有视差滚动效果的自定义 CoordinatorLayout.Behavior?

How to make custom CoordinatorLayout.Behavior with parallax scrolling effect for google MapView?

我尝试使用 CoordinatorLayour.

为 google MapViewRecycleView 制作视差滚动效果

所以根据在网上找到的一些教程,我做了下面的代码。

布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <com.google.android.gms.maps.MapView android:id="@+id/map_view"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:layout_behavior="net.lunavulpo.coordinatorlayouttest.MapViewBehavior"
        />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_marginTop="200dp"
        android:layout_height="match_parent"/>

</android.support.design.widget.CoordinatorLayout>

我实现了 CoordinatorLayout.Behavior:

    public class MapViewBehavior extends CoordinatorLayout.Behavior<MapView> {

        public MapViewBehavior(Context context, AttributeSet attrs) {
        }

        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent, MapView child, View dependency) {
            return true;
        }

        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, MapView child, View directTargetChild, View target, int nestedScrollAxes) {
            return true;
        }

        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, MapView child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {

            //child.setTranslationY(child.getTranslationY() - dyConsumed);
            child.setBottom(child.getBottom() - dyConsumed);
//what should I make here?

        }


    @Override
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, MapView child, View target, float velocityX, float velocityY, boolean consumed) {
//what should be here?
        return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
    }

    @Override
    public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, MapView child, View target, float velocityX, float velocityY) {

//what should be here?
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
    }
    }

如何正确实现视差滚动效果? 也许有一个可以使用行为的库? 或者我错过了什么,有最简单的方法吗?

我根本不想为此使用工具栏。

正如@Xaver Kapeller 所建议的,实现视差最轻松的方法是将其包裹在 CollapsingToolbarLayout 中,并使用折叠模式 PARALLAX 和您选择的视差倍增器。

但是,如果您打算采用自己的行为,则需要在 onPreNestedScroll() 方法中编写实现。

首先,你只关心垂直滚动。在 onStartNestedScrolling() 你检查枯萎 nestedScrollAxes 是垂直的。

然后你累积所有 dy 滚动并翻译虚拟视图(作为 header)和 MapView。当滚动方向发生变化时,将 mTotalDy 重置为 0

然后对于相同的负 mTotalDy 值翻译 ViewCompat.setTranslationY(mDummyView, -mTotalDy)。为了获得适当的视差,视差应该比虚拟视图平移得慢,这意味着 mTotalDy 值应该至少是虚拟视图平移速度的一半,即:ViewCompat.setTranslationY(mMapView, -mTotalDy/2)。因此你会看到它翻译 up/down 更慢。

视图层次应该是:确保你的z-order如我所描述的那样得到保存

-CordinatorLayout
  -FrameLayout
    -MapView
    -DummyView (same height as MapView, different z-order)
    -NestedScrollView (same z-order as DummyView)

如果有嵌套的flinging,同样处理,提示:使用target.getScrollY(),目标是滚动的view。

更新:

我将向您概述如何做(我不能 post 所有答案,因为我 post 在另一个问题中编辑了它,要求比问题更多,而我的旧答案被标记为重复......)无论如何这就是你如何做的:

自定义 CoordinatorLayout:
因为你不能扩展 BottomSheetBehavior,你有 2 个选择:尝试做你自己的 Behavior 或像我一样,只需复制粘贴原始 BottomSheetBehavior 中的代码并修改它以获得另一个状态(当 google 映射打开一个 bottomsheet 时停在屏幕中间,这就是我所说的状态)。
here the CustomBottomSheet with the behavior I was talking above

现在为图像视差效果:
我在 XML 中尝试了所有默认视差效果以避免自定义行为,但最后我结束了一个,它并不难,你需要像这样重写 2 个方法:

public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    return dependency instanceof NestedScrollView;
}

public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
                                      View dependency) {

    if (mYmultiplier == 0) {
        initValues(child, dependency);
        return true;
    }

    float dVerticalScroll = dependency.getY() - mPreviousY;
    mPreviousY = dependency.getY();

    //going up
    if (dVerticalScroll <= 0 && child.getY() <= 0) {
        child.setY(0);
        return true;
    }

    //going down
    if (dVerticalScroll >= 0 && dependency.getY() <= mImageHeight)
        return false;

    child.setY( (int)(child.getY() + (dVerticalScroll * mYmultiplier) ) );

    return true;
}


Here the link to image parallax behavior

下面是它的样子:
[]

A link to the project 我必须澄清之前的 link 有 FAB 和工具栏动画但是如果你只想要底部和图像行为就忽略其他 java 文件(澄清因为我必须 "adjust to the question")