Android Realization of Simple Operation of Paper Airplane

  • 2021-09-11 21:11:34
  • OfStack

In the project, we asked to do the function of a paper airplane: when this interface is opened, four paper airplanes will fly in from the left side of the screen, and then reach their own positions to sit up and down, while clouds will constantly float from the right side of the screen to the left side of the screen. When you click on one of the paper airplanes, the paper airplane first flies up and out of the screen, then flies in from the left side. When the airplane returns to its original position, a message box pops up. The following code is directly listed:

1. First, customize an RelativeLayout, the main purpose of which is to make the entry animation of the aircraft:


public class PaperPlaneLayout extends RelativeLayout implements View.OnClickListener{
  private OnClickListener mOnClickListener;

  // Customize the width and height of the layout 
  private int mHeight;
  private int mWidth;
  private LayoutParams lp;
  private Drawable[] drawables;
  private Random random = new Random();

  // Get 4 Width and height of paper airplane 
  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() {
    //  Initialize the displayed picture 
    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;
    //  Get the width and height of a graph   Used for later calculations 
    //  Attention   Here I am 4 The size of each picture is 1 Like , So I just took 1 A 
    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();
  }

  // The entrance to the real animation, which is called from the outside, x , y Respectively indicate that after the aircraft enters, 
  // Position coordinates of staying 
  public void addHeart(int x, int y, int position) {
    mX = x;
    mY = y;
    ImageView imageView = new ImageView(getContext());
    //  Random selection 1 A 
    imageView.setImageDrawable(drawables[position]);
    imageView.setLayoutParams(lp);
    addView(imageView);
    // Get animation before and after entering 
    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);
    }
  }

  // Definition ImageView Click event 
  public interface OnClickListener {
    void onClick(ImageView v);
  }

2. The next step is to build the layout file (only select 1 part of the control)


<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">

  <!-- White clouds -->
  <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" />

  <!-- Custom Aircraft Layout Animation -->
  <com.cloudi.forum.view.PaperPlaneLayout
    android:id="@+id/plane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
</RelativeLayout> 

3. Now you can use it in 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;
  // Set whether the aircraft has been clicked, if yes true , then another 1 Planes are not clickable 
  private boolean mIsClick = true;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_plane_layout);
    ButterKnife.bind(this);
    mContext = getApplicationContext();
    // Initialize animation 
    initAnimation();
    initListener();
  }

  private void initAnimation() {
    // Set the entry position of the paper airplane 
    initPlaneEnterAnimation();
    // The plane floats up and down after entering 
    initPlaneAnimation();
    // Clouds circulate from the right side of the screen to the left side of the screen 
    initCloudAnimation();
  }

  // Set the entry position of the paper airplane 
  private void initPlaneEnterAnimation() {
    for (int i = 0; i < 4; i++) {
      final int temp = i;
      mPlaneLayout.post(new Runnable() {
        @Override
        public void run() {
          // The following values are set by the user himself 
          if (temp == 0) {
            mPlaneLayout.addHeart(
              100dp, 140dp, 0);
          }
          if (temp == 1) {
            mPlaneLayout.addHeart(
               Screen width  - 120dp, 190dp, 1);
          }
          if (temp == 2) {
            mPlaneLayout.addHeart(
              30dp, 240dp, 2);
          }
          if (temp == 3) {
            mPlaneLayout.addHeart(
               Screen width  - 210, 290, 3);
          }
        }
      });
    }
  }

  // The plane floats up and down after entering 
  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();
  }

  // Clouds circulate from the right side of the screen to the left side of the screen 
  private void initCloudAnimation() {
    if (objCloudAnim == null) {
      objCloudAnim = ObjectAnimator
        .ofFloat(mImgWhiteCloud, "translationX", 
           Screen width  - 50, - Screen width );
      //  Set duration 
      objCloudAnim.setDuration(5000);
      //  Set up loop playback 
      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();
          // When clicking on a 1 When there is a paper plane, the plane will have 1 Flying out animation 
          planeOutAnimation(v);
        }
      }
    });
  }

  /**
   *  Airplane flying out animation 
   */
  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) {
        //  Airplane flying in animation 
        downPlaneAnimation(iconView);
      }

      @Override
      public void onAnimationCancel(Animator animation) {

      }

      @Override
      public void onAnimationRepeat(Animator animation) {

      }
    });
    flyUpAnim.start();
  }

  /**
   *  Airplane flying in animation 
   */
  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();
  }

In this way, the entry and exit animation of paper airplane is completed.


Related articles: