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

Commit fd3e2624 authored by Selim Cinek's avatar Selim Cinek
Browse files

Added the possibility to do custom animations for certain fields

The text of the single line version now doesn't animate over anymore.

Change-Id: Id41c1145cbb07254bff599b10d4d6df84689f797
parent 30e387dd
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ public class CrossFadeHelper {
        view.animate()
                .alpha(1f)
                .setDuration(ANIMATION_DURATION_LENGTH)
                .setInterpolator(PhoneStatusBar.ALPHA_IN);
                .setInterpolator(PhoneStatusBar.ALPHA_IN)
                .withEndAction(null);
        if (view.hasOverlappingRendering()) {
            view.animate().withLayer();
        }
+37 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ public class ViewTransformationHelper implements TransformableView {

    private final Handler mHandler = new Handler();
    private ArrayMap<Integer, View> mTransformedViews = new ArrayMap<>();
    private ArrayMap<Integer, CustomTransformation> mCustomTransformations = new ArrayMap<>();

    public void addTransformedView(int key, View transformedView) {
        mTransformedViews.put(key, transformedView);
@@ -44,6 +45,10 @@ public class ViewTransformationHelper implements TransformableView {
        mTransformedViews.clear();
    }

    public void setCustomTransformation(CustomTransformation transformation, int viewType) {
        mCustomTransformations.put(viewType, transformation);
    }

    @Override
    public TransformState getCurrentState(int fadingView) {
        View view = mTransformedViews.get(fadingView);
@@ -59,6 +64,13 @@ public class ViewTransformationHelper implements TransformableView {
        for (Integer viewType : mTransformedViews.keySet()) {
            TransformState ownState = getCurrentState(viewType);
            if (ownState != null) {
                CustomTransformation customTransformation = mCustomTransformations.get(viewType);
                if (customTransformation != null && customTransformation.transformTo(
                        ownState, notification, runnable)) {
                    ownState.recycle();
                    runnable = null;
                    continue;
                }
                TransformState otherState = notification.getCurrentState(viewType);
                if (otherState != null) {
                    boolean run = ownState.transformViewTo(otherState, runnable);
@@ -86,6 +98,12 @@ public class ViewTransformationHelper implements TransformableView {
        for (Integer viewType : mTransformedViews.keySet()) {
            TransformState ownState = getCurrentState(viewType);
            if (ownState != null) {
                CustomTransformation customTransformation = mCustomTransformations.get(viewType);
                if (customTransformation != null && customTransformation.transformFrom(
                        ownState, notification)) {
                    ownState.recycle();
                    continue;
                }
                TransformState otherState = notification.getCurrentState(viewType);
                if (otherState != null) {
                    ownState.transformViewFrom(otherState);
@@ -154,4 +172,23 @@ public class ViewTransformationHelper implements TransformableView {
            }
        }
    }

    public interface CustomTransformation {
        /**
         * Transform a state to the given view
         * @param ownState the state to transform
         * @param notification the view to transform to
         * @return whether a custom transformation is performed
         */
        boolean transformTo(TransformState ownState, TransformableView notification,
                Runnable endRunnable);

        /**
         * Transform to this state from the given view
         * @param ownState the state to transform to
         * @param notification the view to transform from
         * @return whether a custom transformation is performed
         */
        boolean transformFrom(TransformState ownState, TransformableView notification);
    }
}
+31 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.widget.TextView;
import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -69,6 +70,36 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout
        mTextView = (TextView) findViewById(R.id.notification_text);
        mInvertHelper = new ViewInvertHelper(this, NotificationPanelView.DOZE_ANIMATION_DURATION);
        mTransformationHelper = new ViewTransformationHelper();
        mTransformationHelper.setCustomTransformation(
                new ViewTransformationHelper.CustomTransformation() {
                    @Override
                    public boolean transformTo(TransformState ownState, TransformableView notification,
                            Runnable endRunnable) {
                        // We want to transform to the same y location as the title
                        TransformState otherState = notification.getCurrentState(
                                TRANSFORMING_VIEW_TITLE);
                        CrossFadeHelper.fadeOut(mTextView, endRunnable);
                        if (otherState != null) {
                            ownState.animateViewVerticalTo(otherState, endRunnable);
                            otherState.recycle();
                        }
                        return true;
                    }

                    @Override
                    public boolean transformFrom(TransformState ownState,
                            TransformableView notification) {
                        // We want to transform from the same y location as the title
                        TransformState otherState = notification.getCurrentState(
                                TRANSFORMING_VIEW_TITLE);
                        CrossFadeHelper.fadeIn(mTextView);
                        if (otherState != null) {
                            ownState.animateViewVerticalFrom(otherState);
                            otherState.recycle();
                        }
                        return true;
                    }
                }, TRANSFORMING_VIEW_TEXT);
        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, mTitleView);
        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView);
    }
+73 −0
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;

/**
 * Wraps a notification view inflated from a template.
@@ -41,6 +43,77 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp

    protected NotificationTemplateViewWrapper(Context ctx, View view) {
        super(ctx, view);
        mTransformationHelper.setCustomTransformation(
                new ViewTransformationHelper.CustomTransformation() {
                    @Override
                    public boolean transformTo(TransformState ownState,
                            TransformableView notification, final Runnable endRunnable) {
                        if (!(notification instanceof HybridNotificationView)) {
                            return false;
                        }
                        TransformState otherState = notification.getCurrentState(
                                TRANSFORMING_VIEW_TITLE);
                        CrossFadeHelper.fadeOut(mText, endRunnable);
                        if (otherState != null) {
                            int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
                            int[] ownPosition = ownState.getLaidOutLocationOnScreen();
                            mText.animate()
                                    .translationY((otherStablePosition[1]
                                            + otherState.getTransformedView().getHeight()
                                            - ownPosition[1]) * 0.33f)
                                    .setDuration(CrossFadeHelper.ANIMATION_DURATION_LENGTH)
                                    .setInterpolator(TransformState.FAST_OUT_SLOW_IN)
                                    .withEndAction(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (endRunnable != null) {
                                                endRunnable.run();
                                            }
                                            TransformState.setClippingDeactivated(mText,
                                                    false);
                                        }
                                    });
                            TransformState.setClippingDeactivated(mText, true);
                            otherState.recycle();
                        }
                        return true;
                    }

                    @Override
                    public boolean transformFrom(TransformState ownState,
                            TransformableView notification) {
                        if (!(notification instanceof HybridNotificationView)) {
                            return false;
                        }
                        TransformState otherState = notification.getCurrentState(
                                TRANSFORMING_VIEW_TITLE);
                        boolean isVisible = mText.getVisibility() == View.VISIBLE;
                        CrossFadeHelper.fadeIn(mText);
                        if (otherState != null) {
                            int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
                            int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
                            if (!isVisible) {
                                mText.setTranslationY((otherStablePosition[1]
                                        + otherState.getTransformedView().getHeight()
                                        - ownStablePosition[1]) * 0.33f);
                            }
                            mText.animate()
                                    .translationY(0)
                                    .setDuration(CrossFadeHelper.ANIMATION_DURATION_LENGTH)
                                    .setInterpolator(TransformState.FAST_OUT_SLOW_IN)
                                    .withEndAction(new Runnable() {
                                        @Override
                                        public void run() {
                                            TransformState.setClippingDeactivated(mText,
                                                    false);
                                        }
                                    });
                            TransformState.setClippingDeactivated(mText, true);
                            otherState.recycle();
                        }
                        return true;
                    }
                }, TRANSFORMING_VIEW_TEXT);
    }

    private void resolveTemplateViews(StatusBarNotification notification) {
+63 −15
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -35,10 +37,15 @@ import com.android.systemui.statusbar.ExpandableNotificationRow;
*/
public class TransformState {

    private static Pools.SimplePool<TransformState> sInstancePool = new Pools.SimplePool<>(40);
    private static final int ANIMATE_X = 0x1;
    private static final int ANIMATE_Y = 0x10;
    private static final int ANIMATE_ALL = ANIMATE_X | ANIMATE_Y;
    private static final int CLIP_CLIPPING_SET = R.id.clip_children_set_tag;
    private static final int CLIP_CHILDREN_TAG = R.id.clip_children_tag;
    private static final int CLIP_TO_PADDING = R.id.clip_to_padding_tag;
    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
    private static Pools.SimplePool<TransformState> sInstancePool = new Pools.SimplePool<>(40);

    protected View mTransformedView;
    private int[] mOwnPosition = new int[2];

@@ -59,15 +66,32 @@ public class TransformState {
        } else {
            CrossFadeHelper.fadeIn(mTransformedView);
        }
        animateViewFrom(otherState);
    }

    public void animateViewFrom(TransformState otherState) {
        animateViewFrom(otherState, ANIMATE_ALL);
    }

    public void animateViewVerticalFrom(TransformState otherState) {
        animateViewFrom(otherState, ANIMATE_Y);
    }

    private void animateViewFrom(TransformState otherState, int animationFlags) {
        final View transformedView = mTransformedView;
        // lets animate the positions correctly
        int[] otherPosition = otherState.getLocationOnScreen();
        int[] ownStablePosition = getLaidOutLocationOnScreen();
        mTransformedView.setTranslationX(otherPosition[0] - ownStablePosition[0]);
        mTransformedView.setTranslationY(otherPosition[1] - ownStablePosition[1]);
        mTransformedView.animate()
                .translationX(0)
                .translationY(0)
        if ((animationFlags & ANIMATE_X) != 0) {
            transformedView.setTranslationX(otherPosition[0] - ownStablePosition[0]);
            transformedView.animate().translationX(0);
        }
        if ((animationFlags & ANIMATE_Y) != 0) {
            transformedView.setTranslationY(otherPosition[1] - ownStablePosition[1]);
            transformedView.animate().translationY(0);
        }
        transformedView.animate()
                .setInterpolator(TransformState.FAST_OUT_SLOW_IN)
                .setDuration(CrossFadeHelper.ANIMATION_DURATION_LENGTH)
                .withEndAction(new Runnable() {
                    @Override
@@ -75,7 +99,7 @@ public class TransformState {
                        setClippingDeactivated(transformedView, false);
                    }
                });
        setClippingDeactivated(mTransformedView, true);
        setClippingDeactivated(transformedView, true);
    }

    /**
@@ -94,13 +118,34 @@ public class TransformState {
        } else {
            CrossFadeHelper.fadeOut(mTransformedView, endRunnable);
        }
        animateViewTo(otherState, endRunnable);
        return true;
    }

    public void animateViewTo(TransformState otherState, Runnable endRunnable) {
        animateViewTo(otherState, endRunnable, ANIMATE_ALL);
    }

    public void animateViewVerticalTo(TransformState otherState, Runnable endRunnable) {
        animateViewTo(otherState, endRunnable, ANIMATE_Y);
    }

    private void animateViewTo(TransformState otherState, final Runnable endRunnable,
            int animationFlags) {
        // lets animate the positions correctly
        int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
        int[] ownPosition = getLaidOutLocationOnScreen();
        final View transformedView = mTransformedView;
        mTransformedView.animate()
                .translationX(otherStablePosition[0] - ownPosition[0])
                .translationY(otherStablePosition[1] - ownPosition[1])
        if ((animationFlags & ANIMATE_X) != 0) {
            transformedView.animate()
                    .translationX(otherStablePosition[0] - ownPosition[0]);
        }
        if ((animationFlags & ANIMATE_Y) != 0) {
            transformedView.animate()
                    .translationY(otherStablePosition[1] - ownPosition[1]);
        }
        transformedView.animate()
                .setInterpolator(TransformState.FAST_OUT_SLOW_IN)
                .setDuration(CrossFadeHelper.ANIMATION_DURATION_LENGTH)
                .withEndAction(new Runnable() {
                    @Override
@@ -111,11 +156,10 @@ public class TransformState {
                        setClippingDeactivated(transformedView, false);
                    }
                });
        setClippingDeactivated(mTransformedView, true);
        return true;
        setClippingDeactivated(transformedView, true);
    }

    private void setClippingDeactivated(final View transformedView, boolean deactivated) {
    public static void setClippingDeactivated(final View transformedView, boolean deactivated) {
        ViewGroup view = (ViewGroup) transformedView.getParent();
        while (true) {
            ArraySet<View> clipSet = (ArraySet<View>) view.getTag(CLIP_CLIPPING_SET);
@@ -167,14 +211,14 @@ public class TransformState {
        }
    }

    private int[] getLaidOutLocationOnScreen() {
    public int[] getLaidOutLocationOnScreen() {
        int[] location = getLocationOnScreen();
        location[0] -= mTransformedView.getTranslationX();
        location[1] -= mTransformedView.getTranslationY();
        return location;
    }

    private int[] getLocationOnScreen() {
    public int[] getLocationOnScreen() {
        mTransformedView.getLocationOnScreen(mOwnPosition);
        return mOwnPosition;
    }
@@ -240,4 +284,8 @@ public class TransformState {
        }
        return new TransformState();
    }

    public View getTransformedView() {
        return mTransformedView;
    }
}