前言
如果你的业务涉及到列表上下滑动隐藏显示toolbar(标题栏)或者是你的悬浮按钮根据列表的滑动做上下隐藏,左右隐藏。(若是产品提出仿某b站上下滑动隐藏消失,仿某宝购物车移动上下滑动使其左右隐藏显示)那么恭喜你,直接发动 cc + cv 技能 完美完成需求,大家可以先看下下方实现的效果样式。
需要看代码的话直接点下方链接
toolbar根据滑动上下隐藏实现
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/white"
android:contentInsetStart="0dp"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
//...
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
layout_scrollFlags
这边实现主要是根据 layout_scrollFlags
这个属性判断的,一共有5种属性
-
scroll
Child View 伴随着滚动事件而滚出或滚进屏幕。注意两点:第一点,如果使用了其他值,必定要使用这个值才能起作用;第二点:如果在这个child View前面的任何其他Child View没有设置这个值,那么这个Child View的设置将失去作用。 -
enterAlways
它修改返回的视图,使其最初只滚动回它的折叠高度。一旦滚动视图到达滚动范围的末尾,该视图的其余部分将被滚动到视图中。折叠高度由视图的最小高度定义。 -
enterAlwaysCollapsed
退出(滚屏)时,视图将被滚动,直到它被“折叠”。 -
snap
在滚动结束时,如果视图只有部分可见,那么它将被抓取并滚动到最近的边缘。就是停止滚动时要么toolbar完全显示要么完全消失两种状态 -
exitUntilCollapsed
向上滚动时,toolbar向上滚动退出直至最小高度,然后 开始滚动。就是不会完全退出屏幕的意思。
悬浮按钮根据滑动消失隐藏
这里主要用到 CoordinatorLayout.Behavior<View>
。我们根据监听滑动距离来做相应的处理,实现也很简单。
package com.hugh.basis.coordinatorLayoutPage.behavior;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.ViewCompat;
import androidx.core.view.ViewPropertyAnimatorListener;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
/**
* Created by chenyw on 2020/9/2.
*/
public class ViewRightInOutBehavior extends CoordinatorLayout.Behavior<View> {
private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
private boolean mAnimatingOut = false;
public ViewRightInOutBehavior() {
}
public ViewRightInOutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
//需要垂直的滑动
return axes == ViewCompat.SCROLL_AXIS_VERTICAL ||
super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type);
}
@Override
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
if (dyConsumed > 0 && !mAnimatingOut) {
//向上滑动
animateOut(child);
} else if (dyConsumed < 0) {
//向下滑动
animateIn(child);
}
}
private void animateOut(final View button) {
ViewCompat.animate(button)
.translationX(button.getWidth() + getMarginBottom(button))
.setInterpolator(INTERPOLATOR)
.withLayer()
.setListener(new ViewPropertyAnimatorListener() {
public void onAnimationStart(View view) {
mAnimatingOut = true;
}
public void onAnimationCancel(View view) {
mAnimatingOut = false;
}
public void onAnimationEnd(View view) {
mAnimatingOut = false;
}
})
.start();
}
private void animateIn(View button) {
ViewCompat.animate(button).translationX(0).setInterpolator(INTERPOLATOR).withLayer().setListener(null).start();
}
private int getMarginBottom(View v) {
final ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
return ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
}
return 0;
}
}
在xml中使用上面的 behavior
<ImageView
android:id="@+id/float_dub"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end|bottom"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:src="@android:drawable/ic_dialog_info"
app:layout_behavior=".coordinatorLayoutPage.behavior.ViewBottomInOutBehavior"
tools:visibility="visible" />
Behavior的嵌套NestedScrolling触摸事件
onStartNestedScroll() onNestedScrollAccepted() onStopNestedScroll() onNestedScroll() onNestedPreScroll() onNestedFling() onNestedPreFling()
这上述功能中主要实现 onNestedScroll
方法 ,提供给我们相应的滑动距离给予我们做业务判断
布局文件
xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
android:background="@color/white">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/layout_cooRoot"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/white"
android:contentInsetStart="0dp"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/actionBar"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_below="@+id/view_hold"
android:background="@color/white">
<LinearLayout
android:id="@+id/layout_search"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/oval_c8"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintRight_toLeftOf="@+id/iv_history"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/home_icon_searchnew"
android:drawablePadding="4dp"
android:gravity="center"
android:paddingTop="7dp"
android:paddingBottom="7dp"
android:text="哈哈哈哈哈搜索"
android:textColor="@color/c5"
android:textSize="14sp" />
</LinearLayout>
<ImageView
android:id="@+id/iv_history"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_centerInParent="true"
android:layout_marginRight="13dp"
android:scaleType="center"
android:src="@color/yellow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_message"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_message"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_centerInParent="true"
android:layout_marginRight="13dp"
android:scaleType="center"
android:src="@color/yellow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<net.lucode.hackware.magicindicator.MagicIndicator
android:id="@+id/magic_indicator1"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="@android:color/white" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/magic_indicator1"
android:flipInterval="30"
android:persistentDrawingCache="animation" />
</LinearLayout>
<ImageView
android:id="@+id/img_float_ad"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center|end"
android:src="@android:drawable/ic_dialog_email"
app:layout_behavior=".coordinatorLayoutPage.behavior.ViewRightInOutBehavior"
tools:background="@color/c6"
tools:visibility="visible" />
<ImageView
android:id="@+id/float_dub"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end|bottom"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:src="@android:drawable/ic_dialog_info"
app:layout_behavior=".coordinatorLayoutPage.behavior.ViewBottomInOutBehavior"
tools:visibility="visible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
需要上述整体实现逻辑的话可以直接点 github代码直通车