卜娃娃|Behavior实战,这交互炸了系列:仿小米音乐歌手详情页,自定义

作者:彭冠铭
链接:
完全是使用嵌套滚动机制实现的 , 当时就有很多留言说CoordinatorLayout也能实现 , 确实 , 这不文章就来了 。
作者这个系列一共4篇 , 2篇基础 , 2篇实战 , 如果你能完全吸收 , 基本玩转嵌套滚动 。
PS:感谢大家 , 昨天很给力 , 让我褥了好几年...
1、概述之前的《浅析NestedScrolling嵌套滑动机制之CoordinatorLayout.Behavior》带大家了解CoordinatorLayout.Behavior的原理和基本使用 , 这篇文章手把手基于自定义Behavior实现小米音乐歌手详情页 。
效果预览
下面来说明上图中变量的意义:
topBarHeight;//topBar高度contentTransY;//滑动内容初始化TransYdownEndY;//content下滑的最大值content部分的上滑范围=[topBarHeight,contentTransY]content部分的下滑范围=[contentTransY,downEndY]2、代码实现布局
下面是布局要点 , 侧重于控件的尺寸和位置 , 完整布局请参考:
<android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent">mimusicbehavior.widget.DrawableLeftTextView.../>ContentBehavior这个Behavior主要处理Content部分的Measure、嵌套滑动 。
绑定需要做效果的View、引入Dimens、测量Content部分的高度从上面图片能够分析出:
折叠状态时 , Content部分高度=满屏高度-TopBar部分的高度
publicclassContentBehaviorextendsCoordinatorLayout.Behavior{privateinttopBarHeight;//topBar内容高度privatefloatcontentTransY;//滑动内容初始化TransYprivatefloatdownEndY;//下滑时终点值privateViewmLlContent;//Content部分publicContentBehavior(Contextcontext){this(context,null);}publicContentBehavior(Contextcontext,AttributeSetattrs){super(context,attrs);//引入尺寸值intresourceId=context.getResources().getIdentifier("status_bar_height","dimen","android");intstatusBarHeight=context.getResources().getDimensionPixelSize(resourceId);topBarHeight=(int)context.getResources().getDimension(R.dimen.top_bar_height)+statusBarHeight;contentTransY=(int)context.getResources().getDimension(R.dimen.content_trans_y);downEndY=(int)context.getResources().getDimension(R.dimen.content_trans_down_end_y);...}@OverridepublicbooleanonMeasureChild(@NonNullCoordinatorLayoutparent,Viewchild,intparentWidthMeasureSpec,intwidthUsed,intparentHeightMeasureSpec,intheightUsed){finalintchildLpHeight=child.getLayoutParams().height;if(childLpHeight==ViewGroup.LayoutParams.MATCH_PARENT||childLpHeight==ViewGroup.LayoutParams.WRAP_CONTENT){//先获取CoordinatorLayout的测量规格信息 , 若不指定具体高度则使用CoordinatorLayout的高度intavailableHeight=View.MeasureSpec.getSize(parentHeightMeasureSpec);if(availableHeight==0){availableHeight=parent.getHeight();}//设置Content部分高度finalintheight=availableHeight-topBarHeight;finalintheightMeasureSpec=View.MeasureSpec.makeMeasureSpec(height,childLpHeight==ViewGroup.LayoutParams.MATCH_PARENT?View.MeasureSpec.EXACTLY:View.MeasureSpec.AT_MOST);//执行指定高度的测量 , 并返回true表示使用Behavior来代理测量子Viewparent.onMeasureChild(child,parentWidthMeasureSpec,widthUsed,heightMeasureSpec,heightUsed);returntrue;}returnfalse;}@OverridepublicbooleanonLayoutChild(@NonNullCoordinatorLayoutparent,@NonNullViewchild,intlayoutDirection){booleanhandleLayout=super.onLayoutChild(parent,child,layoutDirection);//绑定ContentViewmLlContent=child;returnhandleLayout;}}实现NestedScrollingParent2接口onStartNestedScroll()ContentBehavior只处理Content部分里可滑动View的垂直方向的滑动 。


推荐阅读