如何为 google MapView 制作具有视差滚动效果的自定义 CoordinatorLayout.Behavior?
How to make custom CoordinatorLayout.Behavior with parallax scrolling effect for google MapView?
-
android
-
google-maps-android-api-2
-
android-design-library
-
androiddesignsupport
-
android-coordinatorlayout
我尝试使用 CoordinatorLayour
.
为 google MapView
和 RecycleView
制作视差滚动效果
所以根据在网上找到的一些教程,我做了下面的代码。
布局:
<?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")
android
google-maps-android-api-2
android-design-library
androiddesignsupport
android-coordinatorlayout
我尝试使用 CoordinatorLayour
.
MapView
和 RecycleView
制作视差滚动效果
所以根据在网上找到的一些教程,我做了下面的代码。
布局:
<?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")