TransitionAnimationView.java revision cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245
185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov/* 285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * 485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * you may not use this file except in compliance with the License. 685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * You may obtain a copy of the License at 785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * 885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * 1085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 1185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 1285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * See the License for the specific language governing permissions and 1485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * limitations under the License. 1585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov */ 1685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovpackage com.android.contacts.widget; 1785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 1885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.animation.Animator; 1985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.animation.Animator.AnimatorListener; 20cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmannimport android.animation.ObjectAnimator; 2185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.content.Context; 2285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.graphics.Bitmap; 2385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.graphics.Canvas; 2485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.graphics.Color; 2585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.graphics.drawable.BitmapDrawable; 2685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.util.AttributeSet; 2785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.view.View; 2885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovimport android.widget.FrameLayout; 2985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 3085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov/** 3185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * A container for a view that needs to have exit/enter animations when rebinding data. 32cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann * After rebinding the contents, the following call should be made (where child is the only visible) 33cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann * child 3485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * <pre> 35cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann * TransitionAnimationView.startAnimation(child); 3685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov * </pre> 3785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov */ 3885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikovpublic class TransitionAnimationView extends FrameLayout implements AnimatorListener { 3985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov private View mPreviousStateView; 4085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov private Bitmap mPreviousStateBitmap; 41cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann private ObjectAnimator mPreviousAnimator; 4285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 4385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov public TransitionAnimationView(Context context) { 4485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov this(context, null, 0); 4585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 4685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 4785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov public TransitionAnimationView(Context context, AttributeSet attrs) { 4885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov this(context, attrs, 0); 4985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 5085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 5185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov public TransitionAnimationView(Context context, AttributeSet attrs, int defStyle) { 5285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov super(context, attrs, defStyle); 5385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 5485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 5585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov @Override 56cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann protected void onFinishInflate() { 57cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann super.onFinishInflate(); 58cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView = new View(getContext()); 59cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setVisibility(View.INVISIBLE); 60cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 61cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann LayoutParams.MATCH_PARENT)); 62cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann addView(mPreviousStateView); 6385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 6485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 65bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov @Override 66bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov protected void onDetachedFromWindow() { 67bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov super.onDetachedFromWindow(); 68bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov mPreviousStateView.setBackgroundDrawable(null); 69bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov if (mPreviousStateBitmap != null) { 70bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov mPreviousStateBitmap.recycle(); 71bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov mPreviousStateBitmap = null; 72bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov } 73bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov } 74bcf864578e0fe25813af75f33f5560709a5c8515Dmitri Plotnikov 752f41fe6bcc8d055bf53ad070425552fad57dff21Daniel Lehmann public void startTransition(View view, boolean closing) { 76cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann if (mPreviousAnimator != null && mPreviousAnimator.isRunning()) { 77cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator.end(); 7858d8be3ff47747454afdfadfe2f566a183cdee3bDmitri Plotnikov } 7985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov if (view.getVisibility() != View.VISIBLE) { 8085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov if (!closing) { 81cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 0.0f, 1.0f); 82cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator.start(); 8385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 8485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } else if (closing) { 85cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f); 86cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator.start(); 8785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } else { 88cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann if (view.getWidth() > 0 && view.getHeight() > 0) { 89cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann // Take a "screenshot" of the current state of the screen and show that on top 90cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann // of the real content. Then, fade that out. 91cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateBitmap = Bitmap.createBitmap( 92cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); 93cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setBackgroundDrawable( 94cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann new BitmapDrawable(getContext().getResources(), mPreviousStateBitmap)); 95cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setLayoutParams(view.getLayoutParams()); 96cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateBitmap.eraseColor(Color.WHITE); 97cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann Canvas canvas = new Canvas(mPreviousStateBitmap); 98cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann view.draw(canvas); 99cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann canvas.setBitmap(null); 100cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setVisibility(View.VISIBLE); 101cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann 102cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator = 103cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann ObjectAnimator.ofFloat(mPreviousStateView, View.ALPHA, 1.0f, 0.0f); 104cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator.start(); 10511a2cb156aedd48424651508689e56374fb10a25Dmitri Plotnikov } 10685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 10785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 10885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 10985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov @Override 110dfbe752b2b96e5a00cff6b936a3bdc194774a0aaDmitri Plotnikov public void onAnimationEnd(Animator animation) { 11185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov mPreviousStateView.setVisibility(View.INVISIBLE); 112cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateView.setBackgroundDrawable(null); 113cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateBitmap.recycle(); 114cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousStateBitmap = null; 115cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245Daniel Lehmann mPreviousAnimator = null; 11685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 11785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 11885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov @Override 119dfbe752b2b96e5a00cff6b936a3bdc194774a0aaDmitri Plotnikov public void onAnimationCancel(Animator animation) { 12085609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 12185609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 12285609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov @Override 12385609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov public void onAnimationStart(Animator animation) { 12485609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 12585609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov 12685609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov @Override 12785609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov public void onAnimationRepeat(Animator animation) { 12885609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov } 12985609edf326d86d4a2b67be3610f8de7cce28d1dDmitri Plotnikov} 130