Share
Embed
Material Animations: show me the code!
- Why animate?
- Good animation samples
- Available tools to animate
- Transition Framework
- Activity transitions
- Shared element transitions
- View property animations
- Complex animations
- Circular Reveal
> Animated slides
https://www.youtube.com/watch?v=5e1Yh0fSZhQ
> Resources
Material Animations: Code Samples
https://github.com/lgvalle/Material-Animations
Alex Lockwood: Transition Framework
http://goo.gl/y4ZSsp
Saul Molinero: User interface
http://goo.gl/8gex9n
Chris Basha: Overhauling the Twitter Experience on Android
https://goo.gl/F281b2
Material Witness: How Android material applications work
https://youtu.be/97SWYiRtF0Y
Pasquale D’Silva: Designing with animation
https://youtu.be/TMe0WnkF1Lc
Luis G. Valle
October 02, 2015
Transcript
50 slides
-
Where things go? What can I do? Where am I?
Where things come from? -
https://medium.com/@BashaChris/overhauling-the-twitter-experience-on-android-80f5b09e7c67 Overhauling the Twitter Experience on Android Where things come
Where things go? Where am I? What can I do? -
Property Animation System (API 11) View property changes Transition Framework
(API 19) View property changes Layout changes ViewAnimationUtils (API 21) CircularReveal Activity Transitions Fragment Transitions -
Animate screen transitions exit · enter · shared startActivity(B) A
Exit Enter A B B … B Return Reenter B A A … back() -
startActivity(B) A Exit Enter A B B … B Return
Reenter B A A … back() Cross-fade by default Reversed enter/exit by default -
startActivity(B) A Exit Enter A B B … B Return
Reenter B A A … back() But you can customise! Cross-fade by default Reversed enter/exit by default -
> activities/MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Explode explode = new Explode(); getWindow().setExitTransition(explode); } Exit Transition @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); } > activities/DetailsActivity.java -
startActivity(B) A Exit Enter A B B … B Return
Reenter B A A … back() A B B A Enter and Exit animations overlap each other Transition Overlap -
startActivity(B) A Exit Enter A B B … B Return
Reenter B A A … back() A B B A Enter and Exit animations overlap each other Transition Overlap -
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Explode explode =
new Explode(); getWindow().setExitTransition(explode); } Disable overlap @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); } > activities/DetailsActivity.java -
> activities/MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Explode explode = new Explode(); explode.excludeTarget(R.id.toolbar, true); getWindow().setExitTransition(explode); } Exclude Views @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. getWindow().setAllowEnterTransitionOverlap(false); } > activities/ -
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Explode explode =
new Explode(); explode.excludeTarget(R.id.toolbar, true); getWindow().setExitTransition(explode); } Return Transition @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); Slide slide = new Slide(Gravity.RIGHT); getWindow().setReturnTransition(slide); } > activities/DetailsActivity.java -
Shared Element Transition startActivity(B) A Exit Enter A B B
… B Return Reenter B A A … back() Shared Element Shared Element has its own transitions -
res/values/styles.xml <style name=“MaterialAnimations.Main"> <item name=“android:windowContentTransitions”>true</item> … </style> 1. Enable content
transition activities/MainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); … } -OR- -
> activities/MainActivity.java Intent i = new Intent(this, DetailsActivity.class); ActivityOptions
options = ActivityOptions .makeSceneTransitionAnimation( this, rowView, // shared element view "rowName"); // common transition name startActivity(i, options.toBundle()); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. getWindow().setAllowEnterTransitionOverlap(false); } > activities/ 3. Start Activity (with options) -
> activities/DetailsActivity.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { @Override
public void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } … }); Transition listener -
> activities/DetailsActivity.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { @Override
public void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } … }); Transition listener Don’t forget! -
> activities/DetailsActivity.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { @Override
public void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } … }); Transition listener @Override public void onBackPressed() { fab.setVisibility(View.INVISIBLE); finishAfterTransition(); } -
> activities/DetailsActivity.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { @Override
public void onTransitionEnd(Transition t) { fab.animate().scaleX(1f).scaleY(1f) fade.removeListener(this); } … }); Transition listener @Override public void onBackPressed() { fab.animate().scaleX(0f).scaleY(0f) .withEndAction(new Runnable() { @Override public void run() { finishAfterTransition(); } }); } -
> activities/DetailsActivity.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { @Override
public void onTransitionEnd(Transition t) { fab.animate().scaleX(1f).scaleY(1f) fade.removeListener(this); } … }); Transition listener @Override public void onBackPressed() { fab.animate().scaleX(0f).scaleY(0f) .withEndAction(new Runnable() { @Override public void run() { finishAfterTransition(); } }); } Property Animation System (API 11+) -
public void onClickFab() { int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater
= TransitionInflater.from(this); Transition transition = inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams) } FAB Transition -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams); FAB Transition Inflate transition from XML! -
<?xml version="1.0" encoding="utf-8"?> <changeBounds android:duration="@integer/anim_duration_long" android:interpolator="@android:interpolator/decelerate_cubic"> <arcMotion android:maximumAngle="45" android:minimumHorizontalAngle="90"
android:minimumVerticalAngle="0" /> </changeBounds> > res/transitions/changebounds_with_arcmotion.xml -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams); FAB Transition -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams); FAB Transition -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams); FAB Transition -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); TransitionManager.beginDelayedTransition(viewRoot, transition); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); fab.setLayoutParams(layoutParams); FAB Transition Where is the Circular Reveal?! -
Circular Reveal Title A Title A Title A Title B
Bacon ipsum dolor amet sausage bacon pork chop strip steak cow porchetta landjaeger ham sirloin swine leberkas prosciutto turducken ball tip. Pork chop kielbasa shank cow, pig corned beef hamburger -
Circular Reveal (x,y) x = (left + right) / 2
y = (top + bottom) / 2 startRadius = 0 endRadius = max(width, height) createCircularReveal(view, x, y, startRadius, endRadius) left right top bottom -
int x = (view.getLeft() + view.getRight()) / 2; int y
= (view.getTop() + view.getBottom()) / 2; int startRadius = 0; int endRadius = Math.max(view.getWidth(), view.getHeight()); Animator anim = ViewAnimationUtils .createCircularReveal(view, x, y, startRadius, endRadius); view.setVisibility(View.VISIBLE); anim.start(); Circular Reveal (x,y) left right top bottom -
int transitionId = R.transition.changebounds_with_arcmotion; TransitionInflater inflater = TransitionInflater.from(this); Transition transition
= inflater.inflateTransition(transitionId); transition.addListener(new Transition.TransitionListener() { @Override public void onTransitionEnd(Transition transition) { fab.setVisibility(View.GONE); createRevealForView(extraContent); } }); (…) private Animator createRevealForView(ViewGroup view) { int x = (view.getLeft() + view.getRight()) / 2; int y = view.getBottom(); float finalRadius = (float) Math.max(view.getWidth(), view.getHeight()); Animator anim = ViewAnimationUtils.createCircularReveal(view, x, y, 0, finalRadius); viewRoot.setVisibility(View.VISIBLE); anim.start(); } Circular Reveal -
-Shared element Transition -Transition Listener -Enter / Exit Transition -Property
Animation System -Delayed Transitions -Circular Reveal -
Pasquale D’Silva: Designing with animation https://youtu.be/TMe0WnkF1Lc Material Animations: Code Samples
https://github.com/lgvalle/Material-Animations Alex Lockwood: Transition Framework http://goo.gl/y4ZSsp Saul Molinero: User interface http://goo.gl/8gex9n Material Witness: How Android material applications work https://youtu.be/97SWYiRtF0Y Chris Basha: Overhauling the Twitter Experience on Android https://goo.gl/F281b2 Resources