通过使用Bahavior,可以实现嵌套滑动的效果。即一个组件的滑动由另一个组件决定、或者有CoordinatorLayout的滑动状态决定。自定义Bahavior需要继承CoordinatorLayout.Behavior<View>,其中在泛型中指定的是应用这个Behavior的View类型。
1、关联Behavior
<android.support.design.widget.FloatingActionButton
...
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
或者
CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.setBehavior(new AppBarLayout.ScrollingViewBehavior());
coordinatorLayout.addView(innerContentView,params);
2、依赖其他组件
通过以下两个方法,可以实现一个组件的滑动依赖其他组件
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) ;
public void onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) ;
其中child是应用这个Behavior的view,dependency是被依赖的组件,可以在layoutDependsOn()方法中指定被依赖的组件A,当A发生改变时,会调用onDependentViewChanged()方法。
简单实现如下:
public class DependTitleBeahvior extends CoordinatorLayout.Behavior<View> {
private int toolbarHeight;
public DependTitleBeahvior(Context context, AttributeSet attrs) {
super(context, attrs);
toolbarHeight = getToolbarHeight(context);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof AppBarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
if (dependency instanceof AppBarLayout){
int childHeight=getChildHeight(child);
float ratio=childHeight*1.0f/toolbarHeight;
Log.e("onDependentViewChanged","dependency:"+dependency.getY() +",child"+childHeight +",ratio"+ratio);
child.setTranslationY( -1 * ratio* dependency.getY());
}
return true;
}
/**
* 应用Behavior的组件距离底部的高度
*/
private int getChildHeight(View child) {
int bottomMargin=0;
ViewGroup.LayoutParams params=child.getLayoutParams();
if (params instanceof ViewGroup.MarginLayoutParams){
bottomMargin=((ViewGroup.MarginLayoutParams) params).bottomMargin;
}
return child.getHeight()+bottomMargin;
}
/**
* 被依赖的toolbar的高度
*/
private int getToolbarHeight(Context context) {
final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
new int[]{R.attr.actionBarSize});
int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return toolbarHeight;
}
}
3、依赖CoordinatorLayout的滑动状态
通过以下两个方法,可以实现一个组件的滑动依赖CoordinatorLayout的滑动状态
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes)
public void onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) ;
其中,child是应用这个Behavior的view,target引起滚动的view(比如NestScrollView)。dy>0,向上滑动。
public class DependScrollBehavior extends CoordinatorLayout.Behavior<View> {
public DependScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL)!=0;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
int childHeight=getChildHeight(child);
int childScrolledY= (int) (child.getTranslationY()+dy);
// 向上滑动 、 滑动的总距离大于 childHeight
if (dy>0 && childScrolledY>=childHeight){
childScrolledY=childHeight;
}
// 向下滑动 、 滑动的总距离小于 0
else if (dy<0 && childScrolledY<=0){
childScrolledY=0;
}
child.setTranslationY(childScrolledY);
}
/**
* 应用Behavior的组件距离底部的高度
*/
private int getChildHeight(View child) {
int bottomMargin=0;
ViewGroup.LayoutParams params=child.getLayoutParams();
if (params instanceof ViewGroup.MarginLayoutParams){
bottomMargin=((ViewGroup.MarginLayoutParams) params).bottomMargin;
}
return child.getHeight()+bottomMargin;
}
}
分析
http://geek.csdn.net/news/detail/59829
http://www.cnblogs.com/soaringEveryday/p/5711545.html