sidhu眼中的CoordinatorLayout.Behavior(三)

前言

看過前兩篇文章的同窗
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

clipboard.png

讓小方塊能夠隨着上面的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

若是以爲這篇文章對你有幫助,點個贊鼓勵一下吧、、(●'◡'●)

相關文章
相關標籤/搜索