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

Commit 4abf86ed authored by Jim Miller's avatar Jim Miller Committed by Android Git Automerger
Browse files

am a073e570: Fix 6398209: General animation improvements for swipe to search

* commit 'a073e570':
  Fix 6398209: General animation improvements for swipe to search
parents 42656867 a073e570
Loading
Loading
Loading
Loading
+100 −78
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.internal.widget.multiwaveview;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -27,6 +28,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -52,10 +54,11 @@ public class MultiWaveView extends View {

    // Wave state machine
    private static final int STATE_IDLE = 0;
    private static final int STATE_FIRST_TOUCH = 1;
    private static final int STATE_TRACKING = 2;
    private static final int STATE_SNAP = 3;
    private static final int STATE_FINISH = 4;
    private static final int STATE_START = 1;
    private static final int STATE_FIRST_TOUCH = 2;
    private static final int STATE_TRACKING = 3;
    private static final int STATE_SNAP = 4;
    private static final int STATE_FINISH = 5;

    // Animation properties.
    private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
@@ -74,17 +77,18 @@ public class MultiWaveView extends View {
    private static final int CHEVRON_INCREMENTAL_DELAY = 160;
    private static final int CHEVRON_ANIMATION_DURATION = 850;
    private static final int RETURN_TO_HOME_DELAY = 1200;
    private static final int RETURN_TO_HOME_DURATION = 300;
    private static final int RETURN_TO_HOME_DURATION = 200;
    private static final int HIDE_ANIMATION_DELAY = 200;
    private static final int HIDE_ANIMATION_DURATION = 200;
    private static final int SHOW_ANIMATION_DURATION = 200;
    private static final int SHOW_ANIMATION_DELAY = 50;
    private static final int INITIAL_SHOW_HANDLE_DURATION = 200;

    private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
    private static final float TARGET_SCALE_SELECTED = 0.8f;
    private static final long INITIAL_SHOW_HANDLE_DURATION = 200;
    private static final float TARGET_SCALE_UNSELECTED = 1.0f;
    private static final float RING_SCALE_UNSELECTED = 0.5f;
    private static final float RING_SCALE_SELECTED = 1.5f;
    private static final float TARGET_SCALE_EXPANDED = 1.0f;
    private static final float TARGET_SCALE_COLLAPSED = 0.8f;
    private static final float RING_SCALE_EXPANDED = 1.0f;
    private static final float RING_SCALE_COLLAPSED = 0.5f;

    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;

@@ -182,7 +186,7 @@ public class MultiWaveView extends View {
            if (mNewTargetResources != 0) {
                internalSetTargetResources(mNewTargetResources);
                mNewTargetResources = 0;
                hideTargets(false);
                hideTargets(false, false);
            }
            mAnimatingTargets = false;
        }
@@ -195,6 +199,7 @@ public class MultiWaveView extends View {
    private int mVerticalInset;
    private int mGravity = Gravity.TOP;
    private boolean mInitialLayout = true;
    private Tweener mBackgroundAnimator;

    public MultiWaveView(Context context) {
        this(context, null);
@@ -358,14 +363,21 @@ public class MultiWaveView extends View {
        switch (state) {
            case STATE_IDLE:
                deactivateTargets();
                hideTargets(true, false);
                startBackgroundAnimation(0, 0.0f);
                mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
                break;

            case STATE_START:
                deactivateHandle(0, 0, 1.0f, null);
                startBackgroundAnimation(0, 0.0f);
                break;

            case STATE_FIRST_TOUCH:
                stopHandleAnimation();
                deactivateTargets();
                showTargets(true);
                activateHandle();
                mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
                startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
                setGrabbedState(OnTriggerListener.CENTER_HANDLE);
                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                    announceTargets();
@@ -384,17 +396,29 @@ public class MultiWaveView extends View {
        }
    }

    private void activateHandle() {
        mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
        if (mAlwaysTrackFinger) {
            mHandleAnimations.stop();
            mHandleDrawable.setAlpha(0.0f);
            mHandleAnimations.add(Tweener.to(mHandleDrawable, INITIAL_SHOW_HANDLE_DURATION,
    private void activateHandle(int duration, int delay, float finalAlpha,
            AnimatorListener finishListener) {
        mHandleAnimations.cancel();
        mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
                "ease", Ease.Cubic.easeIn,
                    "alpha", 1.0f,
                    "onUpdate", mUpdateListener));
                "delay", delay,
                "alpha", finalAlpha,
                "onUpdate", mUpdateListener,
                "onComplete", finishListener));
        mHandleAnimations.start();
    }

    private void deactivateHandle(int duration, int delay, float finalAlpha,
            AnimatorListener finishListener) {
        mHandleAnimations.cancel();
        mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
            "ease", Ease.Quart.easeOut,
            "delay", delay,
            "alpha", finalAlpha,
            "x", 0,
            "y", 0,
            "onUpdate", mUpdateListener,
            "onComplete", finishListener));
    }

    /**
@@ -441,14 +465,6 @@ public class MultiWaveView extends View {
        mChevronAnimations.start();
    }

    private void stopChevronAnimation() {
        mChevronAnimations.stop();
    }

    private void stopHandleAnimation() {
        mHandleAnimations.stop();
    }

    private void deactivateTargets() {
        final int count = mTargetDrawables.size();
        for (int i = 0; i < count; i++) {
@@ -493,39 +509,33 @@ public class MultiWaveView extends View {

    private void doFinish() {
        final int activeTarget = mActiveTarget;
        boolean targetHit =  activeTarget != -1;
        final boolean targetHit =  activeTarget != -1;

        // Hide unselected targets
        hideTargets(true);

        // Highlight the selected one
        mHandleAnimations.cancel();
        if (targetHit) {
            mHandleDrawable.setAlpha(0.0f);
            mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
            hideUnselected(activeTarget);
            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);

            highlightSelected(activeTarget);

            // Inform listener of any active targets.  Typically only one will be active.
            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
            deactivateHandle(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
            dispatchTriggerEvent(activeTarget);
        }

        } else {
            // Animate handle back to the center based on current state.
        int delay = targetHit ? RETURN_TO_HOME_DELAY : 0;
        int duration = RETURN_TO_HOME_DURATION;
        mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
                "ease", Ease.Quart.easeOut,
                "delay", delay,
                "alpha", mAlwaysTrackFinger ? 0.0f : 1.0f,
                "x", 0,
                "y", 0,
                "onUpdate", mUpdateListener,
                "onComplete", (mDragging && !targetHit) ? mResetListenerWithPing : mResetListener));
            deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
                    mResetListenerWithPing);
            hideTargets(true, false);
            mHandleAnimations.start();
        }

        setGrabbedState(OnTriggerListener.NO_HANDLE);
    }

    private void highlightSelected(int activeTarget) {
        // Highlight the given target and fade others
        mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
        hideUnselected(activeTarget);
    }

    private void hideUnselected(int active) {
        for (int i = 0; i < mTargetDrawables.size(); i++) {
            if (i != active) {
@@ -535,16 +545,15 @@ public class MultiWaveView extends View {
        mOuterRing.setAlpha(0.0f);
    }

    private void hideTargets(boolean animate) {
    private void hideTargets(boolean animate, boolean expanded) {
        mTargetAnimations.cancel();
        // Note: these animations should complete at the same time so that we can swap out
        // the target assets asynchronously from the setTargetResources() call.
        mAnimatingTargets = animate;
        final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
        final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
        final boolean targetSelected = mActiveTarget != -1;

        final float targetScale = targetSelected ? TARGET_SCALE_SELECTED : TARGET_SCALE_UNSELECTED;
        final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
        final int length = mTargetDrawables.size();
        for (int i = 0; i < length; i++) {
            TargetDrawable target = mTargetDrawables.get(i);
@@ -558,7 +567,7 @@ public class MultiWaveView extends View {
                    "onUpdate", mUpdateListener));
        }

        final float ringScaleTarget = targetSelected ? RING_SCALE_SELECTED : RING_SCALE_UNSELECTED;
        final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
                "ease", Ease.Cubic.easeOut,
                "alpha", 0.0f,
@@ -580,8 +589,6 @@ public class MultiWaveView extends View {
        for (int i = 0; i < length; i++) {
            TargetDrawable target = mTargetDrawables.get(i);
            target.setState(TargetDrawable.STATE_INACTIVE);
            target.setScaleX(TARGET_SCALE_SELECTED);
            target.setScaleY(TARGET_SCALE_SELECTED);
            mTargetAnimations.add(Tweener.to(target, duration,
                    "ease", Ease.Cubic.easeOut,
                    "alpha", 1.0f,
@@ -732,17 +739,30 @@ public class MultiWaveView extends View {
     * @param animate
     */
    public void reset(boolean animate) {
        stopChevronAnimation();
        stopHandleAnimation();
        mChevronAnimations.stop();
        mHandleAnimations.stop();
        mTargetAnimations.stop();
        startBackgroundAnimation(0, 0.0f);
        hideChevrons();
        hideTargets(animate);
        mHandleDrawable.setX(0);
        mHandleDrawable.setY(0);
        mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
        hideTargets(animate, false);
        deactivateHandle(0, 0, 1.0f, null);
        Tweener.reset();
    }

    private void startBackgroundAnimation(int duration, float alpha) {
        Drawable background = getBackground();
        if (mAlwaysTrackFinger && background != null) {
            if (mBackgroundAnimator != null) {
                mBackgroundAnimator.animator.end();
            }
            mBackgroundAnimator = Tweener.to(background, duration,
                    "ease", Ease.Cubic.easeIn,
                    "alpha", new int[] {0, (int)(255.0f * alpha)},
                    "delay", SHOW_ANIMATION_DELAY);
            mBackgroundAnimator.animator.start();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
@@ -784,7 +804,10 @@ public class MultiWaveView extends View {
    }

    private void handleDown(MotionEvent event) {
        if (!trySwitchToFirstTouchState(event.getX(), event.getY())) {
        float eventX = event.getX();
        float eventY = event.getY();
        switchToState(STATE_START, eventX, eventY);
        if (!trySwitchToFirstTouchState(eventX, eventY)) {
            mDragging = false;
            mTargetAnimations.cancel();
            ping();
@@ -830,7 +853,9 @@ public class MultiWaveView extends View {

            if (!mDragging) {
                trySwitchToFirstTouchState(eventX, eventY);
            } else {
            }

            if (mDragging) {
                if (singleTarget) {
                    // Snap to outer ring if there's only one target
                    float snapRadius = mOuterRadius - mSnapMargin;
@@ -865,17 +890,11 @@ public class MultiWaveView extends View {
        if (activeTarget != -1) {
            switchToState(STATE_SNAP, x,y);
            TargetDrawable target = targets.get(activeTarget);
            float newX = singleTarget ? x : target.getX();
            float newY = singleTarget ? y : target.getY();
            final float newX = singleTarget ? x : target.getX();
            final float newY = singleTarget ? y : target.getY();
            moveHandleTo(newX, newY, false);
            mHandleAnimations.cancel();
            mHandleDrawable.setAlpha(0.0f);
        } else {
            switchToState(STATE_TRACKING, x, y);
            if (mActiveTarget != -1) {
                mHandleAnimations.cancel();
                mHandleDrawable.setAlpha(1.0f);
            }
            moveHandleTo(x, y, false);
        }

@@ -900,6 +919,9 @@ public class MultiWaveView extends View {
                    String targetContentDescription = getTargetDescription(activeTarget);
                    announceText(targetContentDescription);
                }
                activateHandle(0, 0, 0.0f, null);
            } else {
                activateHandle(0, 0, 1.0f, null);
            }
        }
        mActiveTarget = activeTarget;
@@ -1021,7 +1043,7 @@ public class MultiWaveView extends View {

        if (mInitialLayout) {
            hideChevrons();
            hideTargets(false);
            hideTargets(false, false);
            moveHandleTo(0, 0, false);
            mInitialLayout = false;
        }
+3 −0
Original line number Diff line number Diff line
@@ -83,6 +83,9 @@ class Tweener {
            } else if (value instanceof float[]) {
                props.add(PropertyValuesHolder.ofFloat(key,
                        ((float[])value)[0], ((float[])value)[1]));
            } else if (value instanceof int[]) {
                props.add(PropertyValuesHolder.ofInt(key,
                        ((int[])value)[0], ((int[])value)[1]));
            } else if (value instanceof Number) {
                float floatValue = ((Number)value).floatValue();
                props.add(PropertyValuesHolder.ofFloat(key, floatValue));
+21 −48
Original line number Diff line number Diff line
@@ -22,39 +22,16 @@
    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/search_panel_container"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingBottom="0dip">

    <RelativeLayout
        android:id="@+id/search_bg_protect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/search_panel_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true">

            <View
                android:layout_width="0dip"
                android:layout_height="0dip"
                android:layout_alignTop="@id/multi_wave_view"
                android:layout_alignLeft="@id/multi_wave_view"
                android:layout_alignRight="@id/multi_wave_view"
                android:layout_alignBottom="@id/multi_wave_view"
                android:layout_marginBottom="@dimen/navigation_bar_size"
                android:background="@drawable/navbar_search_bg_scrim"/>
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <com.android.internal.widget.multiwaveview.MultiWaveView
        android:id="@+id/multi_wave_view"
                android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/navbar_search_panel_height"
                android:layout_alignParentBottom="true"
                android:gravity="top"
        android:layout_gravity="center_horizontal|bottom"
        android:gravity="center_horizontal|top"
        android:background="@drawable/navbar_search_bg_scrim"

        prvandroid:targetDrawables="@array/navbar_search_targets"
        prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
@@ -67,8 +44,4 @@
        prvandroid:vibrationDuration="@integer/config_vibration_duration"
        prvandroid:alwaysTrackFinger="true"/>

        </RelativeLayout>

    </RelativeLayout>

</com.android.systemui.SearchPanelView>
+22 −48
Original line number Diff line number Diff line
@@ -22,39 +22,17 @@
    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/search_panel_container"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingBottom="0dip">

    <RelativeLayout
        android:id="@+id/search_bg_protect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/search_panel_container"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/navbar_search_panel_height"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="-120dip">

            <View
                android:layout_width="0dip"
                android:layout_height="0dip"
                android:layout_alignTop="@id/multi_wave_view"
                android:layout_alignLeft="@id/multi_wave_view"
                android:layout_alignRight="@id/multi_wave_view"
                android:layout_alignBottom="@id/multi_wave_view"
                android:layout_marginBottom="@dimen/navigation_bar_size"
                android:background="@drawable/navbar_search_bg_scrim"/>
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <com.android.internal.widget.multiwaveview.MultiWaveView
        android:id="@+id/multi_wave_view"
                android:orientation="horizontal"
        android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentBottom="true"
        android:layout_height="@dimen/navbar_search_panel_height"
        android:layout_gravity="left|bottom"
        android:gravity="top|right"
        android:layout_marginLeft="-150dip"
        android:background="@drawable/navbar_search_bg_scrim"

        prvandroid:targetDrawables="@array/navbar_search_targets"
        prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
@@ -67,8 +45,4 @@
        prvandroid:vibrationDuration="@integer/config_vibration_duration"
        prvandroid:alwaysTrackFinger="true"/>

        </RelativeLayout>

    </RelativeLayout>

</com.android.systemui.SearchPanelView>
+25 −45
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
@@ -38,7 +37,6 @@ import android.widget.FrameLayout;

import com.android.internal.widget.multiwaveview.MultiWaveView;
import com.android.internal.widget.multiwaveview.MultiWaveView.OnTriggerListener;
import com.android.server.am.ActivityManagerService;
import com.android.systemui.R;
import com.android.systemui.recent.StatusBarTouchProxy;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -47,7 +45,8 @@ import com.android.systemui.statusbar.tablet.StatusBarPanel;
import com.android.systemui.statusbar.tablet.TabletStatusBar;

public class SearchPanelView extends FrameLayout implements
        StatusBarPanel, Animator.AnimatorListener {
        StatusBarPanel {
    private static final int SEARCH_PANEL_HOLD_DURATION = 500;
    static final String TAG = "SearchPanelView";
    static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
    private Context mContext;
@@ -123,7 +122,7 @@ public class SearchPanelView extends FrameLayout implements
    final MultiWaveView.OnTriggerListener mMultiWaveViewListener
            = new MultiWaveView.OnTriggerListener() {

        private int mTarget = -1;
        private boolean mWaitingForLaunch;

        public void onGrabbed(View v, int handle) {
        }
@@ -132,26 +131,28 @@ public class SearchPanelView extends FrameLayout implements
        }

        public void onGrabbedStateChange(View v, int handle) {
            if (mTarget == -1 && OnTriggerListener.NO_HANDLE == handle) {
            if (!mWaitingForLaunch && OnTriggerListener.NO_HANDLE == handle) {
                mBar.hideSearchPanel();
            }
        }

        public void onTrigger(View v, int target) {
            mTarget = target;
        }

        public void onFinishFinalAnimation() {
            if (mTarget != -1) {
                final int resId = mMultiWaveView.getResourceIdForTarget(mTarget);
                mTarget = -1; // a safety to make sure we never launch w/o prior call to onTrigger
        public void onTrigger(View v, final int target) {
            final int resId = mMultiWaveView.getResourceIdForTarget(target);
            switch (resId) {
                case com.android.internal.R.drawable.ic_lockscreen_search:
                    mWaitingForLaunch = true;
                    startAssistActivity();
                    postDelayed(new Runnable() {
                        public void run() {
                            mWaitingForLaunch = false;
                            mBar.hideSearchPanel();
                        }
                    }, SEARCH_PANEL_HOLD_DURATION);
                break;
            }
                mBar.hideSearchPanel();
        }

        public void onFinishFinalAnimation() {
        }
    };

@@ -194,15 +195,11 @@ public class SearchPanelView extends FrameLayout implements
    };

    public void show(final boolean show, boolean animate) {
        if (animate) {
            if (mShowing != show) {
                mShowing = show;
                // TODO: start animating ring
        if (!show) {
            final LayoutTransition transitioner = animate ? createLayoutTransitioner() : null;
            ((ViewGroup)mSearchTargetsContainer).setLayoutTransition(transitioner);
        }
        } else {
        mShowing = show;
            onAnimationEnd(null);
        }
        if (show) {
            if (getVisibility() != View.VISIBLE) {
                setVisibility(View.VISIBLE);
@@ -228,25 +225,6 @@ public class SearchPanelView extends FrameLayout implements
        }
    }

    public void onAnimationCancel(Animator animation) {
    }

    public void onAnimationEnd(Animator animation) {
        if (mShowing) {
            final LayoutTransition transitioner = new LayoutTransition();
            ((ViewGroup)mSearchTargetsContainer).setLayoutTransition(transitioner);
            createCustomAnimations(transitioner);
        } else {
            ((ViewGroup)mSearchTargetsContainer).setLayoutTransition(null);
        }
    }

    public void onAnimationRepeat(Animator animation) {
    }

    public void onAnimationStart(Animator animation) {
    }

    /**
     * We need to be aligned at the bottom.  LinearLayout can't do this, so instead,
     * let LinearLayout do all the hard work, and then shift everything down to the bottom.
@@ -293,9 +271,11 @@ public class SearchPanelView extends FrameLayout implements
        }
    }

    private void createCustomAnimations(LayoutTransition transitioner) {
    private LayoutTransition createLayoutTransitioner() {
        LayoutTransition transitioner = new LayoutTransition();
        transitioner.setDuration(200);
        transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
        transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
        return transitioner;
    }
}
Loading