Home | History | Annotate | Download | only in squashandstretch
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.squashandstretch;
     18 
     19 import android.animation.AnimatorSet;
     20 import android.animation.ObjectAnimator;
     21 import android.animation.PropertyValuesHolder;
     22 import android.animation.ValueAnimator;
     23 import android.app.Activity;
     24 import android.os.Bundle;
     25 import android.view.Menu;
     26 import android.view.MenuItem;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.view.animation.AccelerateInterpolator;
     30 import android.view.animation.DecelerateInterpolator;
     31 
     32 /**
     33  * This example shows how to add some life to a view during animation by deforming the shape.
     34  * As the button "falls", it stretches along the line of travel. When it hits the bottom, it
     35  * squashes, like a real object when hitting a surface. Then the button reverses these actions
     36  * to bounce back up to the start.
     37  *
     38  * Watch the associated video for this demo on the DevBytes channel of developer.android.com
     39  * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
     40  * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
     41  */
     42 public class SquashAndStretch extends Activity {
     43 
     44     private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
     45     private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
     46 
     47     ViewGroup mContainer = null;
     48     private static final long BASE_DURATION = 300;
     49     private long sAnimatorScale = 1;
     50 
     51     @Override
     52     protected void onCreate(Bundle savedInstanceState) {
     53         super.onCreate(savedInstanceState);
     54         setContentView(R.layout.main);
     55 
     56         mContainer = (ViewGroup) findViewById(R.id.container);
     57     }
     58 
     59     @Override
     60     public boolean onCreateOptionsMenu(Menu menu) {
     61         getMenuInflater().inflate(R.menu.main, menu);
     62         return true;
     63     }
     64 
     65     @Override
     66     public boolean onOptionsItemSelected(MenuItem item) {
     67         if (item.getItemId() == R.id.menu_slow) {
     68             sAnimatorScale = item.isChecked() ? 1 : 5;
     69             item.setChecked(!item.isChecked());
     70         }
     71         return super.onOptionsItemSelected(item);
     72     }
     73 
     74     public void onButtonClick(View view) {
     75         long animationDuration = (long) (BASE_DURATION * sAnimatorScale);
     76 
     77         // Scale around bottom/middle to simplify squash against the window bottom
     78         view.setPivotX(view.getWidth() / 2);
     79         view.setPivotY(view.getHeight());
     80 
     81         // Animate the button down, accelerating, while also stretching in Y and squashing in X
     82         PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
     83                 mContainer.getHeight() - view.getHeight());
     84         PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, .7f);
     85         PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.2f);
     86         ObjectAnimator downAnim = ObjectAnimator.ofPropertyValuesHolder(
     87                 view, pvhTY, pvhSX, pvhSY);
     88         downAnim.setInterpolator(sAccelerator);
     89         downAnim.setDuration((long) (animationDuration * 2));
     90 
     91         // Stretch in X, squash in Y, then reverse
     92         pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 2);
     93         pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, .5f);
     94         ObjectAnimator stretchAnim =
     95                 ObjectAnimator.ofPropertyValuesHolder(view, pvhSX, pvhSY);
     96         stretchAnim.setRepeatCount(1);
     97         stretchAnim.setRepeatMode(ValueAnimator.REVERSE);
     98         stretchAnim.setInterpolator(sDecelerator);
     99         stretchAnim.setDuration(animationDuration);
    100 
    101         // Animate back to the start
    102         pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0);
    103         pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
    104         pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
    105         ObjectAnimator upAnim =
    106                 ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
    107         upAnim.setDuration((long) (animationDuration * 2));
    108         upAnim.setInterpolator(sDecelerator);
    109 
    110         AnimatorSet set = new AnimatorSet();
    111         set.playSequentially(downAnim, stretchAnim, upAnim);
    112         set.start();
    113     }
    114 }
    115