在项目中,我们要求做一个纸飞机的功能:就是当打开这个界面时,会有4架纸飞机从屏幕左侧飞入,然后到达自己的位置坐上下浮动,同时云彩也不断地从屏幕右侧飘到屏幕左侧。当你点击其中一个纸飞机时,这个纸飞机先向上飞出屏幕外,再从左侧飞入,当飞机回到原来位置时,弹出一个消息框。下面直接上代码:

一、首先自定义一个RelativeLayout,主要目的就是制作飞机的进入动画:


public class PaperPlaneLayout extends RelativeLayout implements View.OnClickListener{private OnClickListener mOnClickListener;//自定义布局的宽、高private int mHeight;private int mWidth;private LayoutParams lp;private Drawable[] drawables;private Random random = new Random();//获取4架纸飞机的宽高private int dHeight;private int dWidth;private int mX;private int mY;public PaperPlaneLayout(Context context) {super(context);init();}public PaperPlaneLayout(Context context, AttributeSet attrs) {super(context, attrs);init();}public PaperPlaneLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public PaperPlaneLayout(Context context, AttributeSet attrs,int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init();}private void init() {// 初始化显示的图片drawables = new Drawable[4];Drawable pink = getResources().getDrawable(R.drawable.pl_pink);Drawable yellow = getResources().getDrawable(R.drawable.pl_yellow);Drawable green = getResources().getDrawable(R.drawable.pl_green);Drawable blue = getResources().getDrawable(R.drawable.pl_blue);drawables[0] = blue;drawables[1] = yellow;drawables[2] = green;drawables[3] = pink;// 获取图的宽高 用于后面的计算// 注意 我这里4张图片的大小都是一样的,所以我只取了一个dHeight = UIUtility.dipTopx(getContext(), 80);dWidth = UIUtility.dipTopx(getContext(), 80);lp = new LayoutParams(dWidth, dHeight);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();}//真正动画开始的入口,从外部进行调用,x、y分别表示飞机进入之后所//停留的位置坐标public void addHeart(int x, int y, int position) {mX = x;mY = y;ImageView imageView = new ImageView(getContext());// 随机选一个imageView.setImageDrawable(drawables[position]);imageView.setLayoutParams(lp);addView(imageView);//获取进入前后动画Animator set = getAnimator(imageView);set.start();imageView.setOnClickListener(this);}private Animator getAnimator(View target) {AnimatorSet set = getEnterAnimator(target);AnimatorSet set2 = getLineAnimation(target);AnimatorSet finalSet = new AnimatorSet();finalSet.playSequentially(set, set2);finalSet.setInterpolator(new LinearInterpolator());finalSet.setTarget(target);return finalSet;}private AnimatorSet getEnterAnimator(final View target) {ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f);ObjectAnimator translationX = ObjectAnimator.ofFloat(target, View.TRANSLATION_X, -2 * mWidth, -mWidth);AnimatorSet enter = new AnimatorSet();enter.setDuration(500);enter.setInterpolator(new LinearInterpolator());enter.playTogether(translationX, alpha);enter.setTarget(target);return enter;}private AnimatorSet getLineAnimation(final View iconView) {ObjectAnimator transX = ObjectAnimator.ofFloat(iconView, "translationX", -dWidth, mX);ObjectAnimator transY = ObjectAnimator.ofFloat(iconView, "translationY", (mHeight - dHeight) / 2, mY);transY.setInterpolator(PathInterpolatorCompat.create(0.7f, 1f));AnimatorSet flyUpAnim = new AnimatorSet();flyUpAnim.setDuration(900);flyUpAnim.playTogether(transX, transY);flyUpAnim.setTarget(iconView);return flyUpAnim;}@Overridepublic void onClick(View v) {if (mOnClickListener != null) {mOnClickListener.onClick((ImageView) v);}}//定义ImageView单击事件public interface OnClickListener {void onClick(ImageView v);}

二、接下来就是布局文件的搭建了(只选取一部分控件)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/relative_plane_bj"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/paper_plane_bg"><!--白云--><ImageView
        android:id="@+id/img_white_cloud"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/paper_plane_cloud"android:layout_centerHorizontal="true"android:layout_marginTop="30dp" /><!--自定义的飞机布局动画--><com.cloudi.forum.view.PaperPlaneLayout
        android:id="@+id/plane_layout"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout> 

三、接下来就可以在Activity中使用了:

public class PlaneActivity extends AppCompatActivity{@Bind(R.id.img_white_cloud)ImageView mImgWhiteCloud;@Bind(R.id.plane_layout)PaperPlaneLayout mPlaneLayout;private Context mContext;private ObjectAnimator objCloudAnim;private TranslateAnimation planeAnimation;private float iconX, iconY;//设置飞机是否已点击,如果为true,则另一个飞机不可点击private boolean mIsClick = true;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_plane_layout);ButterKnife.bind(this);mContext = getApplicationContext();//初始化动画initAnimation();initListener();}private void initAnimation() {//设定纸飞机进入的位置initPlaneEnterAnimation();//飞机进入后做上下浮动initPlaneAnimation();//云彩循环从屏幕右侧飘到屏幕左侧initCloudAnimation();}//设定纸飞机进入的位置private void initPlaneEnterAnimation() {for (int i = 0; i < 4; i++) {final int temp = i;mPlaneLayout.post(new Runnable() {@Overridepublic void run() {//下面的值根据用户自己设定if (temp == 0) {mPlaneLayout.addHeart(100dp, 140dp, 0);}if (temp == 1) {mPlaneLayout.addHeart(屏宽 - 120dp, 190dp, 1);}if (temp == 2) {mPlaneLayout.addHeart(30dp, 240dp, 2);}if (temp == 3) {mPlaneLayout.addHeart(屏宽 - 210, 290, 3);}}});}}//飞机进入后做上下浮动private void initPlaneAnimation() {planeAnimation = new TranslateAnimation(0, 0, -10, 10);planeAnimation.setDuration(1000);planeAnimation.setRepeatCount(Animation.INFINITE);planeAnimation.setRepeatMode(Animation.REVERSE);mPlaneLayout.setAnimation(planeAnimation);planeAnimation.start();}//云彩循环从屏幕右侧飘到屏幕左侧private void initCloudAnimation() {if (objCloudAnim == null) {objCloudAnim = ObjectAnimator.ofFloat(mImgWhiteCloud, "translationX", 屏宽 - 50, -屏宽);// 设置持续时间objCloudAnim.setDuration(5000);// 设置循环播放objCloudAnim.setRepeatCount(ObjectAnimator.INFINITE);}objCloudAnim.start();}private void initListener() {mPlaneLayout.setOnClickListener(new PaperPlaneLayout.OnClickListener() {@Overridepublic void onClick(ImageView v) {if (mIsClick) {mIsClick = false;iconX = v.getX();iconY = v.getY();//当点击某一个纸飞机时,飞机会有一个飞出动画planeOutAnimation(v);}}});}/*** 飞机飞出动画*/private void planeOutAnimation(final View iconView) {AnimatorSet flyUpAnim = new AnimatorSet();flyUpAnim.setDuration(600);ObjectAnimator transX = ObjectAnimator.ofFloat(iconView, "translationX", iconView.getX(), UIUtility.getScreenWidth(mContext) * 2);ObjectAnimator transY = ObjectAnimator.ofFloat(iconView, "translationY", 0, - UIUtility.getScreenHeight(mContext) * 2);transY.setInterpolator(PathInterpolatorCompat.create(0.7f, 1f));ObjectAnimator rotation = ObjectAnimator.ofFloat(iconView, "rotation", -45, 0);rotation.setInterpolator(new DecelerateInterpolator());ObjectAnimator rotationX = ObjectAnimator.ofFloat(iconView, "rotationX", 0, 60);rotationX.setInterpolator(new DecelerateInterpolator());flyUpAnim.playTogether(transX, transY, rotationX,ObjectAnimator.ofFloat(iconView, "scaleX", 1, 0.5f),ObjectAnimator.ofFloat(iconView, "scaleY", 1, 0.5f),rotation);flyUpAnim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {// 飞机飞入动画downPlaneAnimation(iconView);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});flyUpAnim.start();}/*** 飞机飞入动画*/private void downPlaneAnimation(final View iconView) {final int offDistX = -iconView.getRight();final int offDistY = -UIUtility.dipTopx(mContext, 10);AnimatorSet flyDownAnim = new AnimatorSet();flyDownAnim.setDuration(500);ObjectAnimator transX1 = ObjectAnimator.ofFloat(iconView, "translationX", UIUtility.getScreenWidth(mContext), offDistX);ObjectAnimator transY1 = ObjectAnimator.ofFloat(iconView, "translationY", - UIUtility.getScreenHeight(mContext), offDistY);transY1.setInterpolator(PathInterpolatorCompat.create(0.1f, 1f));ObjectAnimator rotation1 = ObjectAnimator.ofFloat(iconView, "rotation", iconView.getRotation(), 0);rotation1.setInterpolator(new AccelerateInterpolator());flyDownAnim.playTogether(transX1, transY1,ObjectAnimator.ofFloat(iconView, "scaleX", 0.5f, 0.9f),ObjectAnimator.ofFloat(iconView, "scaleY", 0.5f, 0.9f),rotation1);flyDownAnim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {iconView.setRotationY(180);}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});AnimatorSet flyInAnim = new AnimatorSet();flyInAnim.setDuration(500);flyInAnim.setInterpolator(new DecelerateInterpolator());ObjectAnimator tranX2 = ObjectAnimator.ofFloat(iconView, "translationX", offDistX, iconX);ObjectAnimator tranY2 = ObjectAnimator.ofFloat(iconView, "translationY", offDistY, iconY);ObjectAnimator rotationX2 = ObjectAnimator.ofFloat(iconView, "rotationX", 30, 0);flyInAnim.playTogether(tranX2, tranY2, rotationX2, ObjectAnimator.ofFloat(iconView, "scaleX", 0.9f, 1f),ObjectAnimator.ofFloat(iconView, "scaleY", 0.9f, 1f));flyInAnim.setStartDelay(100);flyInAnim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {iconView.setRotationY(0);}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});AnimatorSet mFlyAnimator = new AnimatorSet();mFlyAnimator.playSequentially(flyDownAnim, flyInAnim);mFlyAnimator.start();}

这样一来纸飞机的进入和点击离开动画就完成了。

Android实现简单的纸飞机操作(类似于漂流瓶)相关推荐

