TransitionAnimationView.java revision cf3d9f04955a8ec3cb405b8a4ddcaddcece2a245
1/*
2 * Copyright (C) 2010 The Android Open Source Project
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 */
16package com.android.contacts.widget;
17
18import android.animation.Animator;
19import android.animation.Animator.AnimatorListener;
20import android.animation.ObjectAnimator;
21import android.content.Context;
22import android.graphics.Bitmap;
23import android.graphics.Canvas;
24import android.graphics.Color;
25import android.graphics.drawable.BitmapDrawable;
26import android.util.AttributeSet;
27import android.view.View;
28import android.widget.FrameLayout;
29
30/**
31 * A container for a view that needs to have exit/enter animations when rebinding data.
32 * After rebinding the contents, the following call should be made (where child is the only visible)
33 * child
34 * <pre>
35 *   TransitionAnimationView.startAnimation(child);
36 * </pre>
37 */
38public class TransitionAnimationView extends FrameLayout implements AnimatorListener {
39    private View mPreviousStateView;
40    private Bitmap mPreviousStateBitmap;
41    private ObjectAnimator mPreviousAnimator;
42
43    public TransitionAnimationView(Context context) {
44        this(context, null, 0);
45    }
46
47    public TransitionAnimationView(Context context, AttributeSet attrs) {
48        this(context, attrs, 0);
49    }
50
51    public TransitionAnimationView(Context context, AttributeSet attrs, int defStyle) {
52        super(context, attrs, defStyle);
53    }
54
55    @Override
56    protected void onFinishInflate() {
57        super.onFinishInflate();
58        mPreviousStateView = new View(getContext());
59        mPreviousStateView.setVisibility(View.INVISIBLE);
60        mPreviousStateView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
61                LayoutParams.MATCH_PARENT));
62        addView(mPreviousStateView);
63    }
64
65    @Override
66    protected void onDetachedFromWindow() {
67        super.onDetachedFromWindow();
68        mPreviousStateView.setBackgroundDrawable(null);
69        if (mPreviousStateBitmap != null) {
70            mPreviousStateBitmap.recycle();
71            mPreviousStateBitmap = null;
72        }
73    }
74
75    public void startTransition(View view, boolean closing) {
76        if (mPreviousAnimator != null && mPreviousAnimator.isRunning()) {
77            mPreviousAnimator.end();
78        }
79        if (view.getVisibility() != View.VISIBLE) {
80            if (!closing) {
81                mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 0.0f, 1.0f);
82                mPreviousAnimator.start();
83            }
84        } else if (closing) {
85            mPreviousAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f);
86            mPreviousAnimator.start();
87        } else {
88            if (view.getWidth() > 0 && view.getHeight() > 0) {
89                // Take a "screenshot" of the current state of the screen and show that on top
90                // of the real content. Then, fade that out.
91                mPreviousStateBitmap = Bitmap.createBitmap(
92                        view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
93                mPreviousStateView.setBackgroundDrawable(
94                        new BitmapDrawable(getContext().getResources(), mPreviousStateBitmap));
95                mPreviousStateView.setLayoutParams(view.getLayoutParams());
96                mPreviousStateBitmap.eraseColor(Color.WHITE);
97                Canvas canvas = new Canvas(mPreviousStateBitmap);
98                view.draw(canvas);
99                canvas.setBitmap(null);
100                mPreviousStateView.setVisibility(View.VISIBLE);
101
102                mPreviousAnimator =
103                        ObjectAnimator.ofFloat(mPreviousStateView, View.ALPHA, 1.0f, 0.0f);
104                mPreviousAnimator.start();
105            }
106        }
107    }
108
109    @Override
110    public void onAnimationEnd(Animator animation) {
111        mPreviousStateView.setVisibility(View.INVISIBLE);
112        mPreviousStateView.setBackgroundDrawable(null);
113        mPreviousStateBitmap.recycle();
114        mPreviousStateBitmap = null;
115        mPreviousAnimator = null;
116    }
117
118    @Override
119    public void onAnimationCancel(Animator animation) {
120    }
121
122    @Override
123    public void onAnimationStart(Animator animation) {
124    }
125
126    @Override
127    public void onAnimationRepeat(Animator animation) {
128    }
129}
130