上一篇我们讲了自定义behavior监听控件的状态变化:例如垂直方向位移的变化。今天我们要谈的是如何监听控件的滑动事件。就是说当布局文件里有一个可滑动的控件(如RecyclerView、NestedScrollView、Viewpager页面里的NestedScrollView)滑动时,我们自定义的behavior可以帮观察者监听到该类事件,同时做相应的处理。我们还是从布局文件讲起,在此之前先看以下运行效果:

android 判断NestedScrollView是否在滑动 android coordinatorlayout 滑动监听_控件

 

1. 布局文件

<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:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nestedScroll"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="left">

        <LinearLayout
            android:id="@+id/nestedScrollLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/bt2"
                android:layout_margin="50dp"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d1"
                android:textColor="@color/white" />

            <ImageView
                android:layout_margin="50dp"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d2"
                android:textColor="@color/white" />

            <ImageView
                android:layout_margin="50dp"
                android:id="@+id/bt1"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d2"
                android:textColor="@color/white" />

            <ImageView
                android:layout_margin="50dp"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d2"
                android:textColor="@color/white" />


            <ImageView
                android:layout_margin="50dp"
                android:id="@+id/bt21"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d2"
                android:tag="tv1"
                android:textColor="@color/white" />

            <ImageView
                android:layout_margin="50dp"
                android:id="@+id/bt23"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_gravity="left|top"
                android:background="@drawable/d2"
                android:tag="tv1"
                android:textColor="@color/white" />
        </LinearLayout>

    </android.support.v4.widget.NestedScrollView>


    <ImageView
        android:background="@drawable/d1"
        android:id="@+id/obeserver"
        android:layout_marginRight="20dp"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:layout_gravity="right|center_vertical"
        android:text="观察者"
        app:layout_behavior="com.example.custombehavior.ListenerScrollBehavior" />
</android.support.design.widget.CoordinatorLayout>

在这里我们声明一个被观测者NestedScrollView,再声明一个观察者NestedScrollView,同时为观察者配置一个自定义behavior:layout_behavior="com.example.custombehavior.ListenerScrollBehavior". 我们看到这个布局的根布局仍然是CoordinatorLayout,这与我们之前的一样,CoordinatorLayout布局捕捉到事件及控件状态变化后,分发给我们自定义的behavior。接下来我们就来看一下这个自定义behavior的实现,看它是如何来监听控件的滑动事件。

 

2. 自定义Behavior实现

package com.example.custombehavior;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.CoordinatorLayout.Behavior;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.NestedScrollView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.util.Random;

public class ListenerScrollBehavior extends Behavior<View> {

	public ListenerScrollBehavior(Context arg0, AttributeSet arg1) {
		super(arg0, arg1);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 用来决定谁是观察者,谁是被观察者
	 * @param  coordinatorLayout ,父容器
	 * @param  child, 观察者
	 @param  directTargetChild,被观察者
	 @param target: 与directTargetChild指的是同一个控件NestedScrollView
	 */
	@Override
	public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
			View child, View directTargetChild, View target,
			int nestedScrollAxes) {
		// TODO Auto-generated method stub


		//监听垂直滚动
		return (nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL)||super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
				target, nestedScrollAxes);
	}
	
	@Override
	public void onNestedPreScroll(CoordinatorLayout coordinatorLayout,
			View child, View target, int dx, int dy, int[] consumed) {
		// TODO Auto-generated method stub
		
		child.animate().rotation( dy* 360);
		super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
	}
	
	@Override
	public boolean onNestedFling(CoordinatorLayout coordinatorLayout,
			View child, View target, float velocityX, float velocityY,
			boolean consumed) {
		return super.onNestedFling(coordinatorLayout, child, target, velocityX,
				velocityY, consumed);
	}
	
}

这里和上一篇类似,只是重写的函数不一样,我们来介绍以下几个函数“

1.onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes);

CoordinatorLayout :根布局

child:观察者

directTargetChild:被观察者

target:还是被观察者,在这里与directTargetChild指向的控件是同一个

nestedScrollAxes:将要监听的滚动方向,垂直还是水平。

child是观察者,对应布局里的id为observer控件 ;directTargetChild是被观察者,对应布局里的id为NestedScrollView控件。

nestedScrollAxes表示滚动的方向。在此我们return (nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL)表示我们只监听NestedScrollView的垂直滑动事件。

2.onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed)

当滑动时执行。

CoordinatorLayout :根布局

child:观察者

target:被观察者,在这里与directTargetChild指向的控件是同一个

nestedScrollAxes:将要监听的滚动方向,垂直还是水平。

dx:每次滚动的水平距离

dy:每次滚动的垂直距离

这里我们让观察者child执行动画:child.animate().rotation( dy* 360); 这样就实现了观察者监听到滑动事件并作出相应的处理。

3. onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed)

滚动的惯性。在这里我们没有用到,用于监听滚动的惯性,就是当人手指松开后列表还会滑动一段距离,我们可以检测到velocityX与velocityY两个惯性值,运用场景可以是:当滑动一个列表时,让另一个列表 跟着滑动,而且另一个列表的惯性值要与列表1的惯性值一样,才能真正保持同步滑动。

CoordinatorLayout :根布局

child:观察者

target:被观察者

velocityX  轴滚动的惯性值,就是人手指松开后列表还会滑动一段距离

velocityY  轴滚动的惯性值,就是人手指松开后列表还会滑动一段距离

consumed: 这个还不理解,望请指教。