您的位置:

深入解析Android中的layout_behavior

一、layout_behavior是什么?

1、layout_behavior是Android自定义Behavior的一种,可在布局文件中通过app:layout_behavior属性设置。这意味着,layout_behavior指定了对应布局的交互方式和效果,如使某个view滑动隐藏头部导航栏。

2、默认情况下,每个view或viewGroup的布局都具有一种默认的behavior,可通过给view或viewGroup设置app:layout_behavior属性切换behavior的类型,但只能有一个behavior与view或viewGroup相关联。

3、layout_behavior需实现CoordinatorLayout.Behavior接口,即可具备behavior特性,以与CoordinatorLayout协调调用。

二、CoordinatorLayout的布局机制

1、CoordinatorLayout是一个主要用于AppBarLayout和FloatingActionButton之类的可交互View之间布局和动画的容器。

2、CoordinatorLayout通过分析以下三种事件:

CoordinatorLayout嵌套子View的大小位置变化、子View的触摸事件、子View的滚动事件。

来确定子View之间的位置关系。

3、CoordinatorLayout在内置的Behavior中集成了所有子View的布局逻辑,可以通过自定义Behavior来扩展CoordinatorLayout的功能来进行视图之间的关联。

三、如何自定义Behavior

1、创建一个Java类并实现CoordinatorLayout.Behavior接口,然后重写Behavior的三个方法:

public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency)

public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency)

public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection)

2、使用@CoordinatorLayout.DefaultBehavior注解对Behavior进行标记,指定用于该view的默认Behavior。

3、自定义Behavior的实现主要是应用其依赖关系来确定相对布局,以及在其依赖项发生变化时对其相应进行动态修改处理。

四、layout_behavior的使用

1、在布局文件中使用定义的Behavior

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/linearlayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior=".MyBehavior">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World!" />

        </LinearLayout>

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

2、在自定义Behavior中定义与其关联的view和dependency

public class MyBehavior extends CoordinatorLayout.Behavior<LinearLayout> {

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

    public boolean layoutDependsOn(CoordinatorLayout parent, LinearLayout child, View dependency) {
        //依赖于AppBarLayout
        return dependency instanceof AppBarLayout;
    }

    public boolean onDependentViewChanged(CoordinatorLayout parent, LinearLayout child, View dependency) {
        return false;
    }

    public boolean onLayoutChild(CoordinatorLayout parent, LinearLayout child, int layoutDirection) {
        return false;
    }

}

五、layout_behavior的应用案例

1、实现滑动隐藏头部导航栏的效果

public class MyAppBarLayoutBehavior extends AppBarLayout.Behavior {

    public MyAppBarLayoutBehavior() {
        super();
    }

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

    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == SCROLL_AXIS_VERTICAL;
    }

    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            child.animate().alpha(0.0f).scaleX(0.0f).scaleY(0.0f).setDuration(200).setListener(new AnimatorListenerAdapter() {
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    child.setVisibility(View.GONE);
                }
            });
        } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
            child.setVisibility(View.VISIBLE);
            child.animate().alpha(1.0f).scaleX(1.0f).scaleY(1.0f).setDuration(200);
        }
    }
}

2、实现浮动按钮滑动隐藏的效果

public class MyFloatingActionButtonBehavior extends FloatingActionButton.Behavior {

    public MyFloatingActionButtonBehavior() {
        super();
    }

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

    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int axes) {
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes);
    }

    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        if (dyConsumed >= 0) {
            animateOut(child);
        } else {
            animateIn(child);
        }
    }

    private void animateOut(FloatingActionButton button) {
        CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) button.getLayoutParams();
        int bottomMargin = layoutParams.bottomMargin;
        button.animate().translationY(button.getHeight()+bottomMargin).setInterpolator(new AccelerateInterpolator(3)).start();
    }

    private void animateIn(FloatingActionButton button) {
        button.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3)).start();
    }
}

六、总结

本文从layout_behavior的定义、CoordinatorLayout的布局机制、自定义Behavior的实现、layout_behavior的使用方法和案例分别进行了详细的阐述,帮助读者更加深入地了解layout_behavior在Android中的作用和细节,为其在实际开发中的应用提供了参考。