通過使用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);
1
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