Android CoordinatorLayout高级用法之自定义Behavior

作者:FightSeeker 时间:2022-03-20 05:47:51 

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


app:layout_behavior="@string/appbar_scrolling_view_behavior"

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

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


public static abstract class Behavior<V extends View> {
...
}

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

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


public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
     return false;
   }

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

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


public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
   V child, View directTargetChild, View target, int nestedScrollAxes) {
 return false;
}

public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target,
   int dx, int dy, int[] consumed) {
 // Do nothing
}

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


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布局:


<?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布局如下:


<?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布局如下:


<?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布局如下:


<?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中我们设置了


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

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

Android CoordinatorLayout高级用法之自定义Behavior

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

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

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

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


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移动的距离。
截图和上面比较没啥区别:

Android CoordinatorLayout高级用法之自定义Behavior

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

来源:http://blog.csdn.net/tabolt/article/details/51821933

标签:Android,CoordinatorLayout,Behavior
0
投稿

猜你喜欢

  • SpringBoot整合TKMyBatis实现单表增删改查操作

    2022-01-30 19:52:28
  • 详解java 客户端链接不上redis解决方案

    2023-11-12 10:12:15
  • 基于C#实现手机号码归属地接口调用

    2022-07-14 09:46:54
  • C# 获取客户端IPv4地址的示例代码

    2022-09-12 12:39:34
  • Java Map简介_动力节点Java学院整理

    2023-06-03 20:27:03
  • SpringBoot集成FTP与SFTP连接池流程

    2021-12-27 12:22:26
  • Java实现简单图书借阅系统

    2023-11-22 01:09:02
  • Java里的static import使用小结

    2023-08-18 18:36:36
  • java 完全二叉树的构建与四种遍历方法示例

    2022-03-21 00:48:04
  • 新手入门Jvm-- JVM对象创建与内存分配机制

    2021-11-04 19:28:10
  • Spring Security 图片验证码功能的实例代码

    2023-11-17 14:23:56
  • java实现波雷费密码算法示例代码

    2022-09-14 23:30:28
  • Maven搭建springboot项目的方法步骤

    2022-08-08 09:50:09
  • C#读取目录下所有指定类型文件的方法

    2023-05-01 10:59:14
  • c#集合快速排序类实现代码分享

    2023-03-30 13:38:51
  • 浅谈Android开发中项目的文件结构及规范化部署建议

    2022-05-13 12:47:37
  • MyBatis-Plus中更新操作的两种实现

    2022-06-24 03:09:14
  • SpringBoot自动装配原理详解

    2023-07-03 05:49:08
  • 使用Java读取Word文件的简单例子分享

    2022-12-17 02:15:19
  • SpringBoot整合Elasticsearch并实现CRUD操作

    2021-10-28 07:27:31
  • asp之家 软件编程 m.aspxhome.com