Android CoordinatorLayout高级用法之自定义Behavior

上次简单的说了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析实例)。其中CoordinatorLayout给我们提供了一种新的事件的处理方式,Behavior。还记得那一串字符串吗?

1

app:layout_behavior="@string/appbar_scrolling_view_behavior"

其实它并不是一个字符串资源,而它代表的是一个类,就是一个Behavior,这玩意其实还可以自定义的。

首先,来让我见识一下它的真面目:

1

2

3

public static abstract class Behavior<V extends View> {

...

}

Behavior是CoordinatorLayout的一个内部泛型抽象类。内部类中指定的view类型规定了哪种类型的view的可以使用才Behavior。因此,如果没有特殊需求,直接指定view为View就行了。

1.某个view需要根据监听另一个的行为来控制自己的行为,这个时候我们需要重写2个方法:

1

2

3

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

      return false;

    }

1

2

3

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

      return false;

    }

2.我们的view需要根据监听CoordinatorLayout中的子view的滚动行为来改变自己的状态,现在我们就需要重写下面的方法了:

1

2

3

4

public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,

    V child, View directTargetChild, View target, int nestedScrollAxes) {

  return false;

}

1

2

3

4

public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target,

    int dx, int dy, int[] consumed) {

  // Do nothing

}

下面我们先来看一下情况1,让一个view跟随另一个view的行为而实现状态的改变。我们定义一个Behavior,名字叫:FooterBehavior,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

package com.lingyun.coordinatorlayoutdemo; 

import android.content.Context;

import android.support.design.widget.AppBarLayout;

import android.support.design.widget.CoordinatorLayout;

import android.util.AttributeSet;

import android.view.View; 

/**

 * Created by dandy on 2016/7/4.

 */

public class FooterBehavior extends CoordinatorLayout.Behavior<View>{

  

  public FooterBehavior(Context context,AttributeSet attributeSet){

    super(context,attributeSet);

  }

  

  @Override

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

    return dependency instanceof AppBarLayout;

  }

  

  @Override

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

    float scaleY = Math.abs(dependency.getY()) / dependency.getHeight();

    child.setTranslationY(child.getHeight() * scaleY);

    return true;

  }

}

我们在自定义的Behavior中,带有参数的这个构造必须要重载,因为在CoordinatorLayout里利用反射去获取这个Behavior的时候就是拿的这个构造。

在layoutDependsOn中,我们设置让View的状态来跟随AppBarLayout,也就是说只有AppBarLayout的状态发生变化才会影响到View。

接下来就是在onDependentViewChanged中对View做出相应的状态改变。在代码中,我们做的改变是,跟随dependedcy一起在Y轴方向移动,来达到显示和隐藏的目的。先布局如下:

activity_main.xml布局:

1

2

3

4

5

6

7

8

9

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout

 xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  <include layout="@layout/appbar_main"/> 

  <include layout="@layout/content_main" /> 

  <include layout="@layout/footer_main"/> 

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

appbar_main.xml布局如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout

  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="wrap_content"

  android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

  

  <android.support.v7.widget.Toolbar

    android:id="@+id/toolbar"

    android:layout_width="match_parent"

    android:layout_height="?attr/actionBarSize"

    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

    android:background="?attr/colorPrimary"

    app:layout_scrollFlags="scroll|enterAlways"/>

  

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

content_main.xml布局如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.NestedScrollView

  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"

  app:layout_behavior="@string/appbar_scrolling_view_behavior">

  

  <TextView

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:gravity="center"

    android:text="你是谁?你从哪里来?你到哪里去?"/>

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

footer_main.xml布局如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  xmlns:app="http://schemas.android.com/apk/res-auto"

  android:orientation="horizontal"

  android:layout_width="match_parent"

  android:layout_height="60dp"

  android:layout_gravity="bottom"

  android:background="?attr/colorPrimary"

  app:layout_behavior="com.lingyun.coordinatorlayoutdemo.FooterBehavior">

  

  <TextView

    android:layout_width="0dp"

    android:layout_height="match_parent"

    android:text="Tab1"

    android:layout_weight="1"

    android:gravity="center"

    android:textColor="@android:color/white"/>

  <TextView

    android:layout_width="0dp"

    android:layout_height="match_parent"

    android:text="Tab2"

    android:layout_weight="1"

    android:gravity="center"

    android:textColor="@android:color/white"/>

  <TextView

    android:layout_width="0dp"

    android:layout_height="match_parent"

    android:text="Tab3"

    android:layout_weight="1"

    android:gravity="center"

    android:textColor="@android:color/white"/>

  

</LinearLayout>

注意看,在footer_main.xml中我们设置了

1

app:layout_behavior="com.lingyun.coordinatorlayoutdemo.FooterBehavior"

这正好就是我们自定义的FooterBehavior的绝对路径。下面我们来看一下效果图:

在效果图上我们看到,当我们上下滑动屏幕的时候,底部footer布局和标题Toolbar一起移动,实现了显示和隐藏的效果。

学会了第一张简单的自定义Behavior之后,接下来我们再来看一下第二种情况,滑动。因为这个是根据CoordinatorLayout里子view的滚动行为来改变我们的状态的,所以情况1中的2个方法我们就不需要重写了。下面,我们用情况2来实现上面的效果。
先来看一下下面几个参数:

child:简单点说,就是用到当前CoordinatorLayout的子View,响应此Behavior。

target:CoordinatorLayout的子View,引起滚动的view,其实child的状态改变是根据target来实现的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

package com.lingyun.coordinatorlayoutdemo; 

import android.content.Context;

import android.support.design.widget.CoordinatorLayout;

import android.support.v4.view.ViewCompat;

import android.util.AttributeSet;

import android.view.View;

  

/**

 * Created by dandy on 2016/7/4.

 */

public class FooterBehavior extends CoordinatorLayout.Behavior<View>{

  

  private float targetY = -1;

  

  private static final String TAG = "FooterBehavior";

  

  public FooterBehavior(Context context,AttributeSet attributeSet){

    super(context, attributeSet);

  }

  

  @Override

  public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child,

                    View directTargetChild, View target, int nestedScrollAxes) {

    if(targetY == -1){

      targetY = target.getY();

    }

    return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;

  }

  

  @Override

  public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target,

                 int dx, int dy, int[] consumed) {

    super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);

    float scrooY = targetY - Math.abs(target.getY());

    float scaleY = scrooY / targetY;

    child.setTranslationY(child.getHeight() * scaleY);

  }

}

在方法onStartNestedScroll中,首先获取target在Y轴上距离屏幕顶端的距离,然后判断是否是在Y轴上滚动。
方法onNestPreScroll中,就是时时根据target距离屏幕顶端的距离计算出滚动的距离,然后根据比例计算出child移动的距离。
截图和上面比较没啥区别:

基本的自定义Behavior就是这样了,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

 

 

转自 https://www.jb51.net/article/134141.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值