/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.squashandstretch; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; /** * This example shows how to add some life to a view during animation by deforming the shape. * As the button "falls", it stretches along the line of travel. When it hits the bottom, it * squashes, like a real object when hitting a surface. Then the button reverses these actions * to bounce back up to the start. * * Watch the associated video for this demo on the DevBytes channel of developer.android.com * or on the DevBytes playlist in the androiddevelopers channel on YouTube at * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0. */ public class SquashAndStretch extends Activity { private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator(); private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator(); ViewGroup mContainer = null; private static final long BASE_DURATION = 300; private long sAnimatorScale = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mContainer = (ViewGroup) findViewById(R.id.container); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_slow) { sAnimatorScale = item.isChecked() ? 1 : 5; item.setChecked(!item.isChecked()); } return super.onOptionsItemSelected(item); } public void onButtonClick(View view) { long animationDuration = (long) (BASE_DURATION * sAnimatorScale); // Scale around bottom/middle to simplify squash against the window bottom view.setPivotX(view.getWidth() / 2); view.setPivotY(view.getHeight()); // Animate the button down, accelerating, while also stretching in Y and squashing in X PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, mContainer.getHeight() - view.getHeight()); PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, .7f); PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.2f); ObjectAnimator downAnim = ObjectAnimator.ofPropertyValuesHolder( view, pvhTY, pvhSX, pvhSY); downAnim.setInterpolator(sAccelerator); downAnim.setDuration((long) (animationDuration * 2)); // Stretch in X, squash in Y, then reverse pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 2); pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, .5f); ObjectAnimator stretchAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhSX, pvhSY); stretchAnim.setRepeatCount(1); stretchAnim.setRepeatMode(ValueAnimator.REVERSE); stretchAnim.setInterpolator(sDecelerator); stretchAnim.setDuration(animationDuration); // Animate back to the start pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0); pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1); pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1); ObjectAnimator upAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY); upAnim.setDuration((long) (animationDuration * 2)); upAnim.setInterpolator(sDecelerator); AnimatorSet set = new AnimatorSet(); set.playSequentially(downAnim, stretchAnim, upAnim); set.start(); } }