  1. 【JavaWeb开发-Servlet】拾起海中的漂流瓶

    项目原型: [JavaWeb开发-Servlet]老人言随机语录_代码骑士的博客-CSDN博客需求:点击网页按钮随机显示一句话:1.内容涵盖:老人言.励志语录.名言名言.一句情话2.设计要求:以老人言 ...

  2. 【JavaWeb开发-Servlet】拾起海中的漂流瓶增强版

    目录 原版: 1.前端样式 2.错误提示 3.实现id序列增长 完整项目代码: 原版: [JavaWeb开发-Servlet]拾起海中的漂流瓶_代码骑士的博客-CSDN博客需求:点击网页按钮随机显示一 ...

  3. android sqlite 操作类封装,SQLiteUtils 一个简单的基于 Android 的 Sqlite 数据库的操作封装库 @codeKK Android开源站...

    一个简单的基于 Android 的 Sqlite 数据库的操作封装,它有如下的好处: 便捷地创建表和增添表字段 通过操作对象来 insert 或者 update 表记录 支持多种查询方式,支持分页查询 ...

  4. Android 系统简单介绍

    Android 系统简单介绍 2011年11月20日 写这篇文章的目的是为了给那些刚刚入手安 卓手机的新手们一些参考,希望他们能快速的上手 [第一期]ANDROID基础知识1~20 [第二期]继续泡! ...

