Behavior-UC-Main-Page

老规矩,还是先上效果图
图片名称

github地址

前面我也写过一篇关于UC浏览器首页滑动动画效果的文章UC浏览器首页滑动动画实现,只不过这篇文章是通过自定义View的方式实现这个滑动效果。最近在看Behavior相关的东西,所以使用Behavior又实现了一次UC浏览器主页的滑动效果,使用Behavior实现相比较自定义View的实现方式还是要简单方便很多。

View结构分析

UC首页滑动过程中可以分为四个View在参与滑动,具体的分析流程可以参见UC浏览器首页滑动动画实现这篇文章的分析,这里简要罗列下:

  1. UCViewTitle:首页标题栏视图(UC首页显示UC头条)
  2. UCViewHeader:首页头部导航视图(UC首页显示各个网站ICON入口)
  3. UCViewContent:首页内容视图(UC首页显示新闻内容的列表)
  4. UCViewTab:首页内容Tab导航视图(UC首页显示新闻分类的View)

Behavior

既然已经决定通过Behavior实现此效果,那下面几个概念就必须要弄清楚:

  1. Behavior必须作用于CoordinatorLayout直接子View才会生效
  2. Behavior其实是对嵌套滑动的应用,因为CoordinatorLayout其实是实现嵌套滑动,最终对嵌套滑动的执行交给Behavior来实现,所以Behavior的滑动处理必须要有能触发嵌套滑动的子View触发才会起作用

关于嵌套滑动

  1. Android实现嵌套滑动只需要实现NestedScrollingParentNestedScrollingChild这两个接口即可
  2. 在嵌套滑动过程中子View(实现NestedScrollingChild接口)会将自身的滑动情况通知父View(实现NestedScrollingParent接口),不一定是直接父View父View做完相关动作之后再通知子View,也就是子View其实是整个嵌套滑动的发起者
  3. CoordinatorLayout实现了NestedScrollingParent接口作为嵌套滑动的父View,因此如果要处理Behavior中对于滑动的相关处理,就需要有一个嵌套滑动的子View来触发这个Behavior

实现

  1. 上面分析UC首页时发现有个显示新闻的列表,因此我们可以用RecyclerView作为列表,因为RecyclerView实现了NestedScrollingChild接口,可以作为嵌套滑动的子View
  2. 因为是多个视图的同时滑动处理,所以在实现Behavior时需要选择一个依赖,这里我选择前面说过的UCViewHeader作为其他视图Behavior的依赖
  3. 在看了AppBarLayout的源码之后,发现其子类ScrollingViewBehavior继承至HeaderScrollingViewBehavior,在查看源码之后发现如下几个类可以抽出来为我们所用HeaderScrollingViewBehavior,ViewOffsetBehavior,ViewOffsetHelper
    1. HeaderScrollingViewBehavior:继承该类后,应用此BehaviorView布局时会自动在其依赖View的下方
    2. ViewOffsetBehavior:继承该类后,应用此BehaviorView在布局时会自动进行移动处理

UCViewTitleBehavior实现

UCViewTitle在初始时是不可见的,我采用设置其TopMargin让其不可见,然后在滑动过程中再慢慢滑动到可见,当前完全可见时滑动结束,此时其translationY为0,当滑动未开始时其translationY-height

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class UCViewTitleBehavior extends ViewOffsetBehavior<View> {
...
@Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
//因为UCViewTitle默认是在屏幕外不可见,所以在UCViewTitle进行布局的时候设置其topMargin让其不可见
((CoordinatorLayout.LayoutParams) child.getLayoutParams()).topMargin = -child.getMeasuredHeight();
return super.onLayoutChild(parent, child, layoutDirection);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return isDependOn(dependency);
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
int headerOffsetRange = -child.getMeasuredHeight();//
int titleOffsetRange = child.getMeasuredHeight();//滑动总距离
if (dependency.getTranslationY() == headerOffsetRange) {//滑动初始位置
child.setTranslationY(titleOffsetRange);
} else if (dependency.getTranslationY() == 0) {//滑动结束位置
child.setTranslationY(0);
} else {//滑动过程中
child.setTranslationY((int) (dependency.getTranslationY() / (headerOffsetRange * 1.0f) * titleOffsetRange));
}
return false;
}
private boolean isDependOn(View dependency) {
//确定UCViewHeader作为依赖
return dependency != null && dependency.getId() == R.id.news_view_header_layout;
}
}


原创文章,本文采用知识共享署名 2.5(中国大陆许可协议)进行许可,欢迎转载,但转载请注明来自ittiger.cn,并保证转载后文章内容的完整性。本人(laohu)保留所有版权相关权利。



评论