当前位置: 移动技术网 > IT编程>移动开发>Android > Material Design系列之自定义Behavior支持所有View

Material Design系列之自定义Behavior支持所有View

2019年07月24日  | 移动技术网IT编程  | 我要评论

厂长退役,wwe8月11日,马君潞

本文实例为大家分享了android自定义behavior支持所有view ,供大家参考,具体内容如下

一、实现效果图

这个右下角的fab,动画当然可以多种多样,可以放在界面的任何地方,我们这里只举个例子。但是v7包中提供的behavior目前只能是floatingactionbutton来用,所以今天我们实现的这个behavior是支持所有的view的,可以用在imageview、button、layout,只要是继承view的类都可以用。

二、自定义behavior和动画的封装

我们知道behavior是coordinatorlayout的一个子类,ctrl + t查看它的实现类目前有如下几个:

1. appbarlayout.behavior;
2. appbarlayout.scrollingviewbehavior;
3. floatingactionbutton.behavior;
4. snackbar.behavior;
5. bottomsheetbehaviro;
6. swipedismissbehavior;
7. headerbehavior;
8. viewoffsetbehavior;
9. headerscrollingviewbehavior;

其中第1、7是抽象类,8是package保护的类,9是8的一个子类,我们回头再说。

appbarlayout.scrollingviewbehavior我们经常用,也就是我们在layout xml中经常用的:app:layout_behavior="@string/appbar_scrolling_view_behavior"。

snackbar.behavior被用于snackbar,这个不用多说。

floatingactionbutton.behavior、bottomsheetbehaviro、swipedismissbehavior在文章开头的几个友情链接的博客中已经讲的很清楚了,大家可以回过头去再看看。

今天讲的是自定义behavior支持所有view作为fab,那么也就是floatingactionbutton.behavior了,但是它只支持floatingactionbutton,所以今天我们要自己继承behavior来写definebehavior。所以第一步就是打开floatingactionbutton.behavior的源码看。

实现basicbehavior

首先必须要知道的是coordinatorlayout.behavior这个基类是支持泛型的,看到floatingactionbutton.behavior后发先它是限制了引用它的view必须是floatingactionbutton罢了,那我们这里也来学它继承一下就ok了。

我们新建一个类basicbehavior,把floatingactionbutton.behavior的代码拷贝过来,把里面的泛型改为如下:

public class basicbehavior<t extends view> extends coordinatorlayout.behavior<t>;

也就是说只要引用实现basicbehavior的类是个view就可以,所以接着把basicbehavior里面拷贝的代码中把引用泛型为floatingactionbutton的地方改为view,嗯觉得打工告成的时候发现有几个类的包导不进来:

仔细一看,这几个类在android.support.design.widget包下,一想肯定这几个类是package保护的类,所以我们在我们的项目下新建一个android.support.design.widget包,把实现basicbehavior移到新建的包下,发现问题迎刃而解。

项目源码和basicbehavior的完整源代码下载链接请在文章开头或者末尾找。

动画的实现和简化

(没看之前博客的客观一定要回过头看看,一定会有不一样的收获。)
我们在之前的同系列博客中,实现view的缩放动画的时候,尤其是在view被隐藏时须用如下代码记录view移出动画是否执行完,因为在界面滑动的时候view移除会被behavior一直调用,所以不能重复执行,需要用一个值来记录:

// 记录view移出动画是否执行完。
private boolean isoutexecute = false;

private viewpropertyanimatorlistener outanimatorlistener = new viewpropertyanimatorlistener() {
 @override
 public void onanimationstart(view view) {
 isoutexecute = true;
 }

 @override
 public void onanimationend(view view) {
 view.setvisibility(view.gone);
 isoutexecute = false;
 }

 @override
 public void onanimationcancel(view view) {
 isoutexecute = false;
 }
};

为了不在每一个调用的地方都写这么长一段,我们把这端代码封装成一个类,简化如下:

public static class listeneranimatorendbuild {
 // 记录view移出动画是否执行完。
 private boolean isoutexecute = false;

 private viewpropertyanimatorlistener outanimatorlistener;

 public listeneranimatorendbuild() {
 outanimatorlistener = new viewpropertyanimatorlistener() {
 @override
 public void onanimationstart(view view) {
 isoutexecute = true;
 }
 @override
 public void onanimationend(view view) {
 view.setvisibility(view.gone);
 isoutexecute = false;
 }

 @override
 public void onanimationcancel(view view) {
 isoutexecute = false;
 }
 };
 }

 // view移出动画是否执行完。
 public boolean isfinish() {
 return !isoutexecute;
 }

 // 返回viewpropertyanimatorlistener。
 public viewpropertyanimatorlistener build() {
 return outanimatorlistener;
 }
}

这样一来我们在用的时候就只是两行代码了:

listeneranimatorendbuild listeneranimatorendbuild = new listeneranimatorendbuild();

// 判断是否执行完动画:
listeneranimatorendbuild.isfinish();

继承basicbehavior实现definebavior

前面定义好了basicbehavior,这里只需要继承basicbehavior实现我们的动画逻辑:

public class definebehavior extends basicbehavior<view> {

 private listeneranimatorendbuild listeneranimatorendbuild;

 public definebehavior(context context, attributeset attrs) {
 super(context, attrs);
 listeneranimatorendbuild = new listeneranimatorendbuild();
 }

 @override
 public boolean onstartnestedscroll(coordinatorlayout coordinatorlayout, view child, view directtargetchild, view target, int nestedscrollaxes) {
 return nestedscrollaxes == viewcompat.scroll_axis_vertical;
 }

 @override
 public void onnestedscroll(coordinatorlayout coordinatorlayout, view child, view target, int dxconsumed, int dyconsumed, int dxunconsumed, int dyunconsumed) {
// if (dyconsumed > 0 && dyunconsumed == 0) {
// system.out.println("上滑中。。。");
// }
// if (dyconsumed == 0 && dyunconsumed > 0) {
// system.out.println("到边界了还在上滑。。。");
// }
// if (dyconsumed < 0 && dyunconsumed == 0) {
// system.out.println("下滑中。。。");
// }
// if (dyconsumed == 0 && dyunconsumed < 0) {
// system.out.println("到边界了,还在下滑。。。");
// }

 // 这里可以写你的其他逻辑动画,这里只是举例子写了个缩放动画。
 if ((dyconsumed > 0 || dyunconsumed > 0) && listeneranimatorendbuild.isfinish() && child.getvisibility() == view.visible) {//往下滑
 scalehide(child, listeneranimatorendbuild.build());
 } else if ((dyconsumed < 0 || dyunconsumed < 0) && child.getvisibility() != view.visible) {
 scaleshow(child, null);
 }
 }
}

你可能会很惊讶,哈哈,不要惊讶,封装的好久是这么简单就能实现所有的view支持。

三、如何使用

使用和google提供的behavior一样,引用完整包名就可以:

app:layout_behavior="com.yanzhenjie.definebehavior.behavior.definebehavior"

为了和google提供的behavior使用一样简单,我们可以string.xml中定义一下这个string:

<string name="define_behavior">com.yanzhenjie.definebehavior.behavior.definebehavior</string>

用的时候:

app:layout_behavior="@string/define_behavior"

现在我们把原来项目中的floatingactionbutton换成imageview:

<imageview
 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="@mipmap/ic_launcher"
 app:layout_behavior="@string/define_behavior"
 app:layout_scrollflags="scroll|enteralways|snap" />

好吧,ok了,具体效果大家下载源码:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网