Robert Ly | 3f53212 | 2012-10-03 14:20:26 -0700 | [diff] [blame] | 1 | page.title=Crossfading Two Views |
| 2 | trainingnavtop=true |
| 3 | |
| 4 | |
| 5 | @jd:body |
| 6 | |
| 7 | <div id="tb-wrapper"> |
| 8 | <div id="tb"> |
| 9 | <h2> |
| 10 | This lesson teaches you to: |
| 11 | </h2> |
| 12 | <ol> |
| 13 | <li> |
| 14 | <a href="#views">Create the Views</a> |
| 15 | </li> |
| 16 | <li> |
| 17 | <a href="#setup">Set up the Animation</a> |
| 18 | </li> |
| 19 | <li> |
| 20 | <a href="#animate">Crossfade the Views</a> |
| 21 | </li> |
| 22 | </ol> |
Roman Nurik | fb80c9e | 2013-01-09 08:35:53 -0800 | [diff] [blame] | 23 | <h2> |
| 24 | Try it out |
| 25 | </h2> |
| 26 | <div class="download-box"> |
| 27 | <a href="{@docRoot}shareables/training/Animations.zip" class= |
| 28 | "button">Download the sample app</a> |
| 29 | <p class="filename"> |
| 30 | Animations.zip |
| 31 | </p> |
| 32 | </div> |
Robert Ly | 3f53212 | 2012-10-03 14:20:26 -0700 | [diff] [blame] | 33 | </div> |
| 34 | </div> |
| 35 | |
| 36 | <p> |
| 37 | Crossfade animations (also know as dissolve) gradually fade out one UI component while simultaneously fading in |
| 38 | another. This animation is useful for situations where you want to switch content or views |
| 39 | in your app. Crossfades are very subtle and short but offer a fluid transition from one screen to the |
| 40 | next. When you don't use them, however, transitions often feel abrupt or hurried. |
| 41 | </p> |
| 42 | <p>Here's an example of a crossfade from a progress indicator to some text content. |
| 43 | </p> |
| 44 | |
| 45 | <div class="framed-galaxynexus-land-span-8"> |
| 46 | <video class="play-on-hover" autoplay> |
| 47 | <source src="anim_crossfade.mp4" type="video/mp4"> |
| 48 | <source src="anim_crossfade.webm" type="video/webm"> |
| 49 | <source src="anim_crossfade.ogv" type="video/ogg"> |
| 50 | </video> |
| 51 | </div> |
| 52 | <div class="figure-caption"> |
| 53 | Crossfade animation |
| 54 | <div class="video-instructions"> </div> |
| 55 | </div> |
| 56 | |
| 57 | <p> |
| 58 | If you want to jump ahead and see a full working example, |
| 59 | <a href="{@docRoot}shareables/training/Animations.zip">download</a> |
| 60 | and run the sample app and select the Crossfade example. |
| 61 | See the following files for the code implementation: |
| 62 | </p> |
| 63 | <ul> |
| 64 | <li> |
| 65 | <code>src/CrossfadeActivity.java</code> |
| 66 | </li> |
| 67 | <li> |
| 68 | <code>layout/activity_crossfade.xml</code> |
| 69 | </li> |
| 70 | <li> |
| 71 | <code>menu/activity_crossfade.xml</code> |
| 72 | </li> |
| 73 | </ul> |
| 74 | <h2 id="views"> |
| 75 | Create the Views |
| 76 | </h2> |
| 77 | <p> |
| 78 | Create the two views that you want to crossfade. The following example creates a progress |
| 79 | indicator and a scrollable text view: |
| 80 | </p> |
| 81 | <pre> |
| 82 | <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 83 | android:layout_width="match_parent" |
| 84 | android:layout_height="match_parent"> |
| 85 | |
| 86 | <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" |
| 87 | android:id="@+id/content" |
| 88 | android:layout_width="match_parent" |
| 89 | android:layout_height="match_parent"> |
| 90 | |
| 91 | <TextView style="?android:textAppearanceMedium" |
| 92 | android:lineSpacingMultiplier="1.2" |
| 93 | android:layout_width="match_parent" |
| 94 | android:layout_height="wrap_content" |
| 95 | android:text="@string/lorem_ipsum" |
| 96 | android:padding="16dp" /> |
| 97 | |
| 98 | </ScrollView> |
| 99 | |
| 100 | <ProgressBar android:id="@+id/loading_spinner" |
| 101 | style="?android:progressBarStyleLarge" |
| 102 | android:layout_width="wrap_content" |
| 103 | android:layout_height="wrap_content" |
| 104 | android:layout_gravity="center" /> |
| 105 | |
| 106 | </FrameLayout> |
| 107 | </pre> |
| 108 | <h2 id="setup"> |
| 109 | Set up the Animation |
| 110 | </h2> |
| 111 | <p> |
| 112 | To set up the animation: |
| 113 | </p> |
| 114 | <ol> |
| 115 | <li>Create member variables for the views that you want to crossfade. You need |
| 116 | these references later when modifying the views during the animation. |
| 117 | </li> |
| 118 | <li>For the view that is being faded in, set its visibility to {@link |
| 119 | android.view.View#GONE}. This prevents the view from taking up layout space and omits it |
| 120 | from layout calculations, speeding up processing. |
| 121 | </li> |
| 122 | <li>Cache the <code>{@link android.R.integer#config_shortAnimTime}</code> |
| 123 | system property in a member variable. This property defines a standard |
| 124 | "short" duration for the animation. This duration is ideal for subtle animations or |
| 125 | animations that occur very frequently. {@link android.R.integer#config_longAnimTime} and |
| 126 | {@link android.R.integer#config_mediumAnimTime} are also available if you wish to use them. |
| 127 | </li> |
| 128 | </ol> |
| 129 | <p> |
| 130 | Here's an example using the layout from the previous code snippet as the activity content |
| 131 | view: |
| 132 | </p> |
| 133 | <pre> |
| 134 | public class CrossfadeActivity extends Activity { |
| 135 | |
| 136 | private View mContentView; |
| 137 | private View mLoadingView; |
| 138 | private int mShortAnimationDuration; |
| 139 | |
| 140 | ... |
| 141 | |
| 142 | @Override |
| 143 | protected void onCreate(Bundle savedInstanceState) { |
| 144 | super.onCreate(savedInstanceState); |
| 145 | setContentView(R.layout.activity_crossfade); |
| 146 | |
| 147 | mContentView = findViewById(R.id.content); |
| 148 | mLoadingView = findViewById(R.id.loading_spinner); |
| 149 | |
| 150 | // Initially hide the content view. |
| 151 | mContentView.setVisibility(View.GONE); |
| 152 | |
| 153 | // Retrieve and cache the system's default "short" animation time. |
| 154 | mShortAnimationDuration = getResources().getInteger( |
| 155 | android.R.integer.config_shortAnimTime); |
| 156 | } |
| 157 | |
| 158 | </pre> |
| 159 | <h2 id="animate"> |
| 160 | Crossfade the Views |
| 161 | </h2> |
| 162 | <p> |
| 163 | Now that the views are properly set up, crossfade them by doing the following: |
| 164 | </p> |
| 165 | <ol> |
| 166 | <li>For the view that is fading in, set the alpha value to <code>0</code> and the visibility |
| 167 | to {@link android.view.View#VISIBLE}. (Remember that it was initially set to {@link |
| 168 | android.view.View#GONE}.) This makes the view visible but completely transparent. |
| 169 | </li> |
| 170 | <li>For the view that is fading in, animate its alpha value from <code>0</code> to |
| 171 | <code>1</code>. At the same time, for the view that is fading out, animate the alpha value |
| 172 | from <code>1</code> to <code>0</code>. |
| 173 | </li> |
| 174 | <li>Using {@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()} |
| 175 | in an {@link android.animation.Animator.AnimatorListener}, set the visibility of the view |
| 176 | that was fading out to {@link android.view.View#GONE}. Even though the alpha value is <code>0</code>, |
| 177 | setting the view's visibility to {@link android.view.View#GONE} prevents the view from taking |
| 178 | up layout space and omits it from layout calculations, speeding up processing. |
| 179 | </li> |
| 180 | </ol> |
| 181 | <p> |
| 182 | The following method shows an example of how to do this: |
| 183 | </p> |
| 184 | <pre> |
| 185 | private View mContentView; |
| 186 | private View mLoadingView; |
| 187 | private int mShortAnimationDuration; |
| 188 | |
| 189 | ... |
| 190 | |
| 191 | private void crossfade() { |
| 192 | |
| 193 | // Set the content view to 0% opacity but visible, so that it is visible |
| 194 | // (but fully transparent) during the animation. |
| 195 | mContentView.setAlpha(0f); |
| 196 | mContentView.setVisibility(View.VISIBLE); |
| 197 | |
| 198 | // Animate the content view to 100% opacity, and clear any animation |
| 199 | // listener set on the view. |
| 200 | mContentView.animate() |
| 201 | .alpha(1f) |
| 202 | .setDuration(mShortAnimationDuration) |
| 203 | .setListener(null); |
| 204 | |
| 205 | // Animate the loading view to 0% opacity. After the animation ends, |
| 206 | // set its visibility to GONE as an optimization step (it won't |
| 207 | // participate in layout passes, etc.) |
Scott Main | d608d5e | 2013-08-26 12:31:09 -0700 | [diff] [blame] | 208 | mLoadingView.animate() |
Robert Ly | 3f53212 | 2012-10-03 14:20:26 -0700 | [diff] [blame] | 209 | .alpha(0f) |
| 210 | .setDuration(mShortAnimationDuration) |
| 211 | .setListener(new AnimatorListenerAdapter() { |
| 212 | @Override |
| 213 | public void onAnimationEnd(Animator animation) { |
Scott Main | d608d5e | 2013-08-26 12:31:09 -0700 | [diff] [blame] | 214 | mLoadingView.setVisibility(View.GONE); |
Robert Ly | 3f53212 | 2012-10-03 14:20:26 -0700 | [diff] [blame] | 215 | } |
| 216 | }); |
| 217 | } |
| 218 | </pre> |