这两天重构项目,遇到需要添加一个Fab的时候,就随便上网上copy了一段代码,测试的时候发现,只能执行一次,之后就不会走Behavior的onNestedScroll方法了。
在网上找了半天解决办法,也没有找到。最后只能看看源码到底是因为什么吧,直接上源码
@Override
public boolean onStartNestedScroll(View child, View target, int axes, int type) {
boolean handled = false;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View view = getChildAt(i);
if (view.getVisibility() == View.GONE) {
// If it's GONE, don't dispatch
continue;
}
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
final Behavior viewBehavior = lp.getBehavior();
if (viewBehavior != null) {
final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child,
target, axes, type);
handled |= accepted;
lp.setNestedScrollAccepted(type, accepted);
} else {
lp.setNestedScrollAccepted(type, false);
}
}
return handled;
}
自定义的Behavior中的onStartNestedScroll方法最后会走到CoordinatorLayout方法的onStartNestedScroll方法中 在里面判断了一下childView的visibility的属性是不是GONE 是的话就会跳过
同样的onNestedScroll中也会判断childView的属性,是GONE的时候就回跳过。所以在设置需要执行Behavior的View的属性就不要设置成GONE就可以了。
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed, int type) {
final int childCount = getChildCount();
boolean accepted = false;
for (int i = 0; i < childCount; i++) {
final View view = getChildAt(i);
if (view.getVisibility() == GONE) {
// If the child is GONE, skip...
continue;
}
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
if (!lp.isNestedScrollAccepted(type)) {
continue;
}
final Behavior viewBehavior = lp.getBehavior();
if (viewBehavior != null) {
viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, type);
accepted = true;
}
}
if (accepted) {
onChildViewsChanged(EVENT_NESTED_SCROLL);
}
}
最后附上自己写的BaseBehavior以及一个可用的Behavior
open class BaseBehavior constructor(context: Context,attrs:AttributeSet): CoordinatorLayout.Behavior(){
private val mFastInterpolator = FastOutSlowInInterpolator()
// 显示view
fun scaleShow(view: View,l :ListenerAnimatorEndBuild?) {
view.visibility = View.VISIBLE
ViewCompat.animate(view)
.scaleX(1.0f)
.scaleY(1.0f)
.alpha(1.0f)
.setDuration(500)
.setListener(l?.build())
.setInterpolator(mFastInterpolator)
.start()
}
// 隐藏view
fun scaleHide(view: View,l:ListenerAnimatorEndBuild?) {
ViewCompat.animate(view)
.scaleX(0.0f)
.scaleY(0.0f)
.alpha(0.0f)
.setDuration(500)
.setInterpolator(mFastInterpolator)
.setListener(l?.build())
.start()
}
class ListenerAnimatorEndBuild {
// 记录View移出动画是否执行完。
private var isOutExecute = false
private val outAnimatorListener: ViewPropertyAnimatorListener
// View移出动画是否执行完。
val isFinish: Boolean
get() = !isOutExecute
init {
outAnimatorListener = object : ViewPropertyAnimatorListener {
override fun onAnimationStart(view: View) {
isOutExecute = true
}
override fun onAnimationEnd(view: View) {
view.visibility = View.INVISIBLE
isOutExecute = false
}
override fun onAnimationCancel(view: View) {
isOutExecute = false
}
}
}
// 返回ViewPropertyAnimatorListener。
fun build(): ViewPropertyAnimatorListener {
return outAnimatorListener
}
}
}
class FabBehavior constructor(context: Context, attributeSet: AttributeSet) : BaseBehavior(context, attributeSet) {
private var listenerAnimatorEndBuild = ListenerAnimatorEndBuild()
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout,
child: FloatingActionButton,
directTargetChild: View,
target: View, axes: Int, type: Int): Boolean {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}
override fun onNestedScroll(coordinatorLayout: CoordinatorLayout,
child: FloatingActionButton,
target: View,
dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int,
type: Int) {
if (dyConsumed > 0 && dyUnconsumed == 0) {
KLog.d("behavior", "上滑中。。。")
}
if (dyConsumed == 0 && dyUnconsumed > 0) {
KLog.d("behavior", "到边界了还在上滑。。。")
}
if (dyConsumed < 0 && dyUnconsumed == 0) {
KLog.d("behavior", "下滑中。。。")
}
if (dyConsumed == 0 && dyUnconsumed < 0) {
KLog.d("behavior", "到边界了,还在下滑。。。")
}
//页面向上滑动像素数大于0 || 拉到底还在向上拉 && 退出动画是否正在执行 && FAB按钮当前显示中
if ((dyConsumed > 0 || dyUnconsumed > 0) && listenerAnimatorEndBuild.isFinish&& child.visibility == View.VISIBLE) {
//隐藏Fab
scaleHide(child,listenerAnimatorEndBuild)
} else if ((dyConsumed < 0 || dyUnconsumed < 0) && child.visibility != View.VISIBLE) {
//显示Fab按钮
scaleShow(child,null)
}
}
}
copy过去就能用了 部分动画代码是上网上找的,毕竟我懒的写。。。
至于是kotlin写的也没关系,之间copy的话 as会自动转为java的。