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

Commit 6dcba895 authored by Sreyas's avatar Sreyas
Browse files

Refactoring DigitalWellbeing Banner to not use footers.

Removing use of footers as they are no longer necessary. Refactoring DWB code to a separate class to be cleaner. Also fixes bug with DWB animating in twice.

Bug: 171317883
Bug: 171317874
Tested:Manual

Change-Id: I78c4e541e7afa76301c3afc373ab3fa251a2c3b0
parent a1733bce
Loading
Loading
Loading
Loading
+72 −10
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.quickstep.views;

import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;

import static com.android.launcher3.Utilities.prefixTextWithIcon;
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
@@ -27,6 +29,7 @@ import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.AppUsageLimit;
import android.graphics.Outline;
import android.icu.text.MeasureFormat;
import android.icu.text.MeasureFormat.FormatWidth;
import android.icu.util.Measure;
@@ -35,6 +38,9 @@ import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.annotation.StringRes;
@@ -61,6 +67,10 @@ public final class DigitalWellBeingToast {
    private Task mTask;
    private boolean mHasLimit;
    private long mAppRemainingTimeMs;
    private View mBanner;
    private ViewOutlineProvider mOldBannerOutlineProvider;
    private float mBannerOffsetPercentage;
    private float mBannerAlpha = 1f;

    public DigitalWellBeingToast(BaseDraggingActivity activity, TaskView taskView) {
        mActivity = activity;
@@ -68,18 +78,10 @@ public final class DigitalWellBeingToast {
        mLauncherApps = activity.getSystemService(LauncherApps.class);
    }

    private void setTaskFooter(View view) {
        View oldFooter = mTaskView.setFooter(TaskView.INDEX_DIGITAL_WELLBEING_TOAST, view);
        if (oldFooter != null) {
            oldFooter.setOnClickListener(null);
            mActivity.getViewCache().recycleView(R.layout.digital_wellbeing_toast, oldFooter);
        }
    }

    private void setNoLimit() {
        mHasLimit = false;
        mTaskView.setContentDescription(mTask.titleDescription);
        setTaskFooter(null);
        replaceBanner(null);
        mAppRemainingTimeMs = 0;
    }

@@ -90,7 +92,7 @@ public final class DigitalWellBeingToast {
                mActivity, mTaskView);
        toast.setText(prefixTextWithIcon(mActivity, R.drawable.ic_hourglass_top, getText()));
        toast.setOnClickListener(this::openAppUsageSettings);
        setTaskFooter(toast);
        replaceBanner(toast);

        mTaskView.setContentDescription(
                getContentDescriptionForTask(mTask, appUsageLimitTimeMs, appRemainingTimeMs));
@@ -233,4 +235,64 @@ public final class DigitalWellBeingToast {
                        getText(appRemainingTimeMs)) :
                task.titleDescription;
    }

    private void replaceBanner(View view) {
        resetOldBanner();
        setBanner(view);
    }

    private void resetOldBanner() {
        if (mBanner != null) {
            mBanner.setOutlineProvider(mOldBannerOutlineProvider);
            mTaskView.removeView(mBanner);
            mBanner.setOnClickListener(null);
            mActivity.getViewCache().recycleView(R.layout.digital_wellbeing_toast, mBanner);
        }
    }

    private void setBanner(View view) {
        mBanner = view;
        if (view != null) {
            setupAndAddBanner();
            setBannerOutline();
        }
    }

    private void setupAndAddBanner() {
        FrameLayout.LayoutParams layoutParams =
                (FrameLayout.LayoutParams) mBanner.getLayoutParams();
        layoutParams.gravity = BOTTOM | CENTER_HORIZONTAL;
        layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams)
                mTaskView.getThumbnail().getLayoutParams()).bottomMargin;
        mBanner.setTranslationY(mBannerOffsetPercentage * mBanner.getHeight());
        mBanner.setAlpha(mBannerAlpha);
        mTaskView.addView(mBanner);
    }

    private void setBannerOutline() {
        mOldBannerOutlineProvider = mBanner.getOutlineProvider();
        mBanner.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                mOldBannerOutlineProvider.getOutline(view, outline);
                outline.offset(0, -Math.round(view.getTranslationY()));
            }
        });
        mBanner.setClipToOutline(true);
    }

    void updateBannerOffset(float offsetPercentage) {
        if (mBanner != null && mBannerOffsetPercentage != offsetPercentage) {
            mBannerOffsetPercentage = offsetPercentage;
            mBanner.setTranslationY(offsetPercentage * mBanner.getHeight());
            mBanner.invalidateOutline();
        }
    }

    void updateBannerAlpha(float alpha) {
        if (mBanner != null && mBannerAlpha != alpha) {
            mBannerAlpha = alpha;
            mBanner.setAlpha(alpha);
        }
    }
}
+5 −149
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
@@ -194,12 +193,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {

    private boolean mEndQuickswitchCuj;

    // Order in which the footers appear. Lower order appear below higher order.
    public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0;
    private final FooterWrapper[] mFooters = new FooterWrapper[2];
    private float mFooterVerticalOffset = 0;
    private float mFooterAlpha = 1;
    private int mStackHeight;
    private View mContextualChipWrapper;
    private View mContextualChip;
    private final float[] mIconCenterCoords = new float[2];
@@ -343,7 +336,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
        if (mContextualChipWrapper != null) {
            mContextualChipWrapper.setAlpha(comp(modalness));
        }
        updateFooterVerticalOffset(mFooterVerticalOffset);
        mDigitalWellBeingToast.updateBannerOffset(modalness);
    }

    public TaskMenuView getMenuView() {
@@ -567,7 +560,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
            mContextualChip.setScaleX(scale);
            mContextualChip.setScaleY(scale);
        }
        updateFooterVerticalOffset(1.0f - scale);
        mDigitalWellBeingToast.updateBannerOffset(1f - scale);
    }

    public void setIconScaleAnimStartProgress(float startProgress) {
@@ -639,12 +632,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
        mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
        setCurveScale(curveScaleForCurveInterpolation);

        mFooterAlpha = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation, 0f, 1f);
        for (FooterWrapper footer : mFooters) {
            if (footer != null) {
                footer.mView.setAlpha(mFooterAlpha);
            }
        }
        float dwbBannerAlpha = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation,
                0f, 1f);
        mDigitalWellBeingToast.updateBannerAlpha(dwbBannerAlpha);

        if (mMenuView != null) {
            PagedOrientationHandler pagedOrientationHandler = getPagedOrientationHandler();
@@ -656,57 +646,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
        }
    }

    /**
     * Sets the footer at the specific index and returns the previously set footer.
     */
    public View setFooter(int index, View view) {
        View oldFooter = null;

        // If the footer are is already collapsed, do not animate entry
        boolean shouldAnimateEntry = mFooterVerticalOffset <= 0;

        if (mFooters[index] != null) {
            oldFooter = mFooters[index].mView;
            mFooters[index].release();
            removeView(oldFooter);

            // If we are replacing an existing footer, do not animate entry
            shouldAnimateEntry = false;
        }
        if (view != null) {
            int indexToAdd = getChildCount();
            for (int i = index - 1; i >= 0; i--) {
                if (mFooters[i] != null) {
                    indexToAdd = indexOfChild(mFooters[i].mView);
                    break;
                }
            }

            addView(view, indexToAdd);
            LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
            layoutParams.gravity = BOTTOM | CENTER_HORIZONTAL;
            layoutParams.bottomMargin =
                    ((MarginLayoutParams) mSnapshotView.getLayoutParams()).bottomMargin;
            view.setAlpha(mFooterAlpha);
            mFooters[index] = new FooterWrapper(view);
            if (shouldAnimateEntry) {
                mFooters[index].animateEntry();
            }
        } else {
            mFooters[index] = null;
        }

        mStackHeight = 0;
        for (FooterWrapper footer : mFooters) {
            if (footer != null) {
                footer.setVerticalShift(mStackHeight);
                mStackHeight += footer.mExpectedHeight;
            }
        }

        return oldFooter;
    }

    /**
     * Sets the contextual chip.
     *
@@ -780,24 +719,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
            SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight());
            setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT);
        }

        mStackHeight = 0;
        for (FooterWrapper footer : mFooters) {
            if (footer != null) {
                mStackHeight += footer.mView.getHeight();
            }
        }
        updateFooterVerticalOffset(0);
    }

    private void updateFooterVerticalOffset(float offset) {
        mFooterVerticalOffset = offset;

        for (FooterWrapper footer : mFooters) {
            if (footer != null) {
                footer.updateFooterOffset();
            }
        }
    }

    public static float getCurveScaleForInterpolation(float linearInterpolation) {
@@ -860,71 +781,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
        }
    }

    private class FooterWrapper extends ViewOutlineProvider {

        final View mView;
        final ViewOutlineProvider mOldOutlineProvider;
        final ViewOutlineProvider mDelegate;

        final int mExpectedHeight;
        final int mOldPaddingBottom;

        int mAnimationOffset = 0;
        int mEntryAnimationOffset = 0;

        public FooterWrapper(View view) {
            mView = view;
            mOldOutlineProvider = view.getOutlineProvider();
            mDelegate = mOldOutlineProvider == null
                    ? ViewOutlineProvider.BACKGROUND : mOldOutlineProvider;

            mExpectedHeight = getExpectedViewHeight(view);
            mOldPaddingBottom = view.getPaddingBottom();

            if (mOldOutlineProvider != null) {
                view.setOutlineProvider(this);
                view.setClipToOutline(true);
            }
        }

        public void setVerticalShift(int shift) {
            mView.setPadding(mView.getPaddingLeft(), mView.getPaddingTop(),
                    mView.getPaddingRight(), mOldPaddingBottom + shift);
        }

        @Override
        public void getOutline(View view, Outline outline) {
            mDelegate.getOutline(view, outline);
            outline.offset(0, -mAnimationOffset - mEntryAnimationOffset);
        }

        void updateFooterOffset() {
            float offset = Utilities.or(mFooterVerticalOffset, mModalness);
            mAnimationOffset = Math.round(mStackHeight * offset);
            mView.setTranslationY(mAnimationOffset + mEntryAnimationOffset
                    + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom
                    + mCurrentFullscreenParams.mCurrentDrawnInsets.top);
            mView.invalidateOutline();
        }

        void release() {
            mView.setOutlineProvider(mOldOutlineProvider);
            setVerticalShift(0);
        }

        void animateEntry() {
            ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
            animator.addUpdateListener(anim -> {
               float factor = 1 - anim.getAnimatedFraction();
               int totalShift = mExpectedHeight + mView.getPaddingBottom() - mOldPaddingBottom;
                mEntryAnimationOffset = Math.round(factor * totalShift);
                updateFooterOffset();
            });
            animator.setDuration(100);
            animator.start();
        }
    }

    private int getExpectedViewHeight(View view) {
        int expectedHeight;
        int h = view.getLayoutParams().height;