二、Behavior上

2017-08-15  本文已影响0人  ec1d4f49eddd

上篇文章我们讲到,在CoordinatorLayout中,一个View可以根据另一个View的变化而变化,而提供这种关联关系的类就是Behavior。仅为了描述上的方便,在这篇文章中称呼这两个View为主动View和被动View

一、基本用法

首先来看效果:

蓝色方块随着黄色方块的变化而变化

要实现这个Demo,首先要了解下Behavior类,在AS里面点进去看下:


Behavior类

Behavior是CoordinatorLayout的内部抽象类

public static abstract class Behavior<V extends View> {

Behavior定义了一个View的子类泛型,这个类指的是被动View。
Behavior的核心方法都是onXXX之类的回调,如最基础的onDependentViewChanged方法,在主动View的大小或者位置发生变化时会回调这个方法。而onNestedFling方法会在主动View fling时回调这个方法。
除此之外layoutDependsOn也是几乎必须要被覆写的方法,它定义了被动View所依赖的主动View是谁,每次CoordinatorLayout布局时,这个方法都会被调用(调用的次数为他的子View的个数减去被动View的个数)。当参数中的dependency是正确的主动View时,这个方法需要返回true,否则返回false。

public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
        return false;
}

另外,如果要在xml中声明Behavior时,需要覆写构造函数。在xml中为被动View声明Behavior的方法是:

app:layout_behavior="com.sg.line.MyBehavior"

下面来实现Demo,首先写主动View ,那个黄色小方块,让他跟随手指移动,正常写就行了:

public class DragableIV extends android.support.v7.widget.AppCompatImageView {

    public DragableIV(Context context) {
        super(context);
    }

    public DragableIV(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DragableIV(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    float xDown, yDown, x, y;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                x = getX();
                y = getY();
                xDown = event.getRawX();
                yDown = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                setX(x + (event.getRawX() - xDown));
                setY(y + (event.getRawY() - yDown));
                break;
        }
        return true;
    }
}

然后是布局(注意用app:layout_behavior为被动View指定Behavior):

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <com.sg.line.DragableIV
        android:id="@+id/ivMove"
        android:background="@android:color/holo_orange_light"
        android:layout_width="50dp"
        android:layout_height="50dp"/>

    <TextView
        app:layout_behavior="com.sg.line.MyBehavior"
        android:layout_gravity="bottom"
        android:id="@+id/tvFollow"
        android:background="@android:color/holo_blue_bright"
        android:layout_width="50dp"
        android:layout_height="50dp"/>

</android.support.design.widget.CoordinatorLayout>

最后是Behavior:

public class MyBehavior extends CoordinatorLayout.Behavior<TextView> {
    public MyBehavior() {
    }

    public MyBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {
        return dependency instanceof DragableIV;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {
        child.setX(dependency.getX());
        child.setY(parent.getHeight() - dependency.getY() - dependency.getHeight());
        return true;
    }
}

在layoutDependsOn方法中,指定被动View对应的主动View为DragableIV实例;
在onDependentViewChanged,让被动View的x等同于主动View,y和主动View垂直对称。如果在这个方法中被动view的大小或者位置也发生了改变则返回true,否则返回false,这里肯定是要返回true的。
这样全部的代码就写完了,是不是很简单。

上一篇 下一篇

猜你喜欢

热点阅读