看過前兩篇文章的同窗
sidhu眼中的CoordinatorLayout.Behavior(一)
sidhu眼中的CoordinatorLayout.Behavior(二)
應該知道今天要講的內容了——Behavior的佈局依賴
其實這個內容挺少的,我都想直接貼代碼然你們本身體會了……額,開玩笑的,不過內容真的少,我也不浪費你們時間了,疑問我不提了,直入主題android
(有木有直入主題,哈哈~)
我將上次的例子作了下修改
xml:segmentfault
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/rel_head" android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/colorAccent" app:layout_behavior=".HideHeadBehavior" /> <View android:id="@+id/rel_body" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="200dp" android:background="@color/colorPrimaryDark" app:layout_behavior=".TouchBehavior" /> <View android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="250dp" app:layout_behavior=".MoveWithHeadBehavior" android:background="@color/colorAccent" /> </android.support.design.widget.CoordinatorLayout>
相比於以前的佈局咱們能夠看到,就多了一個小方塊在佈局裏面,至於我想實現的效果能夠看下面效果圖app
讓小方塊能夠隨着上面的head作同步的位移
就如我上篇所說的,使用原理仍是實現NestedScrollingChild接口,廢話很少說,上代碼(沒錯,我就是這樣的人,一言不合就上代碼)ide
package com.mintmedical.mybehaviordemo; import android.animation.ValueAnimator; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.NestedScrollingChild; import android.support.v4.view.NestedScrollingChildHelper; import android.util.AttributeSet; import android.view.View; /** * Created by SidHu on 2016/8/17. */ public class HideHeadBehavior extends CoordinatorLayout.Behavior implements NestedScrollingChild { private boolean isHeadHide = false; private boolean isAnimating = false; private final int SCROOL_VALUE = 50; private int childHeight; private final int animationDuration = 500; private NestedScrollingChildHelper childHelper; public HideHeadBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if (target.getId() == R.id.rel_body) { if (childHeight == 0) { childHeight = child.getHeight(); } if (childHelper == null) { childHelper = new NestedScrollingChildHelper(child); } return true; } else { return false; } } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); if (isAnimating) { return; } if (dy > SCROOL_VALUE && !isHeadHide) { hide(child, target); } else if (dy < -SCROOL_VALUE && isHeadHide) { show(child, target); } } public void hide(final View child, final View target) { isHeadHide = true; ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setIntValues(0, childHeight); valueAnimator.setDuration(animationDuration); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (child.getBottom() > 0) { int value = (int) animation.getAnimatedValue(); isAnimating = value != childHeight; child.layout(child.getLeft(), -value, child.getRight(), -value + childHeight); target.layout(target.getLeft(), -value + childHeight, target.getRight(), target.getBottom()); } } }); valueAnimator.start(); } public void show(final View child, final View target) { isHeadHide = false; ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setIntValues(0, childHeight); valueAnimator.setDuration(animationDuration); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (child.getBottom() < childHeight) { int value = (int) animation.getAnimatedValue(); isAnimating = value != childHeight; child.layout(child.getLeft(), value - childHeight, child.getRight(), value); target.layout(target.getLeft(), value, target.getRight(), target.getBottom()); } } }); valueAnimator.start(); } @Override public void setNestedScrollingEnabled(boolean enabled) { childHelper.setNestedScrollingEnabled(enabled); } @Override public boolean isNestedScrollingEnabled() { return childHelper.isNestedScrollingEnabled(); } @Override public boolean startNestedScroll(int axes) { return childHelper.startNestedScroll(axes); } @Override public void stopNestedScroll() { childHelper.stopNestedScroll(); } @Override public boolean hasNestedScrollingParent() { return childHelper.hasNestedScrollingParent(); } @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return childHelper.dispatchNestedFling(velocityX, velocityY, consumed); } @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { return childHelper.dispatchNestedPreFling(velocityX, velocityY); } }
我將head實現了NestedScrollingChild接口,而後就沒有作其餘事情了。(這也說明了,想讓控件通知CoordinatorLayout本身的狀態其實只要實現了NestedScrollingChild接口就夠了,假如你不須要關心滑動手勢,就像小方塊只關心head的位移同樣,那你startNestedScroll之類的這樣方法都不用要了)佈局
那咱們看一下小方塊的Behaviorspa
package com.mintmedical.mybehaviordemo; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.util.AttributeSet; import android.view.View; /** * Created by SidHu on 2016/8/18. */ public class MoveWithHeadBehavior extends CoordinatorLayout.Behavior{ private int lastBottom = -1; public MoveWithHeadBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency.getId() == R.id.rel_head; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { if (lastBottom == -1) { lastBottom = dependency.getBottom(); } if (dependency.getBottom() != lastBottom) { int d = dependency.getBottom()-lastBottom; lastBottom = dependency.getBottom(); child.offsetTopAndBottom(d); } return super.onDependentViewChanged(parent, child, dependency); } }
代碼也是非~非~非~很是簡單,佈局依賴最主要的關係這兩個方法,一個是判斷是否是本身關心的target View(跟滑動的時候簡直一毛同樣),一個是被關心的target View變化之後的回調,代碼我就不解釋啦,也是很簡單(你們有什麼問題能夠在評論裏面問我啊)。code
好了,關於Behavior的使用我就先介紹到這了
![圖片上傳中...]xml