FAB避让snackbar的原理 在api23和24下是不同的

这段时间主要用来掌握Material Design 的相关控件的学习,我是先在github上下载了一个示例,但是基本只有代码,没办法真正了解控件的对应使用方法及注意事项,所以我先从示例中了解到都有哪些比较好的控件,并且可以直观的看到控件所展现出来的用户体验,然后在google对应控件的教程来学习并加以理解。前期的任务是先了解各个控件的使用,后面会继续学习其源码。(博客是边学边写的。)


CoordinatorLayout的注释中说明,它必须作为顶层布局(父布局),作为一个容器与它的childs进行特殊的交互操作。这里的作为顶层布局,是指需要体现滑动特效的views组合,必须以它为顶层布局。并不是说它必须在xml里作为根布局。它的大概原理是看它的子view定义了Behavior,然后产生交互。Behavior是一个静态的抽象类,里面有类似的onInterceptTouchEvent和ontouchevent等,还有比较关键的layoutDependsOn,onDependentViewChanged等方法。具体的会在之后的学习中再整理,可以看到的是,CoordinatorLayout在自己的touch相关事件中会根据behavior找到一个behaviorView,然后在对应的touch事件中调用behaviorView的touch事件。使用CoordinatorLayout,我们不用写任何的动画效果,它就可以和一些控件产生很不错的交互效果,比如和FAB、Snackbar一起,Snackbar一般会选择出现在屏幕底部(你可以让他出现在其他地方),如果FAB也在屏幕底部,我们不用写任何代码,当Snackbar出现的时候FAB就会自动有个上移的动画,Snackbar的出现也是从下向上顶起。因为FAB就定义了一个behavior。同理如果我们想形成自己的效果,也需要自定义一个behavior,最佳的学习应该就是参考FAB或者已经存在的其他控件的behavior。其实本章主要想写CoordinatorLayout的应用,但发现它实在是无法脱离它的具体的子view来讲,边学的时候一边就把题目换成了现在的,如果网上搜最多就搜多大片大片的23下的实现原理,如果你用24api开发,你会惊讶的发现,为毛和网上的对不上号。。。


学习总是赶不上变化,之前看的是api23的源码,当时它避让snackbar的时候还是通过behavior里面的对应回调,如下代码:

@Override
public boolean layoutDependsOn(CoordinatorLayout parent,
FloatingActionButton child, View dependency) {
// We're dependent on all SnackbarLayouts (if enabled)
return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
View dependency) {
if (dependency instanceof Snackbar.SnackbarLayout) {
updateFabTranslationForSnackbar(parent, child, dependency);
} else if (dependency instanceof AppBarLayout) {
// If we're depending on an AppBarLayout we will show/hide it automatically
// if the FAB is anchored to the AppBarLayout
updateFabVisibility(parent, (AppBarLayout) dependency, child);
}
return false;
}

当时这样写的时候,还是需要FAB和snackbar进行关联的,或者它默认就进行了关联,而且看源码可以知道这时他只会退让snackbar.behavior或者snacklayout,可以自定义退避时的动画效果,比如网上说的添加旋转之类的。感觉还是挺美好的。但是再看下api24的代码。。:


@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
View dependency) {
if (dependency instanceof AppBarLayout) {
// If we're depending on an AppBarLayout we will show/hide it automatically
// if the FAB is anchored to the AppBarLayout
updateFabVisibilityForAppBarLayout(parent, (AppBarLayout) dependency, child);
} else if (isBottomSheet(dependency)) {
updateFabVisibilityForBottomSheet(dependency, child);
}
return false;
}而layoutDependsOn这个方法已经没有了,也就是说这个方法执行父类的方法,直接return了false。而onDependentViewChanged也只是操作是否显示,然后我自己定义了一个behavior,删除了很多东西,最后尝试到保留两个方法:

public class Behavior extends CoordinatorLayout.Behavior<FloatingActionButton> {

public Behavior() {
super();
}

public Behavior(Context context, AttributeSet attrs) {
super(context, attrs);
}


@Override
public void onAttachedToLayoutParams(@NonNull CoordinatorLayout.LayoutParams lp) {
if (lp.dodgeInsetEdges == Gravity.NO_GRAVITY) {
// If the developer hasn't set dodgeInsetEdges, lets set it to BOTTOM so that
// we dodge any Snackbars
lp.dodgeInsetEdges = Gravity.BOTTOM;
}
}

@Override
public boolean onLayoutChild(CoordinatorLayout parent, FloatingActionButton child,
int layoutDirection) {
// First, let's make sure that the visibility of the FAB is consistent
final List<View> dependencies = parent.getDependencies(child);
Log.d("sqc","i am move");
// Now let the CoordinatorLayout lay out the FAB
parent.onLayoutChild(child, layoutDirection);
// child.setRotation(45);
// Now offset it if needed
return true;
}


}必须得保留这几个方法,才能让它继续避让snackbar,可以看到基本没有什么东西了,上面两个构造方法,第二个构造是如果你的fab是在xml里定义的,必须保留这个方法,否则报错。onLayoutChild这个方法,如果不执行里面的parent.onLayoutChild(child, layoutDirection);FAB就不会显示出来。而如果不执行lp.dodgeInsetEdges = Gravity.BOTTOM;的话,就不会产生避让效果。那么可见,关键就在于lp.dodgeInsetEdges = Gravity.BOTTOM;这一句了,然后我尝试删除了这个方法,并在xml里设置了fab的一个属性

app:layout_dodgeInsetEdges="bottom"
没错,xml有了这个,即使behavior里不写之前那个代码,也可以产生避让,所以只需要搜索一下这个属性的使用。然后发现这确实是api24出现的东西。它不再只限于snackbar,随便一个view你先设置app:layout_insetEdge="bottom"这个属性,然后fab就会避让它。。同理,我继续尝试,view设置成top,然后fab也设置成top,然后两个控件都在coor...layout的顶部。这时如果view从gong到visiable,fab会向下移动来避让。

api24就单独为避让操作做出了改变,不再限制于哪个控件了,而是限制在lp.dodgeInsetEdges和app:layout_insetEdge这两个属性的运用上,注意的是在24api下,fab和snack之间是没有depends的,你会发现depends的相关方法都不会触发,我觉得24主要是为了让depends做更应该做的事情,避让属于一个所有控件都有的属性,而不是某个特定ui下的view联动的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值