实现自定义对话框中的属性动画-续

前言

前一篇文章讲解了在自定义对话框中加入属性动画。
但是有个小小缺憾,小飞机没有从屏幕边缘飞出,仅仅是在对话框的边缘消失。
那如何解决这个小问题呢?这是本篇要说明的重点。

其实,不复杂,只要在上篇对话框布局的基础上做一点改动。可见的区域还是那么大,其他部分只不过是半透明。飞机就可以飞出屏幕了。

目标

这篇blog解决上篇遇到的问题: “假如让这个曲线动画沿着自定义对话框的最上侧往上飞出屏幕或是往下飞出屏幕,该如何实现?”

图形分析

上篇的坐标系参考下图
平移坐标01

说明:
图中的原点(0,0)取的是相对坐标,而不是手机最左上角开始。
而是从对话框的最左上角开始的,然后沿着x轴飞上或飞下。

那回到这篇,我们的坐标系需要变化下, 如下图:
图形平移坐标02

说明:
这个是在上图的基础上,将X轴,Y轴分别往上,往左移动。两图相比,确实是可以这么理解。
但是为了分析这个问题, 还是需要依照图中的标记来说明。
因为对话框的布局撑满了屏幕宽度,背景使用白色,然后在可见区域还是之前的白色图片。
原点(0,0)是在外框的左上角,小飞机的坐标是(50dp, 80dp) 也就是图中的deltaX, deltaY值。

其中需要注意的是从原点(0,0)平移到原点(50dp, 80dp)后,要达到小飞机还是沿着y=80dp这条x轴线跑动往上飞,
需要将 -y值 + 2 * deltaY。

关键点

布局示意图

布局示意图

布局文件 layout.dlg_custom_dialog_fullscreen_anim

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_dlg_container1"
    android:layout_width="fill_parent"
    android:layout_height="400dp"
    android:layout_centerInParent="true"
    android:layout_gravity="center" >

    <RelativeLayout
        android:id="@+id/rl_dlg_container"
        android:layout_width="wrap_content"
        android:layout_height="240dp"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:background="@drawable/bg_dialog" >

        <TextView
            android:id="@+id/tv_dlg_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="15dp"
            android:clickable="true"
            android:text="@string/tv_dlg_title" />

        <TextView
            android:id="@+id/tv_dlg_flyup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_dlg_title"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="53dp"
            android:clickable="true"
            android:text="@string/tv_fly_up" />

        <TextView
            android:id="@+id/tv_dlg_flydown"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_dlg_flyup"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="29dp"
            android:clickable="true"
            android:text="@string/tv_fly_down" />
    </RelativeLayout>

    <ImageView
        android:id="@+id/iv_small_plane"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignLeft="@id/rl_dlg_container"
        android:layout_alignTop="@id/rl_dlg_container"
        android:background="@drawable/plane" 
        android:visibility="invisible"/>

</RelativeLayout>

对话框宽度充满屏幕

DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

customDialog.getWindow().getAttributes().width = metrics.widthPixels;

坐标转换

// 坐标系xy 转换
plane_start_x = Utils.dip2px(mContext,PLANE_START_POINTF_X);
plane_start_y = Utils.dip2px(mContext,PLANE_START_POINTF_Y);

全屏动画时初始化贝塞尔的起点p0, p2

        // full screen anim
        valueAnimator = ValueAnimator.ofObject(new PlaneEvaluator(type),
                new PointF(plane_start_x, plane_start_y), new PointF(width
                        + plane_start_x, height + plane_start_y));
        // full screen anim end

PointF evaluate 中的变化

// full screen anim
/*
 * if (this.type == 0) {// up point1.set(width_up, 0); } else {//
 * down point1.set(width_down, 0); }
 */

if (this.type == 0) {// up
    point1.set(width_up + plane_start_x, plane_start_y);
} else {// down
    point1.set(width_down + plane_start_x, plane_start_y);
}

point.x = oneMinusT * oneMinusT * (point0.x) + 2 * oneMinusT * t
        * (point1.x) + t * t * (point2.x);
point.y = oneMinusT * oneMinusT * (point0.y) + 2 * oneMinusT * t
        * (point1.y) + t * t * (point2.y);

/*
 * if (this.type == 0) { point.y = -point.y; }
 */
if (this.type == 0) {// y值反向, 坐标系移位后,y值 * 2
    point.y = -point.y + plane_start_y * 2;
}
// full screen anim end

小结

结合2篇blog,要实现能在各种屏幕下使用的曲线的属性动画,需要如下几个步骤:
1)对应的布局文件以及view
2)屏幕适应的长宽,需要调整最优的数字dp单位
3)实现属性动画的 TypeEvaluator
4)定义ValueAnimator valueAnimator; 然后使用类是的方式初始化:

ValueAnimator.ofObject(new PlaneEvaluator(type),
new PointF(plane_start_x, plane_start_y), new PointF(width+ plane_start_x, height + plane_start_y));

5)设置特定的动画时间valueAnimator.setDuration(2000);
动画的addUpdateListener,
valueAnimator.addListener(new AnimatorListenerAdapter()

6) 以及动画的目标,重复次数,模式
valueAnimator.setTarget(mIvPlane);
valueAnimator.setRepeatCount(1);
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);

7)valueAnimator.start();

源码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值