Android Design 自定义Behavior

自从Android推出Design后,就广受各位开发者的喜爱,因为以前很多高级特效都需要我们自己去写,而现在Design库内置类很多实用的控件,很多复杂的需求用设个库就能满足,记得以前写自定义控件就经常遇到触摸事件方面的问题,比如外层ViewGroup将事件拦截后,在通过某些特定操作后,将事件还给内部子View处理,这种事件处理就很麻烦,因为在一次事件中外部ViewGroup一旦拦截了事件,子类就将无法再次接受这次事件,在处理某些组合操作时,显得不太流畅,而Design库中提供了一个神奇的控件CoordinatorLayout就能解决这类问题,CoordinatorLayout能将内部所有控件的事件串联起来,相互监听,让我们监听其他控件的状态,并执行自己对应的操作。

接下来我们先自定义一个Behavior,来达到下面演示的效果:

演示.gif

从上面动图可以看出,这个动画实现非常简单,就是在AppBarLayout折叠的同时将底部栏慢慢移出屏幕,移动的数值就是AppBarLayout移动的值取反。

贴下布局文件:

<?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">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:logo="@mipmap/ic_launcher"
            app:navigationIcon="@mipmap/ic_launcher"
            app:title="这是标题" />

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_gravity="bottom"
        android:background="#ccc"
        android:padding="8dp"
        app:layout_behavior="view.peakchao.view.behavior.CustomExpandBehavior">

        <Button
            android:id="@+id/btn_send"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:background="@android:color/white"
            android:text="发送" />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="4dp"
            android:layout_toLeftOf="@id/btn_send"
            android:background="@android:color/white"
            android:hint="你想说点什么?"
            android:padding="4dp" />

    </RelativeLayout>

    <ImageView
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginBottom="70dp"
        android:layout_marginRight="20dp"
        android:src="@mipmap/ic_launcher"
        app:layout_behavior="view.peakchao.view.behavior.DefineBehavior"
        app:layout_scrollFlags="scroll|enterAlways|snap" />

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

重点是上面布局中引用了app:layout_behavior这个属性,这个属性指定了当前View的行为:

//这个Behavior是系统自带的
app:layout_behavior="@string/appbar_scrolling_view_behavior"
//这个Behavior是接下来要自定义的
app:layout_behavior="view.peakchao.view.behavior.CustomExpandBehavior"

Behavior自定义的方式也很简单,首先确定我们要监听的View(这里是指AppBarLayout),然后被监听View发生变化时,处理我们需要做的操作。

/**
 * Created by Chao  2018/4/17 on 9:42
 * description
 */

public class CustomExpandBehavior extends CoordinatorLayout.Behavior {

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

    /**
     * 指定监听目标
     *
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof AppBarLayout;//这里我们需要监听AppBarLayout的状态。
    }

    /**
     * 指定目标更新时候调用,layoutDependsOn返回true时有效
     *
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        int delta = dependency.getTop();
        child.setTranslationY(-delta);//当AppBarLayout移动时,将当前View向反方向移动。
        return true;
    }

}

我们在布局中引用时,会两个参数的构造方法,当我们用注解设置Behavior时,会调用无参构造,比如我们上面用到的:

@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {
}

猜你喜欢

转载自blog.csdn.net/c__chao/article/details/80163292