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