From Punched Cards to Prompts
AndroidIntroduction When computer programming was young, code was punched into cards. That is, holes were punched into a piece of cardboard in a format...
In the previous post, we took a first look at the [android.transition](http://developer.android.com/reference/android/transition/package-summary.html)
framework and started following the evolution of our AndroidTransitionExample project. In this post, we’ll continue our exploration by learning how to control transitions and how to load them from XML files.
To try out the example project, follow the instructions in the previous post under “Following along with Git.” The inset text below gives additional pointers.
Let’s look at controlling transitions. First, we’ll refactor a bit and extract the goToScene
method, instead of calling TransitionManager.go()
directly:
...
goButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TransitionManager.go(scene);
goToScene(scene);
}
});
...
private void goToScene(Scene scene) {
ChangeBounds changeBounds = new ChangeBounds();
Fade fadeOut = new Fade(Fade.OUT);
Fade fadeIn = new Fade(Fade.IN);
TransitionSet transition = new TransitionSet();
transition.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
transition
.addTransition(fadeOut)
.addTransition(changeBounds)
.addTransition(fadeIn);
TransitionManager.go(scene, transition);
}
Jump to “extract method goToScene”:
git checkout 6ea37f7
The effect is still the same. In fact, it’s identical to using AutoTransition. However, this approach gives us more control, since we can tweak the components of the transition set to our liking. For example, we could change the duration of some animations:
private void goToScene(Scene scene) {
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(1000);
Fade fadeOut = new Fade(Fade.OUT);
fadeOut.setDuration(1000);
Fade fadeIn = new Fade(Fade.IN);
fadeIn.setDuration(1000);
TransitionSet transition = new TransitionSet();
transition.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
transition
.addTransition(fadeOut)
.addTransition(changeBounds)
.addTransition(fadeIn);
TransitionManager.go(scene, transition);
}
Jump to “slow motion transitions”:
git checkout fbcc465
For some reason, the animation controls in Developer Options don’t seem to influence transition animations. The above code allows us to look at the animations in slow motion.
We can control more than just duration of these transitions. One interesting thing to try is adding an interpolator. One of the principles of classical animation states that characters cannot simply start moving. They have to show anticipation, then perform the movement and finally overshoot before coming to a stop. Using a built-in AnticipateOvershootInterpolator, we can achieve the desired effect. Note that we slowed down the change bounds animation, so that it’s easier to see.
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setInterpolator(new AnticipateOvershootInterpolator());
changeBounds.setDuration(2000);
Fade fadeOut = new Fade(Fade.OUT);
Jump to “use AnticipateOvershootInterpolator”:
git checkout 1de57f0
If you try pressing the “Perform the transition” button after the transition to the second scene, you’ll discover that it doesn’t do anything. That’s because the only button we wired up with an OnClickListener is the button in the first layout. To make the second scene’s button work, we have to load the scene differently:
View rootView = inflater.inflate(R.layout.fragment_transition_scene_1,
container, false);
final Scene scene = Scene.getSceneForLayout(container,
R.layout.fragment_transition_scene_2, getActivity());
View secondView = inflater.inflate(R.layout.fragment_transition_scene_2,
container, false);
final Scene scene = new Scene(container, (ViewGroup)secondView);
Button goButton = (Button)rootView.findViewById(R.id.goButton);
Now that we have the secondView
, we can wire up the second button:
final Scene originalScene = new Scene(container, (ViewGroup)rootView);
Button goBackButton = (Button)secondView.findViewById(R.id.goButton);
goBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
goToScene(originalScene);
}
});
This is what the final result looks like:
Jump to “add the return transition”:
git checkout 9871bfa
So far, we’ve looked at using the transition framework in code. However, it is also possible to create transitions in XML. KitKat introduces the new resource folder transition
, which holds XML files that define transitions and even the mapping of scenes.
For example, defining our custom transition in XML would look like this (using slow_auto_transition.xml):
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="sequential">
<fade
android:fadingMode="fade_out"
android:duration="1000"/>
<changeBounds
android:duration="2000"
android:interpolator="@android:interpolator/anticipate_overshoot"/>
<fade
android:fadingMode="fade_in"
android:duration="1000"/>
</transitionSet>
Using the XML file would simplify our goToScene
method:
private void goToScene(Scene scene) {
TransitionInflater inflater = TransitionInflater.from(getActivity());
Transition transition
= inflater.inflateTransition(R.transition.slow_auto_transition);
TransitionManager.go(scene, transition);
}
Run the project now, and the result is exactly the same as before.
Jump to “inflate the transition from the XML file”:
git checkout c2a25d4
As mentioned above, it is also possible to inflate an entire transition manager instance from XML, which would define transitions for going from one scene to another. We’ll make the final change to our project. Here’s the new transition_manager.xml file:
<transitionManager
xmlns:android="http://schemas.android.com/apk/res/android">
<transition
android:fromScene="@layout/fragment_transition_scene_1"
android:toScene="@layout/fragment_transition_scene_2"
android:transition="@transition/slow_auto_transition"/>
<transition
android:fromScene="@layout/fragment_transition_scene_1"
android:toScene="@layout/fragment_transition_scene_2"
android:transition="@transition/slow_auto_transition"/>
We’ll also modify our layouts so that we don’t have to connect the buttons in code: add android:onClick="goToScene2"
to the goButton in the first layout and android:onClick="goToScene1"
in the second layout.
<Button
android:id="@+id/goButton"
android:text="@string/button_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="goToScene2"
We’ll move most of the code into the TransitionActivity and the TransitionFragment will be left with just loading the view:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_transition_scene_1, container, false);
return rootView;
}
Add the instance variables to TransitionActivity
:
private TransitionManager mTransitionManager;
private Scene mScene1;
private Scene mScene2;
Add the following code at the end of TransitionActivity.onCreate
:
ViewGroup container = (ViewGroup)findViewById(R.id.container);
TransitionInflater transitionInflater = TransitionInflater.from(this);
mTransitionManager = transitionInflater.inflateTransitionManager(
R.transition.transition_manager, container);
mScene1 = Scene.getSceneForLayout(container,
R.layout.fragment_transition_scene_1, this);
mScene2 = Scene.getSceneForLayout(container,
R.layout.fragment_transition_scene_2, this);
And finally, add the following two methods to TransitionActivity
:
public void goToScene1(View view) {
mTransitionManager.transitionTo(mScene1);
}
public void goToScene2(View view) {
mTransitionManager.transitionTo(mScene2);
}
The final result is still the same.
Jump to “load the transition manager from the XML file”:
git checkout cc40873
or
git checkout master
Enjoy the transitions!
Introduction When computer programming was young, code was punched into cards. That is, holes were punched into a piece of cardboard in a format...
Jetpack Compose is a declarative framework for building native Android UI recommended by Google. To simplify and accelerate UI development, the framework turns the...
Big Nerd Ranch is chock-full of incredibly talented people. Today, we’re starting a series, Tell Our BNR Story, where folks within our industry share...