├── .gitignore
├── LICENSE.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── lgvalle
│ │ └── material_animations
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── lgvalle
│ │ └── material_animations
│ │ ├── AnimationsActivity1.java
│ │ ├── AnimationsActivity2.java
│ │ ├── BaseDetailActivity.java
│ │ ├── MainActivity.java
│ │ ├── RevealActivity.java
│ │ ├── Sample.java
│ │ ├── SamplesRecyclerAdapter.java
│ │ ├── SharedElementActivity.java
│ │ ├── SharedElementFragment1.java
│ │ ├── SharedElementFragment2.java
│ │ ├── TransitionActivity1.java
│ │ ├── TransitionActivity2.java
│ │ ├── TransitionActivity3.java
│ │ └── TransitionHelper.java
│ └── res
│ ├── drawable
│ ├── circle_24dp.xml
│ └── square.xml
│ ├── layout
│ ├── activity_animations1.xml
│ ├── activity_animations2.xml
│ ├── activity_animations_scene0.xml
│ ├── activity_animations_scene1.xml
│ ├── activity_animations_scene2.xml
│ ├── activity_animations_scene3.xml
│ ├── activity_animations_scene4.xml
│ ├── activity_main.xml
│ ├── activity_reveal.xml
│ ├── activity_sharedelement.xml
│ ├── activity_sharedelement_fragment1.xml
│ ├── activity_sharedelement_fragment2.xml
│ ├── activity_transition1.xml
│ ├── activity_transition2.xml
│ ├── activity_transition3.xml
│ ├── row_sample.xml
│ └── square.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── transition
│ ├── changebounds_with_arcmotion.xml
│ ├── explode.xml
│ ├── slide_and_changebounds.xml
│ ├── slide_and_changebounds_sequential.xml
│ ├── slide_and_changebounds_sequential_with_interpolators.xml
│ └── slide_from_bottom.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle
└── wrapper
│ └── gradle-wrapper.properties
├── gradlew.bat
├── screenshots
├── A_startActivity_B.png
├── B_back_A.png
├── a_b_shared_element.png
├── example1.gif
├── example2.gif
├── example3.gif
├── reveal_blue.gif
├── reveal_green.gif
├── reveal_red.gif
├── reveal_yellow.gif
├── scene-transition.gif
├── scenes_anim.gif
├── shared_element.png
├── shared_element_anim.gif
├── shared_element_no_overlap.gif
├── shared_element_overlap.gif
├── shared_reveal_anim.gif
├── transition-shared-elements.gif
├── transition-shared-elements2.gif
├── transition_A_to_B.png
├── transition_B_to_A.png
├── transition_explode.gif
├── transition_fade.gif
├── transition_fade2.gif
├── transition_slide.gif
└── view_layout_anim.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | gen-external-apklibs/
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # intellij & maven
20 | .classpath
21 | .project
22 | .settings/
23 | .idea/
24 | *.iml
25 | *.iws
26 | .DS_Store
27 | log/
28 | target/
29 | tmp/
30 | out/
31 |
32 | # Gradle
33 | .gradle
34 | build/**
35 | libraries/build/**
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Luis G. Valle
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UNMAINTAINED
2 | No maintainance is intended.
3 | The content is still valid as a reference but it won't contain the latest new stuff
4 |
5 | [](http://android-arsenal.com/details/3/1880)
6 |
7 | [Android Transition Framework][transition-framework] can be used for **three** main things:
8 |
9 | 1. Animate activity layout content when transitioning from one activity to another.
10 | 2. Animate shared elements (Hero views) in transitions between activities.
11 | 3. Animate view changes within same activity.
12 |
13 |
14 | ## 1. Transitions between Activities
15 |
16 | Animate existing activity layout **content**
17 |
18 | ![A Start B][transition_a_to_b]
19 |
20 | When transitioning from `Activity A` to `Activity B` content layout is animated according to defined transition. There are three predefined transitions available on `android.transition.Transition` you can use: **Explode**, **Slide** and **Fade**.
21 | All these transitions track changes to the visibility of target views in activity layout and animate those views to follow transition rules.
22 |
23 | [Explode][explode_link] | [Slide][slide_link] | [Fade][fade_link]
24 | --- | --- | ---
25 | ![transition_explode] | ![transition_slide] | ![transition_fade]
26 |
27 |
28 | You can define these transitions **declarative** using XML or **programmatically**. For the Fade Transition sample, it would look like this:
29 |
30 | ### Declarative
31 | Transitions are defined on XML files in `res/transition`
32 |
33 | > res/transition/activity_fade.xml
34 |
35 | ```xml
36 |
37 |
39 |
40 | ```
41 |
42 | > res/transition/activity_slide.xml
43 |
44 | ```xml
45 |
46 |
48 |
49 | ```
50 |
51 | To use these transitions you need to inflate them using `TransitionInflater`
52 |
53 | > MainActivity.java
54 |
55 | ```java
56 | @Override
57 | protected void onCreate(Bundle savedInstanceState) {
58 | super.onCreate(savedInstanceState);
59 | setContentView(R.layout.activity_transition);
60 | setupWindowAnimations();
61 | }
62 |
63 | private void setupWindowAnimations() {
64 | Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide);
65 | getWindow().setExitTransition(slide);
66 | }
67 |
68 | ```
69 |
70 | > TransitionActivity.java
71 |
72 | ```java
73 | @Override
74 | protected void onCreate(Bundle savedInstanceState) {
75 | super.onCreate(savedInstanceState);
76 | setContentView(R.layout.activity_transition);
77 | setupWindowAnimations();
78 | }
79 |
80 | private void setupWindowAnimations() {
81 | Fade fade = TransitionInflater.from(this).inflateTransition(R.transition.activity_fade);
82 | getWindow().setEnterTransition(fade);
83 | }
84 |
85 | ```
86 |
87 | ### Programmatically
88 |
89 | > MainActivity.java
90 |
91 | ```java
92 | @Override
93 | protected void onCreate(Bundle savedInstanceState) {
94 | super.onCreate(savedInstanceState);
95 | setContentView(R.layout.activity_transition);
96 | setupWindowAnimations();
97 | }
98 |
99 | private void setupWindowAnimations() {
100 | Slide slide = new Slide();
101 | slide.setDuration(1000);
102 | getWindow().setExitTransition(slide);
103 | }
104 |
105 | ```
106 |
107 | > TransitionActivity.java
108 |
109 | ```java
110 | @Override
111 | protected void onCreate(Bundle savedInstanceState) {
112 | super.onCreate(savedInstanceState);
113 | setContentView(R.layout.activity_transition);
114 | setupWindowAnimations();
115 | }
116 |
117 | private void setupWindowAnimations() {
118 | Fade fade = new Fade();
119 | fade.setDuration(1000);
120 | getWindow().setEnterTransition(fade);
121 | }
122 |
123 | ```
124 |
125 | #### Any of those produce this result:
126 |
127 | ![transition_fade]
128 |
129 |
130 | ### What is happening step by step:
131 |
132 | 1. Activity A starts Activity B
133 |
134 | 2. Transition Framework finds A Exit Transition (slide) and apply it to all visible views.
135 | 3. Transition Framework finds B Enter Transition (fade) and apply it to all visible views.
136 | 4. **On Back Pressed** Transition Framework executes Enter and Exit reverse animations respectively (If we had defined output `returnTransition` and `reenterTransition`, these have been executed instead)
137 |
138 | ### ReturnTransition & ReenterTransition
139 |
140 | Return and Reenter Transitions are the reverse animations for Enter and Exit respectively.
141 |
142 | * EnterTransition <--> ReturnTransition
143 | * ExitTransition <--> ReenterTransition
144 |
145 | If Return or Reenter are not defined, Android will execute a reversed version of Enter and Exit Transitions. But if you do define them, you can have different transitions for entering and exiting an activity.
146 |
147 | ![b back a][transition_b_to_a]
148 |
149 | We can modify previous Fade sample and define a `ReturnTransition` for `TransitionActivity`, in this case, a **Slide** transition. This way, when returning from B to A, instead of seeing a Fade out (reversed Enter Transition) we will see a **Slide out** transition
150 |
151 | > TransitionActivity.java
152 |
153 | ```java
154 | @Override
155 | protected void onCreate(Bundle savedInstanceState) {
156 | super.onCreate(savedInstanceState);
157 | setContentView(R.layout.activity_transition);
158 | setupWindowAnimations();
159 | }
160 |
161 | private void setupWindowAnimations() {
162 | Fade fade = new Fade();
163 | fade.setDuration(1000);
164 | getWindow().setEnterTransition(fade);
165 |
166 | Slide slide = new Slide();
167 | slide.setDuration(1000);
168 | getWindow().setReturnTransition(slide);
169 | }
170 |
171 | ```
172 |
173 |
174 | Observe that if no Return Transition is defined then a reversed Enter Transition is executed.
175 | If a Return Transition is defined that one is executed instead.
176 |
177 | Without Return Transition | With Return Transition
178 | --- | ---
179 | Enter: `Fade In` | Enter: `Fade In`
180 | Exit: `Fade Out` | Exit: `Slide out`
181 | ![transition_fade] | ![transition_fade2]
182 |
183 |
184 | ## 2. Shared elements between Activities
185 |
186 | The idea behind this is having two different views in two different layouts and link them somehow with an animation.
187 |
188 | Transition framework will then do _whatever animations it consider necessary_ to show the user a transition from one view to another.
189 |
190 | Keep this always in mind: the view **is not really moving** from one layout to another. They are two independent views.
191 |
192 |
193 | ![A Start B with shared][shared_element]
194 |
195 |
196 | ### a) Enable Window Content Transition
197 |
198 | This is something you need to set up once on your app `styles.xml`.
199 |
200 | > values/styles.xml
201 |
202 | ```xml
203 |
208 | ```
209 |
210 | Here you can also specify default enter, exit and shared element transitions for the whole app if you want
211 |
212 | ```xml
213 |
224 | ```
225 |
226 |
227 |
228 | ### b) Define a common transition name
229 |
230 | To make the trick you need to give both, origin and target views, the same **`android:transitionName`**. They may have different ids or properties, but `android:transitionName` must be the same.
231 |
232 | > layout/activity_a.xml
233 |
234 | ```xml
235 |
240 | ```
241 |
242 | > layout/activity_b.xml
243 |
244 | ```xml
245 |
250 | ```
251 |
252 | ### c) Start an activity with a shared element
253 |
254 | Use the `ActivityOptions.makeSceneTransitionAnimation()` method to define shared element origin view and transition name.
255 |
256 | > MainActivity.java
257 |
258 | ```java
259 |
260 | blueIconImageView.setOnClickListener(new View.OnClickListener() {
261 | @Override
262 | public void onClick(View v) {
263 | Intent i = new Intent(MainActivity.this, SharedElementActivity.class);
264 |
265 | View sharedView = blueIconImageView;
266 | String transitionName = getString(R.string.blue_name);
267 |
268 | ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
269 | startActivity(i, transitionActivityOptions.toBundle());
270 | }
271 | });
272 |
273 | ```
274 |
275 |
276 | Just that code will produce this beautiful transition animation:
277 |
278 | ![a to b with shared element][shared_element_anim]
279 |
280 | As you can see, Transition framework is creating and executing an animation to create the illusion that views are moving and changing shape from one activity to the other
281 |
282 | ## Shared elements between fragments
283 |
284 | Shared element transition works with Fragments in a very similar way as it does with activities.
285 |
286 | Steps **a)** and **b)** are exactly the **same**. Only **c)** changes
287 |
288 | ### a) Enable Window Content Transition
289 |
290 | > values/styles.xml
291 |
292 | ```xml
293 |
298 | ```
299 |
300 | ### b) Define a common transition name
301 |
302 | > layout/fragment_a.xml
303 |
304 | ```xml
305 |
310 | ```
311 |
312 | > layout/fragment_b.xml
313 |
314 | ```xml
315 |
320 | ```
321 |
322 | ### c) Start a fragment with a shared element
323 |
324 | To do this you need to include shared element transition information as part of the **`FragmentTransaction`** process.
325 |
326 | ```java
327 | FragmentB fragmentB = FragmentB.newInstance(sample);
328 |
329 | // Defines enter transition for all fragment views
330 | Slide slideTransition = new Slide(Gravity.RIGHT);
331 | slideTransition.setDuration(1000);
332 | sharedElementFragment2.setEnterTransition(slideTransition);
333 |
334 | // Defines enter transition only for shared element
335 | ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
336 | fragmentB.setSharedElementEnterTransition(changeBoundsTransition);
337 |
338 | getFragmentManager().beginTransaction()
339 | .replace(R.id.content, fragmentB)
340 | .addSharedElement(blueView, getString(R.string.blue_name))
341 | .commit();
342 | ```
343 |
344 | And this is the final result:
345 |
346 | ![shared_element_no_overlap]
347 |
348 | ## Allow Transition Overlap
349 |
350 | You can define if enter and exit transitions can overlap each other.
351 |
352 | From [Android documentation](http://developer.android.com/intl/ko/reference/android/app/Fragment.html#getAllowEnterTransitionOverlap()):
353 | > When **true**, the enter transition will start as soon as possible.
354 | >
355 | > When **false**, the enter transition will wait until the exit transition completes before starting.
356 |
357 | This works for both Fragments and Activities shared element transitions.
358 |
359 | ```java
360 | FragmentB fragmentB = FragmentB.newInstance(sample);
361 |
362 | // Defines enter transition for all fragment views
363 | Slide slideTransition = new Slide(Gravity.RIGHT);
364 | slideTransition.setDuration(1000);
365 | sharedElementFragment2.setEnterTransition(slideTransition);
366 |
367 | // Defines enter transition only for shared element
368 | ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
369 | fragmentB.setSharedElementEnterTransition(changeBoundsTransition);
370 |
371 | // Prevent transitions for overlapping
372 | fragmentB.setAllowEnterTransitionOverlap(overlap);
373 | fragmentB.setAllowReturnTransitionOverlap(overlap);
374 |
375 | getFragmentManager().beginTransaction()
376 | .replace(R.id.content, fragmentB)
377 | .addSharedElement(blueView, getString(R.string.blue_name))
378 | .commit();
379 | ```
380 |
381 | It is very easy to spot the difference in this example:
382 |
383 | Overlap True | Overlap False
384 | --- | ---
385 | Fragment_2 appears on top of Fragment_1 | Fragment_2 waits until Fragment_1 is gone
386 | ![shared_element_overlap] | ![shared_element_no_overlap]
387 |
388 |
389 |
390 | ## 3. Animate view layout elements
391 |
392 | ### Scenes
393 | Transition Framework can also be used to animate element changes within current activity layout.
394 |
395 | Transitions happen between scenes. A scene is just a regular layout which **defines a static state of our UI**. You can transition from one scene to another and Transition Framework will animate views in between.
396 |
397 | ```java
398 | scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene1, this);
399 | scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene2, this);
400 | scene3 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene3, this);
401 | scene4 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene4, this);
402 |
403 | (...)
404 |
405 | @Override
406 | public void onClick(View v) {
407 | switch (v.getId()) {
408 | case R.id.button1:
409 | TransitionManager.go(scene1, new ChangeBounds());
410 | break;
411 | case R.id.button2:
412 | TransitionManager.go(scene2, TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds));
413 | break;
414 | case R.id.button3:
415 | TransitionManager.go(scene3, TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential));
416 | break;
417 | case R.id.button4:
418 | TransitionManager.go(scene4, TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
419 | break;
420 | }
421 | }
422 | ```
423 |
424 | That code would produce transition between four scenes in the same activity. Each transition has a different animation defined.
425 |
426 | Transition Framework will take all visible views in current scene and calculate whatever necessary animations are needed to arrange those views according to next scene.
427 |
428 | ![scenes_anim]
429 |
430 |
431 | ### Layout changes
432 |
433 | Transition Framework can also be used to animate layout property changes in a view. You just need to make whatever changes you want and it will perform necessary animations for you
434 |
435 | #### a) Begin Delayed Transition
436 |
437 | With just this line of code we are telling the framework we are going to perform some UI changes that it will need to animate.
438 |
439 | ```java
440 | TransitionManager.beginDelayedTransition(sceneRoot);
441 | ```
442 | #### b) Change view layout properties
443 |
444 |
445 | ```java
446 | ViewGroup.LayoutParams params = greenIconView.getLayoutParams();
447 | params.width = 200;
448 | greenIconView.setLayoutParams(params);
449 |
450 | ```
451 |
452 | Changing view width attribute to make it smaller will trigger a `layoutMeasure`. At that point the Transition framework will record start and ending values and will create an animation to transition from one to another.
453 |
454 |
455 | ![view layout animation][view_layout_anim]
456 |
457 |
458 | ## 4. (Bonus) Shared elements + Circular Reveal
459 | Circular Reveal is just an animation to show or hide a group of UI elements. It is available since API 21 in `ViewAnimationUtils` class.
460 |
461 |
462 | Circular Reveal animation can be used in combination of Shared Element Transition to create meaningful animations that smoothly teach the user what is happening in the app.
463 |
464 | ![reveal_shared_anim]
465 |
466 | What is happening in this example step by step is:
467 |
468 | * Orange circle is a shared element transitioning from `MainActivity` to `RevealActivity`.
469 | * On `RevealActivity` there is a listener to listen for shared element transition end. When that happens it does two things:
470 | * Execute a Circular Reveal animation for the Toolbar
471 | * Execute a scale up animation on `RevealActivity` views using plain old `ViewPropertyAnimator`
472 |
473 |
474 | > Listen to shared element enter transition end
475 |
476 | ```java
477 | Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
478 | getWindow().setSharedElementEnterTransition(transition);
479 | transition.addListener(new Transition.TransitionListener() {
480 | @Override
481 | public void onTransitionEnd(Transition transition) {
482 | animateRevealShow(toolbar);
483 | animateButtonsIn();
484 | }
485 |
486 | (...)
487 |
488 | });
489 |
490 | ```
491 |
492 | > Reveal Toolbar
493 |
494 | ```java
495 | private void animateRevealShow(View viewRoot) {
496 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
497 | int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
498 | int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());
499 |
500 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
501 | viewRoot.setVisibility(View.VISIBLE);
502 | anim.setDuration(1000);
503 | anim.setInterpolator(new AccelerateInterpolator());
504 | anim.start();
505 | }
506 | ```
507 |
508 | > Scale up activity layout views
509 |
510 | ```java
511 | private void animateButtonsIn() {
512 | for (int i = 0; i < bgViewGroup.getChildCount(); i++) {
513 | View child = bgViewGroup.getChildAt(i);
514 | child.animate()
515 | .setStartDelay(100 + i * DELAY)
516 | .setInterpolator(interpolator)
517 | .alpha(1)
518 | .scaleX(1)
519 | .scaleY(1);
520 | }
521 | }
522 | ```
523 |
524 | ### More circular reveal animations
525 |
526 | There are many different ways you can create a reveal animation. The important thing is to use the animation to help the user understand what is happening in the app.
527 |
528 | #### Circular Reveal from the middle of target view
529 |
530 | ![reveal_green]
531 |
532 | ```java
533 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
534 | int cy = viewRoot.getTop();
535 | int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());
536 |
537 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
538 | viewRoot.setBackgroundColor(color);
539 | anim.start();
540 | ```
541 |
542 | #### Circular Reveal from top of target view + animations
543 |
544 | ![reveal_blue]
545 |
546 | ```java
547 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
548 | int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
549 | int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());
550 |
551 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
552 | viewRoot.setBackgroundColor(color);
553 | anim.addListener(new AnimatorListenerAdapter() {
554 | @Override
555 | public void onAnimationEnd(Animator animation) {
556 | animateButtonsIn();
557 | }
558 | });
559 | anim.start();
560 | ```
561 |
562 |
563 | #### Circular Reveal from touch point
564 |
565 | ![reveal_yellow]
566 |
567 | ```java
568 | @Override
569 | public boolean onTouch(View view, MotionEvent motionEvent) {
570 | if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
571 | if (view.getId() == R.id.square_yellow) {
572 | revealFromCoordinates(motionEvent.getRawX(), motionEvent.getRawY());
573 | }
574 | }
575 | return false;
576 | }
577 | ```
578 |
579 | ```java
580 | private Animator animateRevealColorFromCoordinates(int x, int y) {
581 | float finalRadius = (float) Math.hypot(viewRoot.getWidth(), viewRoot.getHeight());
582 |
583 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, x, y, 0, finalRadius);
584 | viewRoot.setBackgroundColor(color);
585 | anim.start();
586 | }
587 | ```
588 |
589 | #### Animate and Reveal
590 |
591 | ![reveal_red]
592 |
593 | ```java
594 | Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
595 | transition.addListener(new Transition.TransitionListener() {
596 | @Override
597 | public void onTransitionEnd(Transition transition) {
598 | animateRevealColor(bgViewGroup, R.color.red);
599 | }
600 | (...)
601 |
602 | });
603 | TransitionManager.beginDelayedTransition(bgViewGroup, transition);
604 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
605 | layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
606 | btnRed.setLayoutParams(layoutParams);
607 | ```
608 |
609 |
610 | # Sample source code
611 |
612 | **[https://github.com/lgvalle/Material-Animations](https://github.com/lgvalle/Material-Animations/)**
613 |
614 |
615 | # More information
616 |
617 | * Alex Lockwood posts about Transition Framework. A great in deep into this topic: [http://www.androiddesignpatterns.com/2014/12/activity-fragment-transitions-in-android-lollipop-part1.html](http://www.androiddesignpatterns.com/2014/12/activity-fragment-transitions-in-android-lollipop-part1.html)
618 | * Amazing repository with lot of Material Design samples by Saul Molinero: [https://github.com/saulmm/Android-Material-Examples](https://github.com/saulmm/Android-Material-Examples)
619 | * Chet Hasse video explaining Transition framework: [https://www.youtube.com/watch?v=S3H7nJ4QaD8](https://www.youtube.com/watch?v=S3H7nJ4QaD8)
620 |
621 |
622 |
623 | [transition-framework]: https://developer.android.com/training/transitions/overview.html
624 |
625 | [explode_link]: https://developer.android.com/reference/android/transition/Explode.html
626 | [fade_link]: https://developer.android.com/reference/android/transition/Fade.html
627 | [slide_link]: https://developer.android.com/reference/android/transition/Slide.html
628 |
629 | [transition_explode]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_explode.gif
630 | [transition_slide]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_slide.gif
631 | [transition_fade]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_fade.gif
632 | [transition_fade2]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_fade2.gif
633 | [transition_a_to_b]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_A_to_B.png
634 | [transition_b_to_a]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/transition_B_to_A.png
635 |
636 | [shared_element]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/shared_element.png
637 | [shared_element_anim]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/shared_element_anim.gif
638 | [shared_element_no_overlap]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/shared_element_no_overlap.gif
639 | [shared_element_overlap]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/shared_element_overlap.gif
640 |
641 | [scenes_anim]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/scenes_anim.gif
642 | [view_layout_anim]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/view_layout_anim.gif
643 |
644 | [reveal_blue]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/reveal_blue.gif
645 | [reveal_red]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/reveal_red.gif
646 | [reveal_green]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/reveal_green.gif
647 | [reveal_yellow]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/reveal_yellow.gif
648 | [reveal_shared_anim]: https://raw.githubusercontent.com/lgvalle/Material-Animations/master/screenshots/shared_reveal_anim.gif
649 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.lgvalle.material_animations"
9 | minSdkVersion 21
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | dataBinding {
21 | enabled = true
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | compile 'com.android.support:appcompat-v7:23.1.1'
28 | compile 'com.android.support:recyclerview-v7:23.1.1'
29 | }
30 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/lgvalle/Developer/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/lgvalle/material_animations/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
24 |
27 |
30 |
31 |
34 |
35 |
38 |
39 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/AnimationsActivity1.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.content.Intent;
4 | import android.databinding.DataBindingUtil;
5 | import android.os.Bundle;
6 | import android.transition.Fade;
7 | import android.transition.TransitionManager;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ImageView;
12 | import android.widget.LinearLayout;
13 |
14 | import com.lgvalle.material_animations.databinding.ActivityAnimations1Binding;
15 |
16 | public class AnimationsActivity1 extends BaseDetailActivity {
17 | private ImageView square;
18 | private ViewGroup viewRoot;
19 | private boolean sizeChanged;
20 | private int savedWidth;
21 | private boolean positionChanged;
22 | private Sample sample;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | bindData();
28 | setupWindowAnimations();
29 | setupLayout();
30 | setupToolbar();
31 | }
32 |
33 | private void setupWindowAnimations() {
34 | getWindow().setReenterTransition(new Fade());
35 | }
36 |
37 | private void bindData() {
38 | ActivityAnimations1Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_animations1);
39 | sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
40 | binding.setAnimationsSample(sample);
41 | }
42 |
43 | private void setupLayout() {
44 | square = (ImageView) findViewById(R.id.square_green);
45 | viewRoot = (ViewGroup) findViewById(R.id.sample3_root);
46 | findViewById(R.id.sample3_button1).setOnClickListener(new View.OnClickListener() {
47 | @Override
48 | public void onClick(View v) {
49 | changeLayout();
50 | }
51 | });
52 | findViewById(R.id.sample3_button2).setOnClickListener(new View.OnClickListener() {
53 | @Override
54 | public void onClick(View v) {
55 | changePosition();
56 | }
57 | });
58 |
59 | findViewById(R.id.sample3_button3).setOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | Intent i = new Intent(AnimationsActivity1.this, AnimationsActivity2.class);
63 | i.putExtra(EXTRA_SAMPLE, sample);
64 | transitionTo(i);
65 | }
66 | });
67 | }
68 |
69 | private void changeLayout() {
70 | TransitionManager.beginDelayedTransition(viewRoot);
71 |
72 | ViewGroup.LayoutParams params = square.getLayoutParams();
73 | if (sizeChanged) {
74 | params.width = savedWidth;
75 | } else {
76 | savedWidth = params.width;
77 | params.width = 200;
78 | }
79 | sizeChanged = !sizeChanged;
80 | square.setLayoutParams(params);
81 | }
82 |
83 | private void changePosition() {
84 | TransitionManager.beginDelayedTransition(viewRoot);
85 |
86 | LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) square.getLayoutParams();
87 | if (positionChanged) {
88 | lp.gravity = Gravity.CENTER;
89 | } else {
90 | lp.gravity = Gravity.LEFT;
91 | }
92 | positionChanged = !positionChanged;
93 | square.setLayoutParams(lp);
94 | }
95 |
96 |
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/AnimationsActivity2.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.os.Bundle;
5 | import android.transition.ChangeBounds;
6 | import android.transition.Scene;
7 | import android.transition.Transition;
8 | import android.transition.TransitionInflater;
9 | import android.transition.TransitionManager;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.lgvalle.material_animations.databinding.ActivityAnimations2Binding;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | public class AnimationsActivity2 extends BaseDetailActivity {
19 |
20 | private static final int DELAY = 100;
21 | private Scene scene0;
22 | private Scene scene1;
23 | private Scene scene2;
24 | private Scene scene3;
25 | private Scene scene4;
26 | private final List viewsToAnimate = new ArrayList<>();
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | bindData();
32 | setupLayout();
33 | setupToolbar();
34 | setupWindowAnimations();
35 | }
36 |
37 | private void bindData() {
38 | ActivityAnimations2Binding binding = DataBindingUtil.setContentView(
39 | this, R.layout.activity_animations2);
40 | Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
41 | binding.setAnimationsSample(sample);
42 | }
43 |
44 | private void setupWindowAnimations() {
45 | getWindow().setEnterTransition(TransitionInflater.from(this).inflateTransition(
46 | R.transition.slide_from_bottom));
47 | getWindow().getEnterTransition().addListener(new Transition.TransitionListener() {
48 | @Override
49 | public void onTransitionStart(Transition transition) {
50 | }
51 |
52 | @Override
53 | public void onTransitionCancel(Transition transition) {
54 | }
55 |
56 | @Override
57 | public void onTransitionPause(Transition transition) {
58 | }
59 |
60 | @Override
61 | public void onTransitionResume(Transition transition) {
62 | }
63 |
64 | @Override
65 | public void onTransitionEnd(Transition transition) {
66 | getWindow().getEnterTransition().removeListener(this);
67 | TransitionManager.go(scene0);
68 | }
69 | });
70 | }
71 |
72 | private void setupLayout() {
73 | final ViewGroup activityRoot = (ViewGroup) findViewById(R.id.buttons_group);
74 | ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
75 |
76 | scene0 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene0, this);
77 | scene0.setEnterAction(new Runnable() {
78 | @Override
79 | public void run() {
80 | for (int i = 0; i < viewsToAnimate.size(); i++) {
81 | View child = viewsToAnimate.get(i);
82 | child.animate()
83 | .setStartDelay(i * DELAY)
84 | .scaleX(1)
85 | .scaleY(1);
86 |
87 | }
88 | }
89 | });
90 | scene0.setExitAction(new Runnable() {
91 | @Override
92 | public void run() {
93 | TransitionManager.beginDelayedTransition(activityRoot);
94 | View title = scene0.getSceneRoot().findViewById(R.id.scene0_title);
95 | title.setScaleX(0);
96 | title.setScaleY(0);
97 | }
98 | });
99 |
100 |
101 | scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene1, this);
102 | scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene2, this);
103 | scene3 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene3, this);
104 | scene4 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene4, this);
105 |
106 | View button1 = findViewById(R.id.sample3_button1);
107 | button1.setOnClickListener(new View.OnClickListener() {
108 | @Override
109 | public void onClick(View v) {
110 | TransitionManager.go(scene1, new ChangeBounds());
111 | }
112 | });
113 | View button2 = findViewById(R.id.sample3_button2);
114 | button2.setOnClickListener(new View.OnClickListener() {
115 | @Override
116 | public void onClick(View v) {
117 | TransitionManager.go(scene2, TransitionInflater.from(AnimationsActivity2.this).
118 | inflateTransition(R.transition.slide_and_changebounds));
119 | }
120 | });
121 |
122 | View button3 = findViewById(R.id.sample3_button3);
123 | button3.setOnClickListener(new View.OnClickListener() {
124 | @Override
125 | public void onClick(View v) {
126 | TransitionManager.go(scene3, TransitionInflater.from(AnimationsActivity2.this).
127 | inflateTransition(R.transition.slide_and_changebounds_sequential));
128 | }
129 | });
130 |
131 | View button4 = findViewById(R.id.sample3_button4);
132 | button4.setOnClickListener(new View.OnClickListener() {
133 | @Override
134 | public void onClick(View v) {
135 | TransitionManager.go(scene4, TransitionInflater.from(AnimationsActivity2.this).
136 | inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
137 | }
138 | });
139 |
140 | viewsToAnimate.add(button1);
141 | viewsToAnimate.add(button2);
142 | viewsToAnimate.add(button3);
143 | viewsToAnimate.add(button4);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/BaseDetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.content.Intent;
4 | import android.support.v4.app.ActivityOptionsCompat;
5 | import android.support.v4.util.Pair;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.View;
9 |
10 | /**
11 | * Created by lgvalle on 12/09/15.
12 | */
13 | public class BaseDetailActivity extends AppCompatActivity {
14 | static final String EXTRA_SAMPLE = "sample";
15 | static final String EXTRA_TYPE = "type";
16 | static final int TYPE_PROGRAMMATICALLY = 0;
17 | static final int TYPE_XML = 1;
18 |
19 | void setupToolbar() {
20 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
21 | setSupportActionBar(toolbar);
22 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
23 | getSupportActionBar().setDisplayShowTitleEnabled(false);
24 | }
25 |
26 | @Override
27 | public boolean onSupportNavigateUp() {
28 | onBackPressed();
29 | return true;
30 | }
31 |
32 | @SuppressWarnings("unchecked") void transitionTo(Intent i) {
33 | final Pair[] pairs = TransitionHelper.createSafeTransitionParticipants(this, true);
34 | ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pairs);
35 | startActivity(i, transitionActivityOptions.toBundle());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.content.ContextCompat;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.support.v7.widget.Toolbar;
9 | import android.transition.Slide;
10 | import android.view.Gravity;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class MainActivity extends AppCompatActivity {
16 | private List samples;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_main);
22 | setupWindowAnimations();
23 | setupSamples();
24 | setupToolbar();
25 | setupLayout();
26 | }
27 |
28 | private void setupWindowAnimations() {
29 | // Re-enter transition is executed when returning to this activity
30 | Slide slideTransition = new Slide();
31 | slideTransition.setSlideEdge(Gravity.LEFT);
32 | slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
33 | getWindow().setReenterTransition(slideTransition);
34 | getWindow().setExitTransition(slideTransition);
35 | }
36 |
37 | private void setupSamples() {
38 | samples = Arrays.asList(
39 | new Sample(ContextCompat.getColor(this, R.color.sample_red), "Transitions"),
40 | new Sample(ContextCompat.getColor(this, R.color.sample_blue), "Shared Elements"),
41 | new Sample(ContextCompat.getColor(this, R.color.sample_green), "View animations"),
42 | new Sample(ContextCompat.getColor(this, R.color.sample_yellow), "Circular Reveal Animation")
43 | );
44 | }
45 |
46 | private void setupToolbar() {
47 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
48 | setSupportActionBar(toolbar);
49 | getSupportActionBar().setDisplayShowTitleEnabled(false);
50 | }
51 |
52 | private void setupLayout() {
53 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.sample_list);
54 | recyclerView.setHasFixedSize(true);
55 | recyclerView.setLayoutManager(new LinearLayoutManager(this));
56 | SamplesRecyclerAdapter samplesRecyclerAdapter = new SamplesRecyclerAdapter(this, samples);
57 | recyclerView.setAdapter(samplesRecyclerAdapter);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/RevealActivity.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.databinding.DataBindingUtil;
6 | import android.os.Bundle;
7 | import android.support.annotation.ColorRes;
8 | import android.support.v4.content.ContextCompat;
9 | import android.support.v7.widget.Toolbar;
10 | import android.transition.Fade;
11 | import android.transition.Transition;
12 | import android.transition.TransitionInflater;
13 | import android.transition.TransitionManager;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.ViewAnimationUtils;
17 | import android.view.ViewGroup;
18 | import android.view.animation.AccelerateDecelerateInterpolator;
19 | import android.view.animation.AccelerateInterpolator;
20 | import android.view.animation.AnimationUtils;
21 | import android.view.animation.Interpolator;
22 | import android.widget.RelativeLayout;
23 | import android.widget.TextView;
24 |
25 | import com.lgvalle.material_animations.databinding.ActivityRevealBinding;
26 |
27 |
28 | public class RevealActivity extends BaseDetailActivity implements View.OnTouchListener {
29 | private static final int DELAY = 100;
30 | private RelativeLayout bgViewGroup;
31 | private Toolbar toolbar;
32 | private Interpolator interpolator;
33 | private TextView body;
34 | private View btnRed;
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | bindData();
40 | setupWindowAnimations();
41 | setupLayout();
42 | setupToolbar();
43 | }
44 |
45 | private void bindData() {
46 | ActivityRevealBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_reveal);
47 | Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
48 | binding.setReveal1Sample(sample);
49 | }
50 |
51 | private void setupWindowAnimations() {
52 | interpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.linear_out_slow_in);
53 | setupEnterAnimations();
54 | setupExitAnimations();
55 | }
56 |
57 | private void setupEnterAnimations() {
58 | Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
59 | getWindow().setSharedElementEnterTransition(transition);
60 | transition.addListener(new Transition.TransitionListener() {
61 | @Override
62 | public void onTransitionStart(Transition transition) {
63 | }
64 |
65 | @Override
66 | public void onTransitionEnd(Transition transition) {
67 | // Removing listener here is very important because shared element transition is executed again backwards on exit. If we don't remove the listener this code will be triggered again.
68 | transition.removeListener(this);
69 | hideTarget();
70 | animateRevealShow(toolbar);
71 | animateButtonsIn();
72 | }
73 |
74 | @Override
75 | public void onTransitionCancel(Transition transition) {
76 | }
77 |
78 | @Override
79 | public void onTransitionPause(Transition transition) {
80 | }
81 |
82 | @Override
83 | public void onTransitionResume(Transition transition) {
84 | }
85 | });
86 | }
87 |
88 | private void setupExitAnimations() {
89 | Fade returnTransition = new Fade();
90 | getWindow().setReturnTransition(returnTransition);
91 | returnTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
92 | returnTransition.setStartDelay(getResources().getInteger(R.integer.anim_duration_medium));
93 | returnTransition.addListener(new Transition.TransitionListener() {
94 | @Override
95 | public void onTransitionStart(Transition transition) {
96 | transition.removeListener(this);
97 | animateButtonsOut();
98 | animateRevealHide(bgViewGroup);
99 | }
100 |
101 | @Override
102 | public void onTransitionEnd(Transition transition) {
103 | }
104 |
105 | @Override
106 | public void onTransitionCancel(Transition transition) {
107 | }
108 |
109 | @Override
110 | public void onTransitionPause(Transition transition) {
111 | }
112 |
113 | @Override
114 | public void onTransitionResume(Transition transition) {
115 | }
116 | });
117 | }
118 |
119 | private void setupLayout() {
120 | bgViewGroup = (RelativeLayout) findViewById(R.id.reveal_root);
121 | toolbar = (Toolbar) findViewById(R.id.toolbar);
122 | body = ((TextView) findViewById(R.id.sample_body));
123 | View btnGreen = findViewById(R.id.square_green);
124 | btnGreen.setOnClickListener(new View.OnClickListener() {
125 | @Override
126 | public void onClick(View v) {
127 | revealGreen();
128 | }
129 | });
130 | btnRed = findViewById(R.id.square_red);
131 | btnRed.setOnClickListener(new View.OnClickListener() {
132 | @Override
133 | public void onClick(View v) {
134 | revealRed();
135 | }
136 | });
137 | View btnBlue = findViewById(R.id.square_blue);
138 | btnBlue.setOnClickListener(new View.OnClickListener() {
139 | @Override
140 | public void onClick(View v) {
141 | revealBlue();
142 | }
143 | });
144 | findViewById(R.id.square_yellow).setOnTouchListener(this);
145 | }
146 |
147 | private void revealBlue() {
148 | animateButtonsOut();
149 | Animator anim = animateRevealColorFromCoordinates(bgViewGroup, R.color.sample_blue, bgViewGroup.getWidth() / 2, 0);
150 | anim.addListener(new AnimatorListenerAdapter() {
151 | @Override
152 | public void onAnimationEnd(Animator animation) {
153 | animateButtonsIn();
154 | }
155 | });
156 | body.setText(R.string.reveal_body4);
157 | body.setTextColor(ContextCompat.getColor(this, R.color.theme_blue_background));
158 | }
159 |
160 | private void revealRed() {
161 | final ViewGroup.LayoutParams originalParams = btnRed.getLayoutParams();
162 | Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
163 | transition.addListener(new Transition.TransitionListener() {
164 | @Override
165 | public void onTransitionStart(Transition transition) {
166 | }
167 |
168 | @Override
169 | public void onTransitionEnd(Transition transition) {
170 | animateRevealColor(bgViewGroup, R.color.sample_red);
171 | body.setText(R.string.reveal_body3);
172 | body.setTextColor(ContextCompat.getColor(RevealActivity.this, R.color.theme_red_background));
173 | btnRed.setLayoutParams(originalParams);
174 | }
175 |
176 | @Override
177 | public void onTransitionCancel(Transition transition) {
178 | }
179 |
180 | @Override
181 | public void onTransitionPause(Transition transition) {
182 |
183 | }
184 |
185 | @Override
186 | public void onTransitionResume(Transition transition) {
187 |
188 | }
189 | });
190 | TransitionManager.beginDelayedTransition(bgViewGroup, transition);
191 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
192 | layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
193 | btnRed.setLayoutParams(layoutParams);
194 | }
195 |
196 | private void revealYellow(float x, float y) {
197 | animateRevealColorFromCoordinates(bgViewGroup, R.color.sample_yellow, (int) x, (int) y);
198 | body.setText(R.string.reveal_body1);
199 | body.setTextColor(ContextCompat.getColor(this, R.color.theme_yellow_background));
200 | }
201 |
202 | private void revealGreen() {
203 | animateRevealColor(bgViewGroup, R.color.sample_green);
204 | body.setText(R.string.reveal_body2);
205 | body.setTextColor(ContextCompat.getColor(this, R.color.theme_green_background));
206 | }
207 |
208 | private void hideTarget() {
209 | findViewById(R.id.shared_target).setVisibility(View.GONE);
210 | }
211 |
212 | private void animateButtonsIn() {
213 | for (int i = 0; i < bgViewGroup.getChildCount(); i++) {
214 | View child = bgViewGroup.getChildAt(i);
215 | child.animate()
216 | .setStartDelay(100 + i * DELAY)
217 | .setInterpolator(interpolator)
218 | .alpha(1)
219 | .scaleX(1)
220 | .scaleY(1);
221 | }
222 | }
223 |
224 | private void animateButtonsOut() {
225 | for (int i = 0; i < bgViewGroup.getChildCount(); i++) {
226 | View child = bgViewGroup.getChildAt(i);
227 | child.animate()
228 | .setStartDelay(i)
229 | .setInterpolator(interpolator)
230 | .alpha(0)
231 | .scaleX(0f)
232 | .scaleY(0f);
233 | }
234 | }
235 |
236 | @Override
237 | public boolean onTouch(View view, MotionEvent motionEvent) {
238 | if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
239 | if (view.getId() == R.id.square_yellow) {
240 | revealYellow(motionEvent.getRawX(), motionEvent.getRawY());
241 | }
242 | }
243 | return false;
244 | }
245 |
246 | private void animateRevealShow(View viewRoot) {
247 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
248 | int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
249 | int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());
250 |
251 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
252 | viewRoot.setVisibility(View.VISIBLE);
253 | anim.setDuration(getResources().getInteger(R.integer.anim_duration_long));
254 | anim.setInterpolator(new AccelerateInterpolator());
255 | anim.start();
256 | }
257 |
258 | private void animateRevealColor(ViewGroup viewRoot, @ColorRes int color) {
259 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
260 | int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
261 | animateRevealColorFromCoordinates(viewRoot, color, cx, cy);
262 | }
263 |
264 | private Animator animateRevealColorFromCoordinates(ViewGroup viewRoot, @ColorRes int color, int x, int y) {
265 | float finalRadius = (float) Math.hypot(viewRoot.getWidth(), viewRoot.getHeight());
266 |
267 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, x, y, 0, finalRadius);
268 | viewRoot.setBackgroundColor(ContextCompat.getColor(this, color));
269 | anim.setDuration(getResources().getInteger(R.integer.anim_duration_long));
270 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
271 | anim.start();
272 | return anim;
273 | }
274 |
275 | private void animateRevealHide(final View viewRoot) {
276 | int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
277 | int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
278 | int initialRadius = viewRoot.getWidth();
279 |
280 | Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, initialRadius, 0);
281 | anim.addListener(new AnimatorListenerAdapter() {
282 | @Override
283 | public void onAnimationEnd(Animator animation) {
284 | super.onAnimationEnd(animation);
285 | viewRoot.setVisibility(View.INVISIBLE);
286 | }
287 | });
288 | anim.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
289 | anim.start();
290 | }
291 | }
292 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/Sample.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.databinding.BindingAdapter;
4 | import android.support.annotation.ColorRes;
5 | import android.support.v4.graphics.drawable.DrawableCompat;
6 | import android.widget.ImageView;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * Created by lgvalle on 04/09/15.
12 | */
13 | public class Sample implements Serializable {
14 |
15 | final int color;
16 | private final String name;
17 |
18 | public Sample(@ColorRes int color, String name) {
19 | this.color = color;
20 | this.name = name;
21 | }
22 |
23 | @BindingAdapter("bind:colorTint")
24 | public static void setColorTint(ImageView view, @ColorRes int color) {
25 | DrawableCompat.setTint(view.getDrawable(), color);
26 | //view.setColorFilter(color, PorterDuff.Mode.SRC_IN);
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public int getColor() {
34 | return color;
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/SamplesRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.databinding.DataBindingUtil;
6 | import android.support.v4.app.ActivityOptionsCompat;
7 | import android.support.v4.util.Pair;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.lgvalle.material_animations.databinding.RowSampleBinding;
14 |
15 | import java.util.List;
16 |
17 | public class SamplesRecyclerAdapter extends RecyclerView.Adapter {
18 | private final Activity activity;
19 | private final List samples;
20 |
21 | public SamplesRecyclerAdapter(Activity activity, List samples) {
22 | this.activity = activity;
23 | this.samples = samples;
24 | }
25 |
26 | @Override
27 | public SamplesViewHolder onCreateViewHolder(ViewGroup parent, int position) {
28 | RowSampleBinding binding = RowSampleBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
29 | return new SamplesViewHolder(binding.getRoot());
30 | }
31 |
32 | @Override
33 | public void onBindViewHolder(final SamplesViewHolder viewHolder, final int position) {
34 | final Sample sample = samples.get(viewHolder.getAdapterPosition());
35 | viewHolder.binding.setSample(sample);
36 | viewHolder.binding.sampleLayout.setOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | switch (viewHolder.getAdapterPosition()) {
40 | case 0:
41 | transitionToActivity(TransitionActivity1.class, sample);
42 | break;
43 | case 1:
44 | transitionToActivity(SharedElementActivity.class, viewHolder, sample);
45 | break;
46 | case 2:
47 | transitionToActivity(AnimationsActivity1.class, sample);
48 | break;
49 | case 3:
50 | transitionToActivity(RevealActivity.class, viewHolder, sample, R.string.transition_reveal1);
51 | break;
52 | }
53 | }
54 | });
55 | }
56 |
57 | private void transitionToActivity(Class target, Sample sample) {
58 | final Pair[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, true);
59 | startActivity(target, pairs, sample);
60 | }
61 |
62 |
63 | private void transitionToActivity(Class target, SamplesViewHolder viewHolder, Sample sample, int transitionName) {
64 | final Pair[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, false,
65 | new Pair<>(viewHolder.binding.sampleIcon, activity.getString(transitionName)));
66 | startActivity(target, pairs, sample);
67 | }
68 |
69 | private void transitionToActivity(Class target, SamplesViewHolder viewHolder, Sample sample) {
70 | final Pair[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, false,
71 | new Pair<>(viewHolder.binding.sampleIcon, activity.getString(R.string.square_blue_name)),
72 | new Pair<>(viewHolder.binding.sampleName, activity.getString(R.string.sample_blue_title)));
73 | startActivity(target, pairs, sample);
74 | }
75 |
76 | private void startActivity(Class target, Pair[] pairs, Sample sample) {
77 | Intent i = new Intent(activity, target);
78 | ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs);
79 | i.putExtra("sample", sample);
80 | activity.startActivity(i, transitionActivityOptions.toBundle());
81 | }
82 |
83 | @Override
84 | public int getItemCount() {
85 | return samples.size();
86 | }
87 |
88 |
89 | public class SamplesViewHolder extends RecyclerView.ViewHolder {
90 | final RowSampleBinding binding;
91 |
92 | public SamplesViewHolder(View rootView) {
93 | super(rootView);
94 | binding = DataBindingUtil.bind(rootView);
95 |
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/SharedElementActivity.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.os.Bundle;
5 | import android.transition.ChangeBounds;
6 | import android.transition.Slide;
7 | import android.view.Gravity;
8 |
9 | import com.lgvalle.material_animations.databinding.ActivitySharedelementBinding;
10 |
11 | public class SharedElementActivity extends BaseDetailActivity {
12 |
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
18 | bindData(sample);
19 | setupWindowAnimations();
20 | setupLayout(sample);
21 | setupToolbar();
22 | }
23 |
24 | private void bindData(Sample sample) {
25 | ActivitySharedelementBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sharedelement);
26 | binding.setSharedSample(sample);
27 | }
28 |
29 | private void setupWindowAnimations() {
30 | // We are not interested in defining a new Enter Transition. Instead we change default transition duration
31 | getWindow().getEnterTransition().setDuration(getResources().getInteger(R.integer.anim_duration_long));
32 | }
33 |
34 | private void setupLayout(Sample sample) {
35 | // Transition for fragment1
36 | Slide slideTransition = new Slide(Gravity.LEFT);
37 | slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
38 | // Create fragment and define some of it transitions
39 | SharedElementFragment1 sharedElementFragment1 = SharedElementFragment1.newInstance(sample);
40 | sharedElementFragment1.setReenterTransition(slideTransition);
41 | sharedElementFragment1.setExitTransition(slideTransition);
42 | sharedElementFragment1.setSharedElementEnterTransition(new ChangeBounds());
43 |
44 | getSupportFragmentManager().beginTransaction()
45 | .replace(R.id.sample2_content, sharedElementFragment1)
46 | .commit();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/SharedElementFragment1.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.graphics.drawable.DrawableCompat;
6 | import android.transition.ChangeBounds;
7 | import android.transition.Slide;
8 | import android.view.Gravity;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.ImageView;
13 |
14 | /**
15 | * Created by lgvalle on 05/09/15.
16 | */
17 | public class SharedElementFragment1 extends Fragment {
18 |
19 | private static final String EXTRA_SAMPLE = "sample";
20 |
21 | public static SharedElementFragment1 newInstance(Sample sample) {
22 |
23 | Bundle args = new Bundle();
24 |
25 | args.putSerializable(EXTRA_SAMPLE, sample);
26 | SharedElementFragment1 fragment = new SharedElementFragment1();
27 | fragment.setArguments(args);
28 | return fragment;
29 | }
30 |
31 | @Override
32 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
33 | View view = inflater.inflate(R.layout.activity_sharedelement_fragment1, container, false);
34 | final Sample sample = (Sample) getArguments().getSerializable(EXTRA_SAMPLE);
35 |
36 | final ImageView squareBlue = (ImageView) view.findViewById(R.id.square_blue);
37 | DrawableCompat.setTint(squareBlue.getDrawable(), sample.color);
38 |
39 | view.findViewById(R.id.sample2_button1).setOnClickListener(new View.OnClickListener() {
40 | @Override
41 | public void onClick(View v) {
42 | addNextFragment(sample, squareBlue, false);
43 | }
44 | });
45 |
46 | view.findViewById(R.id.sample2_button2).setOnClickListener(new View.OnClickListener() {
47 | @Override
48 | public void onClick(View v) {
49 | addNextFragment(sample, squareBlue, true);
50 | }
51 | });
52 |
53 | return view;
54 | }
55 |
56 | private void addNextFragment(Sample sample, ImageView squareBlue, boolean overlap) {
57 | SharedElementFragment2 sharedElementFragment2 = SharedElementFragment2.newInstance(sample);
58 |
59 | Slide slideTransition = new Slide(Gravity.RIGHT);
60 | slideTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
61 |
62 | ChangeBounds changeBoundsTransition = new ChangeBounds();
63 | changeBoundsTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
64 |
65 | sharedElementFragment2.setEnterTransition(slideTransition);
66 | sharedElementFragment2.setAllowEnterTransitionOverlap(overlap);
67 | sharedElementFragment2.setAllowReturnTransitionOverlap(overlap);
68 | sharedElementFragment2.setSharedElementEnterTransition(changeBoundsTransition);
69 |
70 | getFragmentManager().beginTransaction()
71 | .replace(R.id.sample2_content, sharedElementFragment2)
72 | .addToBackStack(null)
73 | .addSharedElement(squareBlue, getString(R.string.square_blue_name))
74 | .commit();
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/SharedElementFragment2.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.graphics.drawable.DrawableCompat;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ImageView;
10 |
11 | public class SharedElementFragment2 extends Fragment {
12 | private static final String EXTRA_SAMPLE = "sample";
13 |
14 | public static SharedElementFragment2 newInstance(Sample sample) {
15 | Bundle args = new Bundle();
16 | args.putSerializable(EXTRA_SAMPLE, sample);
17 | SharedElementFragment2 fragment = new SharedElementFragment2();
18 | fragment.setArguments(args);
19 | return fragment;
20 | }
21 |
22 | @Override
23 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
24 | View view = inflater.inflate(R.layout.activity_sharedelement_fragment2, container, false);
25 | Sample sample = (Sample) getArguments().getSerializable(EXTRA_SAMPLE);
26 |
27 | ImageView squareBlue = (ImageView) view.findViewById(R.id.square_blue);
28 | DrawableCompat.setTint(squareBlue.getDrawable(), sample.color);
29 |
30 | return view;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/TransitionActivity1.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.content.Intent;
4 | import android.databinding.DataBindingUtil;
5 | import android.os.Bundle;
6 | import android.transition.Fade;
7 | import android.transition.Slide;
8 | import android.transition.Visibility;
9 | import android.view.View;
10 |
11 | import com.lgvalle.material_animations.databinding.ActivityTransition1Binding;
12 |
13 | public class TransitionActivity1 extends BaseDetailActivity {
14 | private Sample sample;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | bindData();
20 | setupWindowAnimations();
21 | setupLayout();
22 | setupToolbar();
23 | }
24 |
25 | private void bindData() {
26 | ActivityTransition1Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition1);
27 | sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
28 | binding.setTransition1Sample(sample);
29 | }
30 |
31 | private void setupWindowAnimations() {
32 | Visibility enterTransition = buildEnterTransition();
33 | getWindow().setEnterTransition(enterTransition);
34 | }
35 |
36 |
37 | private void setupLayout() {
38 | findViewById(R.id.sample1_button1).setOnClickListener(new View.OnClickListener() {
39 | @Override
40 | public void onClick(View v) {
41 | Intent i = new Intent(TransitionActivity1.this, TransitionActivity2.class);
42 | i.putExtra(EXTRA_SAMPLE, sample);
43 | i.putExtra(EXTRA_TYPE, TYPE_PROGRAMMATICALLY);
44 | transitionTo(i);
45 | }
46 | });
47 |
48 | findViewById(R.id.sample1_button2).setOnClickListener(new View.OnClickListener() {
49 | @Override
50 | public void onClick(View v) {
51 | Intent i = new Intent(TransitionActivity1.this, TransitionActivity2.class);
52 | i.putExtra(EXTRA_SAMPLE, sample);
53 | i.putExtra(EXTRA_TYPE, TYPE_XML);
54 | transitionTo(i);
55 | }
56 | });
57 |
58 | findViewById(R.id.sample1_button3).setOnClickListener(new View.OnClickListener() {
59 | @Override
60 | public void onClick(View v) {
61 | Intent i = new Intent(TransitionActivity1.this, TransitionActivity3.class);
62 | i.putExtra(EXTRA_SAMPLE, sample);
63 | i.putExtra(EXTRA_TYPE, TYPE_PROGRAMMATICALLY);
64 | transitionTo(i);
65 | }
66 | });
67 |
68 | findViewById(R.id.sample1_button4).setOnClickListener(new View.OnClickListener() {
69 | @Override
70 | public void onClick(View v) {
71 | Intent i = new Intent(TransitionActivity1.this, TransitionActivity3.class);
72 | i.putExtra(EXTRA_SAMPLE, sample);
73 | i.putExtra(EXTRA_TYPE, TYPE_XML);
74 | transitionTo(i);
75 | }
76 | });
77 |
78 | findViewById(R.id.sample1_button5).setOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) {
81 | Visibility returnTransition = buildReturnTransition();
82 | getWindow().setReturnTransition(returnTransition);
83 |
84 | finishAfterTransition();
85 | }
86 | });
87 | findViewById(R.id.sample1_button6).setOnClickListener(new View.OnClickListener() {
88 | @Override
89 | public void onClick(View v) {
90 | /**
91 | * If no return transition is defined Android will use reversed enter transition
92 | * In this case, return transition will be a reversed Slide (defined in buildEnterTransition)
93 | */
94 | finishAfterTransition();
95 | }
96 | });
97 | }
98 |
99 | private Visibility buildEnterTransition() {
100 | Fade enterTransition = new Fade();
101 | enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
102 | // This view will not be affected by enter transition animation
103 | enterTransition.excludeTarget(R.id.square_red, true);
104 | return enterTransition;
105 | }
106 |
107 | private Visibility buildReturnTransition() {
108 | Visibility enterTransition = new Slide();
109 | enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
110 | return enterTransition;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/TransitionActivity2.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.os.Bundle;
5 | import android.transition.Explode;
6 | import android.transition.Transition;
7 | import android.transition.TransitionInflater;
8 | import android.view.View;
9 |
10 | import com.lgvalle.material_animations.databinding.ActivityTransition2Binding;
11 |
12 | public class TransitionActivity2 extends BaseDetailActivity {
13 |
14 | private int type;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | bindData();
20 | setupWindowAnimations();
21 | setupLayout();
22 | setupToolbar();
23 | }
24 |
25 | private void bindData() {
26 | ActivityTransition2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition2);
27 | Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
28 | type = getIntent().getExtras().getInt(EXTRA_TYPE);
29 | binding.setTransition2Sample(sample);
30 | }
31 |
32 | private void setupWindowAnimations() {
33 | Transition transition;
34 |
35 | if (type == TYPE_PROGRAMMATICALLY) {
36 | transition = buildEnterTransition();
37 | } else {
38 | transition = TransitionInflater.from(this).inflateTransition(R.transition.explode);
39 | }
40 | getWindow().setEnterTransition(transition);
41 | }
42 |
43 | private void setupLayout() {
44 | findViewById(R.id.exit_button).setOnClickListener(new View.OnClickListener() {
45 | @Override
46 | public void onClick(View v) {
47 | finishAfterTransition();
48 | }
49 | });
50 | }
51 |
52 | private Transition buildEnterTransition() {
53 | Explode enterTransition = new Explode();
54 | enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
55 | return enterTransition;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/TransitionActivity3.java:
--------------------------------------------------------------------------------
1 | package com.lgvalle.material_animations;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.os.Bundle;
5 | import android.transition.Slide;
6 | import android.transition.Transition;
7 | import android.transition.TransitionInflater;
8 | import android.transition.Visibility;
9 | import android.view.Gravity;
10 | import android.view.View;
11 |
12 | import com.lgvalle.material_animations.databinding.ActivityTransition3Binding;
13 |
14 | public class TransitionActivity3 extends BaseDetailActivity {
15 |
16 | private int type;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | bindData();
22 | setupWindowAnimations();
23 | setupLayout();
24 | setupToolbar();
25 | }
26 |
27 | private void bindData() {
28 | ActivityTransition3Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_transition3);
29 | Sample sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
30 | type = getIntent().getExtras().getInt(EXTRA_TYPE);
31 | binding.setTransition3Sample(sample);
32 | }
33 |
34 | private void setupWindowAnimations() {
35 | Transition transition;
36 |
37 | if (type == TYPE_PROGRAMMATICALLY) {
38 | transition = buildEnterTransition();
39 | } else {
40 | transition = TransitionInflater.from(this).inflateTransition(R.transition.slide_from_bottom);
41 | }
42 | getWindow().setEnterTransition(transition);
43 | }
44 |
45 | private void setupLayout() {
46 | findViewById(R.id.exit_button).setOnClickListener(new View.OnClickListener() {
47 | @Override
48 | public void onClick(View v) {
49 | finishAfterTransition();
50 | }
51 | });
52 | }
53 |
54 | private Visibility buildEnterTransition() {
55 | Slide enterTransition = new Slide();
56 | enterTransition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
57 | enterTransition.setSlideEdge(Gravity.RIGHT);
58 | return enterTransition;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lgvalle/material_animations/TransitionHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Google Inc.
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.lgvalle.material_animations;
18 |
19 | import android.app.Activity;
20 | import android.support.annotation.NonNull;
21 | import android.support.annotation.Nullable;
22 | import android.support.v4.util.Pair;
23 | import android.view.View;
24 |
25 | import java.util.ArrayList;
26 | import java.util.Arrays;
27 | import java.util.List;
28 |
29 | /**
30 | * Helper class for creating content transitions used with {@link android.app.ActivityOptions}.
31 | */
32 | class TransitionHelper {
33 |
34 | /**
35 | * Create the transition participants required during a activity transition while
36 | * avoiding glitches with the system UI.
37 | *
38 | * @param activity The activity used as start for the transition.
39 | * @param includeStatusBar If false, the status bar will not be added as the transition
40 | * participant.
41 | * @return All transition participants.
42 | */
43 | public static Pair[] createSafeTransitionParticipants(@NonNull Activity activity,
44 | boolean includeStatusBar, @Nullable Pair... otherParticipants) {
45 | // Avoid system UI glitches as described here:
46 | // https://plus.google.com/+AlexLockwood/posts/RPtwZ5nNebb
47 | View decor = activity.getWindow().getDecorView();
48 | View statusBar = null;
49 | if (includeStatusBar) {
50 | statusBar = decor.findViewById(android.R.id.statusBarBackground);
51 | }
52 | View navBar = decor.findViewById(android.R.id.navigationBarBackground);
53 |
54 | // Create pair of transition participants.
55 | List participants = new ArrayList<>(3);
56 | addNonNullViewToTransitionParticipants(statusBar, participants);
57 | addNonNullViewToTransitionParticipants(navBar, participants);
58 | // only add transition participants if there's at least one none-null element
59 | if (otherParticipants != null && !(otherParticipants.length == 1
60 | && otherParticipants[0] == null)) {
61 | participants.addAll(Arrays.asList(otherParticipants));
62 | }
63 | return participants.toArray(new Pair[participants.size()]);
64 | }
65 |
66 | private static void addNonNullViewToTransitionParticipants(View view, List participants) {
67 | if (view == null) {
68 | return;
69 | }
70 | participants.add(new Pair<>(view, view.getTransitionName()));
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/square.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations1.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
17 |
18 |
25 |
26 |
33 |
34 |
35 |
36 |
41 |
42 |
43 |
49 |
50 |
53 |
54 |
55 |
58 |
59 |
64 |
65 |
70 |
71 |
72 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
35 |
39 |
40 |
45 |
46 |
49 |
50 |
55 |
56 |
61 |
62 |
63 |
66 |
67 |
72 |
73 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations_scene0.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations_scene1.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
12 |
13 |
19 |
20 |
26 |
27 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations_scene2.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
13 |
14 |
19 |
20 |
27 |
28 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations_scene3.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
14 |
15 |
21 |
22 |
28 |
29 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_animations_scene4.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
13 |
14 |
21 |
22 |
27 |
28 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
15 |
16 |
23 |
24 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_reveal.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
16 |
17 |
24 |
25 |
28 |
29 |
36 |
37 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
58 |
59 |
63 |
64 |
65 |
71 |
72 |
79 |
80 |
87 |
88 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sharedelement.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
15 |
16 |
23 |
24 |
32 |
33 |
34 |
35 |
38 |
39 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sharedelement_fragment1.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
18 |
19 |
22 |
23 |
24 |
28 |
29 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sharedelement_fragment2.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_transition1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
15 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
44 |
45 |
50 |
51 |
56 |
57 |
58 |
59 |
64 |
65 |
70 |
71 |
76 |
77 |
78 |
82 |
83 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_transition2.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
25 |
26 |
33 |
34 |
35 |
36 |
41 |
42 |
48 |
49 |
52 |
53 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_transition3.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
25 |
26 |
33 |
34 |
35 |
36 |
41 |
42 |
48 |
49 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
21 |
22 |
27 |
28 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/square.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/transition/changebounds_with_arcmotion.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/explode.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/slide_and_changebounds.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/slide_and_changebounds_sequential.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/slide_and_changebounds_sequential_with_interpolators.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/transition/slide_from_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | #9ccc
19 |
20 | #039BE5
21 | #0277BD
22 | #424242
23 | #3F51B5
24 |
25 | @android:color/white
26 | #616161
27 |
28 | #ff4444
29 | #33b5e5
30 | #669900
31 | #ff8800
32 |
33 |
34 |
35 | #84ffff
36 | #4FC3F7
37 | #ff193a
38 | @color/text_dark
39 | @android:color/black
40 | #039BE5
41 |
42 | #b9f6ca
43 | #669900
44 | #e919ff
45 | @color/text_dark
46 | #558B2F
47 |
48 | #b388ff
49 | #7e57c2
50 | #ff9419
51 | @color/text_light
52 | #6c4aa6
53 |
54 | #ff8a80
55 | #ff5252
56 | #fffc19
57 | @color/text_light
58 | #e64a4a
59 |
60 | #ffff8d
61 | #ff8800
62 | #19dcff
63 | @color/text_dark
64 | #EF6C00
65 |
66 | #00e676
67 | #ff5252
68 | #E0E0E0
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4dp
4 | 8dp
5 | 16dp
6 | 72dp
7 |
8 |
9 | 4dp
10 | 8dp
11 |
12 | 40dp
13 |
14 | 1500
15 | 500
16 | 300
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Material-Animations
3 |
4 | Hello world!
5 | Settings
6 |
7 | square_red
8 | square_blue
9 | square_green
10 | transition_reveal1
11 |
12 | sample_blue_title
13 | Bacon ipsum dolor amet cupidatat bresaola minim, aliquip beef aute ea porchetta. Meatball brisket do, rump in beef ea ham hock spare ribs mollit qui dolore ipsum voluptate cow. Drumstick prosciutto salami duis jerky jowl. Mollit ball tip short ribs doner fugiat frankfurter leberkas andouille kevin pork loin nostrud ham culpa. Rump pariatur ham hock excepteur picanha pork. Corned beef flank proident shankle rump.
14 | Porchetta landjaeger tail meatball t-bone spare ribs. Sirloin pork chop bacon pork belly strip steak. Porchetta ham meatball pig salami short ribs jowl spare ribs sirloin tongue jerky cupim chuck.
15 | Circular Reveal Animation starting from the center of target view
16 | Circular Reveal Animation starting from touch coordinates
17 | View layout change animation with Circular Reveal Animation on finish
18 | Circular Reveal Animation from top with nested animations on end
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
28 |
29 |
38 |
39 |
47 |
48 |
56 |
57 |
60 |
61 |
64 |
65 |
71 |
72 |
76 |
77 |
80 |
81 |
85 |
86 |
91 |
92 |
97 |
98 |
102 |
103 |
108 |
109 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/screenshots/A_startActivity_B.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/A_startActivity_B.png
--------------------------------------------------------------------------------
/screenshots/B_back_A.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/B_back_A.png
--------------------------------------------------------------------------------
/screenshots/a_b_shared_element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/a_b_shared_element.png
--------------------------------------------------------------------------------
/screenshots/example1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/example1.gif
--------------------------------------------------------------------------------
/screenshots/example2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/example2.gif
--------------------------------------------------------------------------------
/screenshots/example3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/example3.gif
--------------------------------------------------------------------------------
/screenshots/reveal_blue.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/reveal_blue.gif
--------------------------------------------------------------------------------
/screenshots/reveal_green.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/reveal_green.gif
--------------------------------------------------------------------------------
/screenshots/reveal_red.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/reveal_red.gif
--------------------------------------------------------------------------------
/screenshots/reveal_yellow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/reveal_yellow.gif
--------------------------------------------------------------------------------
/screenshots/scene-transition.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/scene-transition.gif
--------------------------------------------------------------------------------
/screenshots/scenes_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/scenes_anim.gif
--------------------------------------------------------------------------------
/screenshots/shared_element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/shared_element.png
--------------------------------------------------------------------------------
/screenshots/shared_element_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/shared_element_anim.gif
--------------------------------------------------------------------------------
/screenshots/shared_element_no_overlap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/shared_element_no_overlap.gif
--------------------------------------------------------------------------------
/screenshots/shared_element_overlap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/shared_element_overlap.gif
--------------------------------------------------------------------------------
/screenshots/shared_reveal_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/shared_reveal_anim.gif
--------------------------------------------------------------------------------
/screenshots/transition-shared-elements.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition-shared-elements.gif
--------------------------------------------------------------------------------
/screenshots/transition-shared-elements2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition-shared-elements2.gif
--------------------------------------------------------------------------------
/screenshots/transition_A_to_B.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_A_to_B.png
--------------------------------------------------------------------------------
/screenshots/transition_B_to_A.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_B_to_A.png
--------------------------------------------------------------------------------
/screenshots/transition_explode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_explode.gif
--------------------------------------------------------------------------------
/screenshots/transition_fade.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_fade.gif
--------------------------------------------------------------------------------
/screenshots/transition_fade2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_fade2.gif
--------------------------------------------------------------------------------
/screenshots/transition_slide.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/transition_slide.gif
--------------------------------------------------------------------------------
/screenshots/view_layout_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lgvalle/Material-Animations/be755fe9ebe7f9093360e4263c4293de368da1c7/screenshots/view_layout_anim.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------