CoordinatorLayout_Behavior控制Toolbar&Fab的显示和隐藏

前言

       Behavior是Android新出的Design库里新增的布局概念。Behavior只有是CoordinatorLayout的直接子View才有意义。可以为任何View添加一个Behavior。Behavior是一系列回调。让你有机会以非侵入的为View添加动态的依赖布局,和处理父布局(CoordinatorLayout)滑动手势的机会。

效果~

    


Part 1、利用监听事件来实现显示和隐藏动画

布局

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.andly.administrator.andly_md9.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize"
        />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:src="@android:drawable/ic_dialog_email"
        android:layout_margin="16dp"
        app:elevation="10dp"
        app:fabSize="normal"
        app:pressedTranslationZ="12dp"
        app:rippleColor="#ff0"
        />
</RelativeLayout>
为RecyclerView设置监听事件

rv.addOnScrollListener(new FabScrollListener(this));
public class FabScrollListener extends RecyclerView.OnScrollListener {
    private int distance = 0;//滑动的距离,根据距离于临界值比较判断是向上滑还是向下滑
    private HideScrollListener hideListener;//这里使用监听让Activity进行实现
    private boolean visible = true;//是否可见

    public FabScrollListener(HideScrollListener hideScrollListener) {
        // TODO Auto-generated constructor stub
        this.hideListener = hideScrollListener;
    }
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        //dy有正有负,向上滑为负 向下滑为正
        if (distance < -ViewConfiguration.getTouchSlop() && !visible) {
            //显示Fab和ToolBar
            hideListener.onShow();
            distance = 0;
            visible = true;
        } else if (distance > ViewConfiguration.getTouchSlop() && visible) {
            //隐藏Fab和ToolBar
            hideListener.onHide();
            distance = 0;
            visible = false;
        }
        if ((dy > 0 && visible) || (dy < 0 && !visible))//向下滑并且可见  或者  向上滑并且不可见
            distance += dy;
    }
}
这里通过distance和visible的判断来实现toolbar和fab的显示和隐藏

相应的实现

    @Override
    public void onHide() {
        mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams();
        ViewCompat.animate(fab).translationY(fab.getHeight() + layoutParams.bottomMargin + layoutParams.topMargin).setInterpolator(new AccelerateInterpolator(3));
    }

    @Override
    public void onShow() {
        mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
        ViewCompat.animate(fab).translationY(0).setInterpolator(new DecelerateInterpolator(3));
    }
效果~

    


Part 2、Behavior控制Toolbar&Fab的显示和隐藏

CoordinatorLayout继承ViewGroup,通过协调并调度里面的子控件来实现触摸并产生一些相关的动画,可以通过设置View的Behavior来实现触摸的动画调度

布局

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.andly.administrator.andly_md9.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="?attr/actionBarSize"
        />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_dialog_email"
        app:elevation="10dp"
        app:fabSize="normal"
        app:layout_behavior=".FabBehavior"
        app:pressedTranslationZ="12dp"
        app:rippleColor="#ff0"/>


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

1、要用CoordinatorLayout进行包裹

2、app:layout_behavior="包名+类名" 这里注意的是在Behavior子类加上构造方法

    public FabBehavior(Context context, AttributeSet attrs) {
        super();
    }
不然会报Could not inflate Behavior subclass异常

相应的自定义Behavior,这里继承的是FloatingActionButton.Behavior类

public class FabBehavior extends FloatingActionButton.Behavior {
    private boolean visible = true;//是否可见

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

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

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout,
                               FloatingActionButton child, View target, int dxConsumed,
                               int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
                dxUnconsumed, dyUnconsumed);
        if (dyConsumed > 0 && visible) {
            //show
            visible = false;
            onHide(child, (Toolbar) coordinatorLayout.getChildAt(1));
        } else if (dyConsumed < 0) {
            //hide
            visible = true;
            onShow(child, (Toolbar) coordinatorLayout.getChildAt(1));
        }

    }

    public void onHide(FloatingActionButton fab, Toolbar toolbar) {
        toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));
        CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
        fab.animate().translationY(fab.getHeight() + layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3));
    }

    public void onShow(FloatingActionButton fab, Toolbar toolbar) {
        toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
        fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
    }

}
tips:

1、onStartNestedScroll() : 当观察的View滑动开始的时候进行回调

2、onNestedScroll() : 当观察的View滑动的时候回调

3、nestedScrollAxes : 滑动的关联轴,这里只考虑竖直方向

当然你可以使用github上第三方库https://github.com/makovkastar/FloatingActionButton

步骤:

1、添加依赖

dependencies {
    compile 'com.melnykov:floatingactionbutton:1.3.0'
}
2、在布局中引用自定义FloatingActionButton
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:fab="http://schemas.android.com/apk/res-auto"
             android:layout_width="match_parent"
             android:layout_height="match_parent">

    <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    <com.melnykov.fab.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:layout_margin="16dp"
            android:src="@drawable/ic_action_content_new"
            fab:fab_colorNormal="@color/primary"
            fab:fab_colorPressed="@color/primary_pressed"
            fab:fab_colorRipple="@color/ripple" />
</FrameLayout>
3、关联Fab到ScrollView、ListView、RecyclerView

ListView listView = (ListView) findViewById(android.R.id.list);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.attachToListView(listView);
4、在布局中设置

        fab:fab_type="mini"
        fab:fab_colorNormal="@color/primary"
        fab:fab_colorPressed="@color/primary_pressed"
        fab:fab_shadow="false"
        fab:fab_colorRipple="@color/ripple"
或者在代码中进行设置

        fab.setType(FloatingActionButton.TYPE_MINI);
        fab.setColorNormal(getResources().getColor(R.color.primary));
        fab.setColorPressed(getResources().getColor(R.color.primary_pressed));
        fab.setShadow(false);
        fab.show();
        fab.hide();
        fab.show(false); // Show without an animation
        fab.hide(false); // Hide without an animation
        fab.setColorRipple(getResources().getColor(R.color.ripple));






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值