English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Анимация запуска имитации приложения с клапаном

Используя приложение Wallet, я обнаружил, что анимация запуска очень забавная, поэтому я решил имитировать её реализацию.

Эффект анимации gif:


animation.gif

Путь к реализации:

Если внимательно посмотреть, можно увидеть, что выполнение анимации делится на два этапа:
Первая фаза - падение монеты.
Вторая фаза -反弹 кошелька.

Layout xml файл如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools" 
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      tools:context=".MainActivity">
  <ImageView
    android:id="@+id/coin_iv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@mipmap/coin"/>
  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_marginBottom="70dp"
    android:layout_marginLeft="70dp"
    android:src="@mipmap/version"/>
  <ImageView
    android:id="@+id/wallet_iv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@mipmap/wallet"/>
  <Button
    android:id="@+id/start_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center|bottom"
    android:layout_marginBottom="10dp"
    android:text="start"/>
</FrameLayout>

Падение монеты:

Во время падения монеты выполняются два типа анимаций: перемещение и вращение.
Анимация перемещения использует интерполяцию, xml-файл следующий:

<?xml version="1.0" encoding="utf-8"?>
<translate
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:fromYDelta="-50%p"
  android:interpolator="@android:anim/accelerate_interpolator"
  android:toYDelta="0%"/>

Ротационная анимация реализована через перезапись класса Animation и использование класса android.hardware.Camera.

public class ThreeDRotateAnimation extends Animation { 
 int centerX, centerY; 
 Camera camera = new Camera(); 
  @Override
  public void initialize(int width, int height, int parentWidth, int parentHeight) {  
  super.initialize(width, height, parentWidth, parentHeight);  
  // координаты центра
  centerX = width / 2;  
  centerY = height / 2; 
  setDuration(500);  
  setInterpolator(new LinearInterpolator()); 
 }  
@Override  
protected void applyTransformation(float interpolatedTime, Transformation t) {  
  final Matrix matrix = t.getMatrix();
  camera.save(); 
  // вращение вокруг оси Y
  camera.rotateY(360 * interpolatedTime);  
  camera.getMatrix(matrix);  
  // установка центра поворота 
  matrix.preTranslate(-centerX, -centerY); 
  matrix.postTranslate(centerX, centerY);   
  camera.restore();  
 }
}

Здесь кратко介绍一下 методы preTranslate и postTranslate в animation, preTranslate означает перед вращением rotateY выполнять перевод, а postTranslate означает выполнять перевод после rotateY, обратите внимание, что их параметры — это расстояние перевода, а не координаты цели перевода!
Поскольку вращение происходит вокруг центра (0,0), чтобы центрировать центр монеты с (0,0), необходимо выполнить preTranslate(-centerX, -centerY), после выполнения rotateY вызывается postTranslate(centerX, centerY), чтобы вернуть изображение обратно, и именно так видна анимация, где монета постоянно вращается вокруг центра.
В конце выполняются оба типа анимаций, чтобы был достигнут эффект падения и вращения.

private void startCoin() {
// падение
Animation animationTranslate = AnimationUtils.loadAnimation(this, R.anim.anim_top_in);
// вращение
ThreeDRotateAnimation animation3D = new ThreeDRotateAnimation();
animation3D.setRepeatCount(10);
AnimationSet animationSet = new AnimationSet(true);
animationSet.setDuration(800);
animationSet.addAnimation(animation3D);
animationSet.addAnimation(animationTranslate);
mCoinIv.startAnimation(animationSet);
}

钱包反弹:

在执行硬币掉落的同时,启动一个ValueAnimator动画,来判断钱包反弹的时机。

private void setWallet() {
final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(800);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
  @Override  public void onAnimationUpdate(ValueAnimator animation) {
    float fraction = animation.getAnimatedFraction();
    // 大概掉落到钱包的上边缘位置的时候,取消ValueAnimator动画,并执行钱包反弹效果
    if (fraction >= 0.75) {
      valueAnimator.cancel();
      startWallet();
    } 
  }});
valueAnimator.start();
}

最后执行钱包反弹效果动画,这里采用了ObjectAnimator 。

private void startWallet() {
  // x轴缩放
  ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(mLogoIv, "scaleX", 1, 1.1f, 0.9f, 1);
  objectAnimator1.setDuration(600);
  // y轴缩放 
  ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mLogoIv, "scaleY", 1, 0.75f, 1.25f, 1);
  objectAnimator2.setDuration(600);
  AnimatorSet animatorSet = new AnimatorSet();
  animatorSet.setInterpolator(new LinearInterpolator()); 
  // Одновременное выполнение анимации масштабирования по осям x и y 
  animatorSet.playTogether(objectAnimator1, objectAnimator2);
  animatorSet.start();}

Эффект анимации простого запуска钱包差不多 готов, единственный недостаток - при масштабировании кошелька по оси y, масштабируется вся ось y. Чтобы не двигать нижнюю часть кошелька, необходимо поднять верхнюю часть кошелька, пока не думал о хорошем способе, малый брат не очень умный, надеюсь, что великие мастера дадут советы! Спасибо!

Полный исходный код:

Полный исходный код находится вGitHub
Если вам это нравится, не забудьте starred╰( ̄▽ ̄)╮!

Вот и все, что есть в этой статье, я надеюсь, что это поможет вам в изучении. Надеюсь, что вы также поддержите и хлопайте в ладоши руководству Yell.

Заявление: контент этой статьи взят из Интернета, авторские права принадлежат соответствующему автору, контент предоставлен пользователями Интернета, сайт не обладает правами собственности, не был обработан редакторами, и не несет ответственности за соответствующие юридические последствия. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма, пожалуйста, замените # на @) для отчета,并提供相关证据. При обнаружении факта нарушения, сайт немедленно удаляет涉嫌侵权的内容。

Основной учебник
Вам может понравиться