Масштабная анимация с небольшим «отскоком» - PullRequest
1 голос
/ 10 октября 2019

Я пытаюсь использовать XML Animations , чтобы увеличить представление от 0% до 150% (на 50% больше, чем «реальный размер»). Затем уменьшите размер с 150% до «реального размера» 100%. Намерение - это что-то вроде эффекта «отскока», когда представление вырастет из ничего до большего, чем должно быть, а затем «отскок» или «возврат» к нужному размеру.

Вотизображение, которое иллюстрирует график того, что я хотел бы достичь.

Timeline of desired Animations

Я использую этот код анимации XML:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <scale android:fromXScale="0"
        android:fromYScale="0"
        android:toXScale="1.5"
        android:toYScale="1.5"
        android:duration="200"
        android:pivotX="50%"
        android:pivotY="100%"
        android:fillAfter="false"
        />
    <scale android:fromXScale="1.5"
        android:fromYScale="1.5"
        android:toXScale="1.0"
        android:toYScale="1.0"
        android:duration="100"
        android:pivotX="50%"
        android:pivotY="100%"
        android:startOffset="200"
        />
</set>

Проблема, с которой я сталкиваюсь, заключается в том, что после первогоМасштабирование анимации завершает представление правильно с размером 150%, но когда он запускает вторую анимацию, он масштабируется относительно размера, который мы закончили с первой анимацией (150%) как «реальный размер» 100% или 1,0.

Поэтому, когда запускается вторая анимация вместо того, чтобы мой масштаб уменьшился с 150% до реального размера 100%, это фактически масштабируется с 150% из 150% (225%) до 150%. Это означает, что в конце анимации вид все еще слишком велик, в моем случае он составляет 150% от реального размера.

Есть ли какой-нибудь способ дать указание второй анимации или набору анимации игнорировать конечное значение из первой анимации и вместо этого просто использовать «реальный» размер представления, чтобы код был более буквально интерпретирован ибудет масштабироваться от 150% реального размера до 100% реального размера.

Я пробовал каждую комбинацию fillBefore, fillAfter и fillEnabled, которую я могу придумать для каждой анимации масштаба ина самом устройстве, но до сих пор я не смог найти комбинацию этих настроек, которая заставит его вести себя так, как я намереваюсь.

Я нашел Эта статья , которая, кажется, может иметь отношение к моей ситуации, и это заставило меня опробовать еще несколько комбинаций различных свойств fill. Но до сих пор я не могу получить результат, на который я надеюсь.

Ответы [ 2 ]

3 голосов
/ 17 октября 2019

не должен быть простым Интерполятором для анимации, я имею в виду, что у вас не так много точного контроля над анимацией с точным временем, но что-то вроде этого должно сделать подобный трюк без такой большой работы:

<scale android:fromXScale="0"
    android:fromYScale="0"
    android:toXScale="1.0"
    android:toYScale="1.0"
    android:duration="300"
    android:pivotX="50%"
    android:pivotY="100%"
    android:fillAfter="true"
    android:interpolator="@android:anim/overshoot_interpolator"
    />
2 голосов
/ 14 октября 2019

Facebook имеет библиотеку Java под названием Rebound , которая моделирует динамику весны и добавляет физику реального мира. Пример кода:

import com.facebook.rebound.BaseSpringSystem;
import com.facebook.rebound.SimpleSpringListener;
import com.facebook.rebound.Spring;
import com.facebook.rebound.SpringSystem;
import com.facebook.rebound.SpringUtil;

/**
 * This Activity presents an ImageView that scales down when pressed and returns to full size when
 * released. This demonstrates a very simple integrates a very Simple integration of a Rebound
 * Spring model to drive a bouncy animation as the photo scales up and down. You can control the
 * Spring configuration by tapping on the blue nub at the bottom of the screen to reveal the
 * SpringConfiguratorView. From this view you can adjust the tension and friction of the animation
 * spring and observe the effect these values have on the animation.
 */
public class MainActivity extends Activity {

  private final BaseSpringSystem mSpringSystem = SpringSystem.create();
  private final ExampleSpringListener mSpringListener = new ExampleSpringListener();
  private FrameLayout mRootView;
  private Spring mScaleSpring;
  private View mImageView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);
    mRootView = (FrameLayout) findViewById(R.id.root_view);
    mImageView = mRootView.findViewById(R.id.image_view);

    // Create the animation spring.
    mScaleSpring = mSpringSystem.createSpring();

    // Add an OnTouchListener to the root view.
    mRootView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            // When pressed start solving the spring to 1.
            mScaleSpring.setEndValue(1);
            break;
          case MotionEvent.ACTION_UP:
          case MotionEvent.ACTION_CANCEL:
            // When released start solving the spring to 0.
            mScaleSpring.setEndValue(0);
            break;
        }
        return true;
      }
    });
  }

  @Override
  public void onResume() {
    super.onResume();
    // Add a listener to the spring when the Activity resumes.
    mScaleSpring.addListener(mSpringListener);
  }

  @Override
  public void onPause() {
    super.onPause();
    // Remove the listener to the spring when the Activity pauses.
    mScaleSpring.removeListener(mSpringListener);
  }

  private class ExampleSpringListener extends SimpleSpringListener {
    @Override
    public void onSpringUpdate(Spring spring) {
      // On each update of the spring value, we adjust the scale of the image view to match the
      // springs new value. We use the SpringUtil linear interpolation function mapValueFromRangeToRange
      // to translate the spring's 0 to 1 scale to a 100% to 50% scale range and apply that to the View
      // with setScaleX/Y. Note that rendering is an implementation detail of the application and not
      // Rebound itself. If you need Gingerbread compatibility consider using NineOldAndroids to update
      // your view properties in a backwards compatible manner.
      float mappedValue = (float) SpringUtil.mapValueFromRangeToRange(spring.getCurrentValue(), 0, 1, 1, 0.5);
      mImageView.setScaleX(mappedValue);
      mImageView.setScaleY(mappedValue);
    }
  }

}
...