合理的动画能让交互更加的舒服,不至于太过生硬。
在这篇文档中,我们将会通过一个简单的例子来了解如何在BasePopup实现动画。
更多动画相关内容,请查看 进阶指引——动画

BasePopup中的动画

BasePopup创建的初衷是让开发者在尽可能少的约束下实现各种天马行空的需求,因此在BasePopup中,开放了Animation的实现和Animator的实现。

由于BasePopup仅仅内置了简单的动画,因此大多数情况下,动画的具体实现都是交给您来完成。

2.2.4版本开始,背景蒙层渐变动画的时间将会与您的动画时间关联,不会产生动画比蒙层动画过早或者过晚完成的不和谐感觉(当然,您也可以配置是否同步,这都是可控的)
同时,我们在2.2.4中增加了动画创建工具类:AnimationHelper,通过该工具类,您可以非常方便的创建出您想要的动画,更多信息请查阅:进阶指引-动画-AnimationHelper

实现一个简单的动画

我们通过一个常见的场景来了解如何实现动画:

场景描述

  • 弹窗从底部弹出,动画为从下往上位移出现
  • 弹窗消失的时候动画改为从上往下位移消失

    布局

    我们简单的实现一个布局,由于常见的弹窗宽度都是填满屏幕宽度的,因此我们根布局宽度给match_parent,高度wrap_content即可。

同时由于要求弹窗从底部弹出,我们直接在xml中给根布局添加 android:layout_gravity=”bottom”
(因为篇幅问题,子控件我们仅保留部分代码,其余子控件代码都一样的)

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:layout_gravity="bottom"
  6. android:background="@color/white"
  7. android:orientation="vertical">
  8. <TextView
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:layout_gravity="center"
  12. android:gravity="center"
  13. android:padding="16dp"
  14. android:text="BasePopup"
  15. android:textColor="@color/text_black3"
  16. android:textSize="@dimen/text_large" />
  17. <View style="@style/divider" />
  18. <!--其他子控件都是copy这两个子控件而已,代码略-->
  19. </LinearLayout>

效果图:

TIM截图20200705112049.png

Popup代码

按照前面的指引完成我们的基本代码,然后我们override两个动画的方法:

  • onCreateShowAnimation():弹窗展示动画
  • onCreateDismissAnimation():弹窗消失动画

      class Demo extends BasePopupWindow {
    
          public Demo(Context context) {
              super(context);
              setContentView(R.layout.popup_slide);
          }
    
          @Override
          protected Animation onCreateShowAnimation() {
              //这里完成展示动画
              return super.onCreateShowAnimation();
          }
    
          @Override
          protected Animation onCreateDismissAnimation() {
              //这里完成消失动画
              return super.onCreateDismissAnimation();
          }
      }
    

    动画代码

    首先完成我们的展示代码,需求要求我们完成由下往上的位移代码,因此我们可以创建一个简单的
    TranslateAnimation:

  • x位移:保持0即可,因为我们x方向上不需要位移

  • y位移:1到0,这里填的是float值,意思是从相对于自己而言,y方向上从100%位移到0%。(对于自己来说,y方向上100%意味着自己的bottom所在位置,0%意味着默认位置,即xml上展示的位置)

          @Override
          protected Animation onCreateShowAnimation() {
              //这里完成展示动画
              TranslateAnimation showAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                      0,
                      Animation.RELATIVE_TO_SELF,
                      0,
                      Animation.RELATIVE_TO_SELF,
                      1f,
                      Animation.RELATIVE_TO_SELF,
                      0);
              showAnimation.setDuration(500);
              return showAnimation;
          }
    

    如果您的BasePopup版本是2.2.3或以上,还可以选择override同名不同参的方法,该方法回调的参数是ContentView的宽高:

          @Override
          protected Animation onCreateShowAnimation(int width, int height) {
              TranslateAnimation showAnimation = new TranslateAnimation(0, 0, height, 0);
              showAnimation.setDuration(500);
              return showAnimation;
          }
    

    如果您的BasePopup版本是2.2.4或以上,您还可以使用AnimationHelper快速的创建您需要的动画,更多相关信息可以查阅文档

      @Override
      protected Animation onCreateShowAnimation() {
          return AnimationHelper.asAnimation()
                  .withTranslation(TranslationConfig.FROM_BOTTOM)
                  .toShow();
      }
    

    弹窗展示动画效果

    ezgif-5-b9673db18450 (1).gif
    完成展示的动画后,我们继续完成消失动画,动画非常简单,跟展示动画相反即可。

  • x位移:保持0即可,因为我们x方向上不需要位移

  • y位移:0到1,这里填的是float值,意思是从相对于自己而言,y方向上从0%位移到100%。(对于自己来说,y方向上100%意味着自己的bottom所在位置,0%意味着默认位置,即xml上展示的位置)
          @Override
          protected Animation onCreateDismissAnimation() {
              //这里完成消失动画
              TranslateAnimation dismissAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                      0,
                      Animation.RELATIVE_TO_SELF,
                      0,
                      Animation.RELATIVE_TO_SELF,
                      0f,
                      Animation.RELATIVE_TO_SELF,
                      1f);
              dismissAnimation.setDuration(500);
              return dismissAnimation;
          }
    
    如果您的BasePopup版本是2.2.3或以上,还可以选择override同名不同参的方法,该方法回调的参数是ContentView的宽高:
          @Override
          protected Animation onCreateDismissAnimation(int width, int height) {
              TranslateAnimation dismissAnimation = new TranslateAnimation(0, 0, 0, height);
              dismissAnimation.setDuration(500);
              return dismissAnimation;
          }
    
    如果您的BasePopup版本是2.2.4或以上,您还可以使用AnimationHelper快速的创建您需要的动画,更多相关信息可以查阅文档
      @Override
      protected Animation onCreateDismissAnimation() {
          return AnimationHelper.asAnimation()
                  .withTranslation(TranslationConfig.TO_BOTTOM)
                  .toDismiss();
      }
    

    弹窗消失效果

    ezgif-5-eb6402623153.gif