  5. Android Studio简单设置

    2019独角兽企业重金招聘Python工程师标准>>> Android Studio 简单设置 界面设置 默认的 Android Studio 为灰色界面,可以选择使用炫酷的黑色界面 ...

  6. android仿微信的activity平滑水平切换动画,Android实现简单底部导航栏 Android仿微信滑动切换效果...

    Android实现简单底部导航栏 Android仿微信滑动切换效果 发布时间:2020-10-09 19:48:00 来源:脚本之家 阅读:96 作者:丶白泽 Android仿微信滑动切换最终实现效果 ...

  7. 【转】Android Studio简单设置

    原文网址:http://ask.android-studio.org/?/article/14 Android Studio 简单设置 界面设置 默认的 Android Studio 为灰色界面,可以 ...

  8. android Glide简单使用

    今天,简单讲讲Android里Glide的简单使用. Android框架系列: 一.android EventBus的简单使用 二.android Glide简单使用 对于Glide这个加载图片的框架 ...

  9. android: listview与sqlite数据操作实例

    ListView与Sqlite数据库绑定步骤: 1.将Sqlite数据库的内容查询出来并放入数组列表中,形成ListView的数据源: 2.适配器绑定数据源,显示在ListView item中. 本文 ...

最新文章

  1. Gradle7.0,依赖统一管理的全新方式,了解一下~
  2. Python3.5+selenium操作Chrome浏览器的简单实例
  3. Android笔记 Application对象的使用-数据传递以及内存泄漏问题
  4. C#多线程开发-任务并行库
  5. spring的钩子_spring提供的钩子,你知道哪些
  6. 代码中 密码存储_你还记得浏览器自动存储的密码吗?用js代码恢复一下记忆吧...
  7. cuda nvcc版本不一致_windows 验证CUDA和CUDNN是否安装成功
  8. UI设计灵感|如何将数据摆放得整整齐齐?
  9. FreeNAS 安装与用户指导页
  10. Python学习笔记(五)—LOOP 循环
  11. 构建运营级IPv6网络
  12. ArcGIS 判断坐标系是否正确
  13. Java 程序员必会的「垃圾回收」算法
  14. vue做混合式app_基于vue2.0开发混合app的思考
  15. 基于cropper.js封装vue在线图片裁剪组件
  16. 学习是一件很辛苦的事,全世界都一样!
  17. Python常见问题 - pip报错 ValueError: Unable to find resource t32.exe in package pip._vendor.distlib
  18. php文字加边框,图片加特效文字 图片添加各种边框的文字效果 如果有多种边框模板就更好了...
  19. 数字化转型常见的5种问题:除了意识和能力问题,还有什么?
  20. php单例模式(Singleton)

热门文章

  1. Vue系列之vue生命周期详解
  2. 杭州内推 | 蚂蚁集团机器智能部招聘2024届算法实习生
  3. MySQL基础操作总结_CRUD
  4. 农村卖什么东西销量大?怎么找货源?
  5. matlab中cplxpair是什么,colon_HCOLON什么意思
  6. 还不认识Tux你就太low了
  7. 黑马Uni-App视频笔记(上) 基础部分(含视频素材下载地址)
  8. 上传服务器 验证码不显示不出来,部署以后 验证码不显示
  9. CAD软件使用打断命令
  10. 3.4softmax回归