Share
Embed
Material Animations: show me the code! (Codemotion 2015)
** Codemotion Madrid 2015 **
- Why animate?
- Good animation samples
- Available tools to animate
- Transition Framework
- Activity transitions
- Shared element transitions
- View property animations
- Complex animations
- Circular Reveal
> 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
November 27, 2015
Transcript
74 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 12) View property changes Transition Framework
(API 19) View property changes Layout changes ViewAnimationUtils (API 21) CircularReveal Activity Transitions Fragment Transitions How can we animate? -
Property Animation System (API 12) View property changes Transition Framework
(API 19) View property changes Layout changes ViewAnimationUtils (API 21) CircularReveal Activity Transitions Fragment Transitions How can we animate? -
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 Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A Default: Cross-fade back() Default: Reversed enter/exit -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A Default: Cross-fade back() Default: Reversed enter/exit But you can customise! -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
> activities/Activity_A.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/Activity_B.java -
> activities/Activity_A.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/Activity_B.java -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() Default: Transitions Overlap -
> activities/Activity_A.java @Override 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); } > activities/Activity_B.java -
> activities/Activity_A.java @Override 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/Activity_B.java -
> activities/Activity_A.java @Override 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/Activity_B.java -
> activities/Activity_A.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.activity_details); getWindow().setAllowEnterTransitionOverlap(false); } > activities/Activity_B.java -
> activities/Activity_A.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.activity_details); getWindow().setAllowEnterTransitionOverlap(false); } > activities/Activity_B.java -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() -
> activities/Activity_A.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); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); } > activities/Activity_B.java Return Transition -
> activities/Activity_A.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); } 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/Activity_B.java -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() Shared Element has its own transitions Reversed shared element transition -
res/values/styles.xml <style name=“MaterialAnimations.Main"> <item name=“android:windowContentTransitions”>true</ item> … </style> 1. Enable
content transition activities/Activity_A.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); … } -OR- -
> activities/Activity_A.java Intent i = new Intent(this, Activity_B.class); ActivityOptions
options = ActivityOptions .makeSceneTransitionAnimation( this, rowView, // shared element view "rowName"); // common transition name startActivity(i, options.toBundle()); 3. Start Activity (with options) -
startActivity(B) A Exit Transition Enter Transition A B B B
Return Transition Reenter Transition B A A back() Transition Listener Transition Listener -
Transition Listener > activities/Activity_B.java @Override protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); } -
Transition Listener > activities/Activity_B.java @Override protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); getWindow().getEnterTransition() .addListener(new TransitionListener() { @Override public void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } … }); } Don’t forget! -
Transition Listener > activities/Activity_B.java @Override protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); getWindow().setAllowEnterTransitionOverlap(false); getWindow().getEnterTransition() .addListener(new TransitionListener() { @Override public void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } … }); } @Override public void onBackPressed() { fab.setVisibility(View.INVISIBLE); finishAfterTransition(); } -
> activities/Activity_B.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { public
void onTransitionEnd(Transition t) { fab.setVisibility(View.VISIBLE); fade.removeListener(this); } }); public void onBackPressed() { fab.setVisibility(View.INVISIBLE); finishAfterTransition(); } (API 12+) Property animation system -
> activities/Activity_B.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { public
void onTransitionEnd(Transition t) { fab.animate() .scaleX(1f) .scaleY(1f) fade.removeListener(this); } }); public void onBackPressed() { fab.animate() .scaleX(0f) .scaleY(0f) .withEndAction(new Runnable() { @Override public void run() { finishAfterTransition(); } }); } (API 12+) Property animation system -
> activities/Activity_B.java Transition fade = getWindow().getEnterTransition(); fade.addListener(new TransitionListener() { public
void onTransitionEnd(Transition t) { fab.animate() .scaleX(1f) .scaleY(1f) fade.removeListener(this); } }); public void onBackPressed() { fab.animate() .scaleX(0f) .scaleY(0f) .withEndAction(new Runnable() { @Override public void run() { finishAfterTransition(); } }); } (API 12+) Property animation system -
public void onClickFab() { Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); TransitionManager
.beginDelayedTransition(viewRoot, transition); fab.setLayoutParams( new RelativeLayout.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, CENTER_HORIZONTAL, ALIGN_PARENT_BOTTOM) ); } Fab Transition -
public void onClickFab() { Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); TransitionManager
.beginDelayedTransition(viewRoot, transition); fab.setLayoutParams( new RelativeLayout.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, CENTER_HORIZONTAL, ALIGN_PARENT_BOTTOM) ); } Fab Transition Inflate transition from XML! -
activities/TargetActivity.java <?xml version="1.0" encoding="utf-8"?> <changeBounds android:duration="@integer/anim_duration_long" android:interpolator=“@android/decelerate_cubic"> <arcMotion android:maximumAngle="45"
android:minimumHorizontalAngle="90" android:minimumVerticalAngle="0" /> </changeBounds> > res/transitions/changebounds_with_arcmotion.xml -
public void onClickFab() { Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); TransitionManager
.beginDelayedTransition(viewRoot, transition); fab.setLayoutParams( new RelativeLayout.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, CENTER_HORIZONTAL, ALIGN_PARENT_BOTTOM) ); } Fab Transition -
public void onClickFab() { Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); TransitionManager
.beginDelayedTransition(viewRoot, transition); fab.setLayoutParams( new RelativeLayout.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, CENTER_HORIZONTAL, ALIGN_PARENT_BOTTOM) ); } Fab Transition -
public void onClickFab() { Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); TransitionManager
.beginDelayedTransition(viewRoot, transition); fab.setLayoutParams( new RelativeLayout.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, CENTER_HORIZONTAL, ALIGN_PARENT_BOTTOM) ); } Fab Transition Where is the 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 Animation -
Circular Reveal Animation int x = (view.getLeft() + view.getRight()) /
2; int y = (view.getTop() + view.getBottom()) / 2; int startRadius = 0; int endRadius = Math.hypot(x, y); Animator anim = ViewAnimationUtils .createCircularReveal( view, x, y, startRadius, endRadius); view.setVisibility(View.VISIBLE); anim.start(); (x,y) left right top bottom hypot -
(…) transition.addListener(new Transition.TransitionListener() { @Override public void onTransitionEnd(Transition transition) {
fab.setVisibility(View.GONE); createRevealForView(extraContent); } }); private Animator createRevealForView(ViewGroup view) { int x = (viewRoot.getLeft() + viewRoot.getRight()) / 2; int y = viewRoot.getBottom() - fab.getHeight(); float finalRadius = (float) Math.hypot(x, y); Animator anim = ViewAnimationUtils .createCircularReveal(viewRoot, x, y, fab.getWidth(), finalRadius); viewRoot.setVisibility(View.VISIBLE); anim.start(); } Circular Reveal Animation -
- Shared element Transition - Transition Listener - Enter /
Exit Transition - Property Animation System - Transition Manager - 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