Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d3519b9 authored by Daniel Lehmann's avatar Daniel Lehmann Committed by Android (Google) Code Review
Browse files

Merge "De-jank quick contact animation" into jb-dev

parents 4d89ef85 3a53c73f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -9,10 +9,12 @@
  public void *(android.view.MenuItem);
}

# Any class or method annotated with NeededForTesting.
# Any class or method annotated with NeededForTesting or NeededForReflection.
-keep @com.android.contacts.test.NeededForTesting class *
-keep @com.android.contacts.test.NeededForReflection class *
-keepclassmembers class * {
@com.android.contacts.test.NeededForTesting *;
@com.android.contacts.test.NeededForReflection *;
}

-verbose
+39 −10
Original line number Diff line number Diff line
@@ -17,15 +17,17 @@
package com.android.contacts.quickcontact;

import com.android.contacts.R;
import com.android.contacts.test.NeededForReflection;
import com.android.contacts.util.SchedulingUtils;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -53,11 +55,13 @@ public class FloatingChildLayout extends FrameLayout {
    private View mChild;
    private Rect mTargetScreen = new Rect();
    private final int mAnimationDuration;
    private final TransitionDrawable mBackground;

    /** The phase of the background dim. This is one of the values of {@link BackgroundPhase}  */
    private int mBackgroundPhase = BackgroundPhase.BEFORE;

    private ObjectAnimator mBackgroundAnimator = ObjectAnimator.ofInt(this,
            "backgroundColorAlpha", 0, DIM_BACKGROUND_ALPHA);

    private interface BackgroundPhase {
        public static final int BEFORE = 0;
        public static final int APPEARING_OR_VISIBLE = 1;
@@ -76,7 +80,7 @@ public class FloatingChildLayout extends FrameLayout {
    }

    // Black, 50% alpha as per the system default.
    private static final int DIM_BACKGROUND_COLOR = 0x7F000000;
    private static final int DIM_BACKGROUND_ALPHA = 0x7F;

    public FloatingChildLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -85,10 +89,7 @@ public class FloatingChildLayout extends FrameLayout {
                resources.getDimensionPixelOffset(R.dimen.quick_contact_top_position);
        mAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime);

        final ColorDrawable[] drawables =
            { new ColorDrawable(0), new ColorDrawable(DIM_BACKGROUND_COLOR) };
        mBackground = new TransitionDrawable(drawables);
        super.setBackground(mBackground);
        super.setBackground(new ColorDrawable(0));
    }

    @Override
@@ -178,17 +179,35 @@ public class FloatingChildLayout extends FrameLayout {
        child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
    }

    @NeededForReflection
    public void setBackgroundColorAlpha(int alpha) {
        setBackgroundColor(alpha << 24);
    }

    public void fadeInBackground() {
        if (mBackgroundPhase == BackgroundPhase.BEFORE) {
            mBackgroundPhase = BackgroundPhase.APPEARING_OR_VISIBLE;
            mBackground.startTransition(mAnimationDuration);

            createChildLayer();

            SchedulingUtils.doAfterDraw(this, new Runnable() {
                @Override
                public void run() {
                    mBackgroundAnimator.setDuration(mAnimationDuration).start();
                }
            });
        }
    }

    public void fadeOutBackground() {
        if (mBackgroundPhase == BackgroundPhase.APPEARING_OR_VISIBLE) {
            mBackgroundPhase = BackgroundPhase.DISAPPEARING_OR_GONE;
            mBackground.reverseTransition(mAnimationDuration);
            if (mBackgroundAnimator.isRunning()) {
                mBackgroundAnimator.reverse();
            } else {
                ObjectAnimator.ofInt(this, "backgroundColorAlpha", DIM_BACKGROUND_ALPHA, 0).
                        setDuration(mAnimationDuration).start();
            }
        }
    }

@@ -212,6 +231,9 @@ public class FloatingChildLayout extends FrameLayout {
        if (mForegroundPhase == ForegroundPhase.APPEARING ||
                mForegroundPhase == ForegroundPhase.IDLE) {
            mForegroundPhase = ForegroundPhase.DISAPPEARING;

            createChildLayer();

            animateScale(true, onAnimationEndRunnable);
            return true;
        } else {
@@ -219,6 +241,12 @@ public class FloatingChildLayout extends FrameLayout {
        }
    }

    private void createChildLayer() {
        mChild.invalidate();
        mChild.setLayerType(LAYER_TYPE_HARDWARE, null);
        mChild.buildLayer();
    }

    /** Creates the open/close animation */
    private void animateScale(
            final boolean isExitAnimation,
@@ -231,7 +259,7 @@ public class FloatingChildLayout extends FrameLayout {
                : android.R.interpolator.decelerate_quint;
        final float scaleTarget = isExitAnimation ? 0.5f : 1.0f;

        mChild.animate().withLayer()
        mChild.animate()
                .setDuration(mAnimationDuration)
                .setInterpolator(AnimationUtils.loadInterpolator(getContext(), scaleInterpolator))
                .scaleX(scaleTarget)
@@ -240,6 +268,7 @@ public class FloatingChildLayout extends FrameLayout {
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mChild.setLayerType(LAYER_TYPE_NONE, null);
                        if (isExitAnimation) {
                            if (mForegroundPhase == ForegroundPhase.DISAPPEARING) {
                                mForegroundPhase = ForegroundPhase.AFTER;
+6 −1
Original line number Diff line number Diff line
@@ -220,8 +220,13 @@ public class QuickContactActivity extends Activity {
        mContactLoader = (ContactLoader) getLoaderManager().initLoader(
                LOADER_ID, null, mLoaderCallbacks);

        SchedulingUtils.doAfterLayout(mFloatingLayout, new Runnable() {
            @Override
            public void run() {
                mFloatingLayout.fadeInBackground();
            }
        });
    }

    private void handleOutsideTouch() {
        if (mFloatingLayout.isContentFullyVisible()) {
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.contacts.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Denotes that the class, constructor, method or field is used by tests and therefore cannot be
 * removed by tools like ProGuard.
 */
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
public @interface NeededForReflection{}