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

在项目中,我们要求做一个纸飞机的功能:就是当打开这个界面时,会有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);
    }

    @Override
    protected 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;
    }

    @Override
    public 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;

    @Override
    protected 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() {
                @Override
                public 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() {
            @Override
            public 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() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // 飞机飞入动画
                downPlaneAnimation(iconView);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public 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() {
            @Override
            public void onAnimationStart(Animator animation) {
                iconView.setRotationY(180);
            }

            @Override
            public void onAnimationEnd(Animator animation) {

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public 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() {
            @Override
            public void onAnimationStart(Animator animation) {
                iconView.setRotationY(0);
            }

            @Override
            public void onAnimationEnd(Animator animation) {

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });

        AnimatorSet mFlyAnimator = new AnimatorSet();
        mFlyAnimator.playSequentially(flyDownAnim, flyInAnim);
        mFlyAnimator.start();
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值