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

Commit db503683 authored by Matías Hernández's avatar Matías Hernández Committed by Android (Google) Code Review
Browse files

Merge "Animate the color transition (active<->inactive) in the mode header icon" into main

parents a2c65ece 115d29e8
Loading
Loading
Loading
Loading
+35 −27
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.settings.notification.modes;

import static com.google.common.base.Preconditions.checkNotNull;

import android.app.Flags;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -22,8 +24,8 @@ import android.view.ViewGroup;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -32,13 +34,15 @@ import com.android.settingslib.notification.modes.ZenIconLoader;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;

import java.util.function.Consumer;
import com.google.common.base.Objects;

import java.util.function.Function;

abstract class AbstractZenModeHeaderController extends AbstractZenModePreferenceController {

    private final DashboardFragment mFragment;
    private EntityHeaderController mHeaderController;
    private String mCurrentIconKey;

    AbstractZenModeHeaderController(
            @NonNull Context context,
@@ -53,27 +57,18 @@ abstract class AbstractZenModeHeaderController extends AbstractZenModePreference
        return Flags.modesApi() && Flags.modesUi();
    }

    protected void updateIcon(Preference preference, @NonNull ZenMode zenMode, int iconSizePx,
            Function<Drawable, Drawable> modeIconStylist,
            @Nullable Consumer<ImageView> iconViewCustomizer) {
        if (mFragment == null) {
            return;
        }
    protected void setUpHeader(PreferenceScreen screen, int iconSizePx) {
        LayoutPreference preference = checkNotNull(screen.findPreference(getPreferenceKey()));
        preference.setSelectable(false);

        if (mHeaderController == null) {
            final LayoutPreference pref = (LayoutPreference) preference;
            mHeaderController = EntityHeaderController.newInstance(
                    mFragment.getActivity(),
                    mFragment,
                    pref.findViewById(R.id.entity_header));
                    preference.findViewById(R.id.entity_header));
        }

        ImageView iconView = ((LayoutPreference) preference).findViewById(R.id.entity_header_icon);
        if (iconView != null) {
            if (iconViewCustomizer != null) {
                iconViewCustomizer.accept(iconView);
            }
        ImageView iconView = checkNotNull(preference.findViewById(R.id.entity_header_icon));
        ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams();
        if (layoutParams.width != iconSizePx || layoutParams.height != iconSizePx) {
            layoutParams.width = iconSizePx;
@@ -82,11 +77,24 @@ abstract class AbstractZenModeHeaderController extends AbstractZenModePreference
        }
    }

    protected void updateIcon(Preference preference, @NonNull ZenMode zenMode,
            Function<Drawable, Drawable> iconStylist, boolean isSelected) {

        ImageView iconView = checkNotNull(
                ((LayoutPreference) preference).findViewById(R.id.entity_header_icon));
        iconView.setSelected(isSelected);

        if (!Objects.equal(mCurrentIconKey, zenMode.getIconKey())) {
            mCurrentIconKey = zenMode.getIconKey();
            FutureUtil.whenDone(
                    zenMode.getIcon(mContext, ZenIconLoader.getInstance()),
                icon -> mHeaderController
                        .setIcon(modeIconStylist.apply(icon))
                        .done(/* rebindActions= */ false),
                    icon -> {
                        checkNotNull(mHeaderController)
                                .setIcon(iconStylist.apply(icon))
                                .done(/* rebindActions= */ false);
                        iconView.jumpDrawablesToCurrentState(); // Skip animation on first load.
                    },
                    mContext.getMainExecutor());
        }
    }
}
+35 −11
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.StateSet;
import android.view.Gravity;

import androidx.annotation.AttrRes;
@@ -65,20 +67,42 @@ class IconUtil {

    /**
     * Returns a variant of the supplied mode icon to be used as the header in the mode page. The
     * inner icon is 64x64 dp and it's contained in a 12-sided-cookie of 136dp diameter. It's
     * tinted with the "material secondary" color combination and the "selected" color variant
     * should be used for modes currently active.
     * mode icon is contained in a 12-sided-cookie. The color combination is "material secondary"
     * when unselected and "material primary" when selected; the switch between these two color sets
     * is animated with a cross-fade. The selected colors should be used when the mode is currently
     * active.
     */
    static Drawable makeModeHeader(@NonNull Context context, Drawable modeIcon) {
        return composeIcons(
                checkNotNull(context.getDrawable(R.drawable.ic_zen_mode_icon_cookie)),
                context.getColorStateList(R.color.modes_icon_selectable_background),
                context.getResources().getDimensionPixelSize(
                        R.dimen.zen_mode_header_size),
        Resources res = context.getResources();
        Drawable background = checkNotNull(context.getDrawable(R.drawable.ic_zen_mode_icon_cookie));
        @Px int outerSizePx = res.getDimensionPixelSize(R.dimen.zen_mode_header_size);
        @Px int innerSizePx = res.getDimensionPixelSize(R.dimen.zen_mode_header_inner_icon_size);

        Drawable base = composeIcons(
                background,
                Utils.getColorAttr(context,
                        com.android.internal.R.attr.materialColorSecondaryContainer),
                outerSizePx,
                modeIcon,
                context.getColorStateList(R.color.modes_icon_selectable_icon),
                context.getResources().getDimensionPixelSize(
                        R.dimen.zen_mode_header_inner_icon_size));
                Utils.getColorAttr(context,
                        com.android.internal.R.attr.materialColorOnSecondaryContainer),
                innerSizePx);

        Drawable selected = composeIcons(
                background,
                Utils.getColorAttr(context, com.android.internal.R.attr.materialColorPrimary),
                outerSizePx,
                modeIcon,
                Utils.getColorAttr(context, com.android.internal.R.attr.materialColorOnPrimary),
                innerSizePx);

        StateListDrawable result = new StateListDrawable();
        result.setEnterFadeDuration(res.getInteger(android.R.integer.config_mediumAnimTime));
        result.setExitFadeDuration(res.getInteger(android.R.integer.config_mediumAnimTime));
        result.addState(new int[] { android.R.attr.state_selected }, selected);
        result.addState(StateSet.WILD_CARD, base);
        result.setBounds(0, 0, outerSizePx, outerSizePx);
        return result;
    }

    /**
+9 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import android.content.Context;

import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -33,11 +34,17 @@ class ZenModeHeaderController extends AbstractZenModeHeaderController {
        super(context, key, fragment);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        setUpHeader(screen,
                mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_header_size));
    }

    @Override
    public void updateState(Preference preference, @NonNull ZenMode zenMode) {
        updateIcon(preference, zenMode,
                mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_header_size),
                icon -> IconUtil.makeModeHeader(mContext, icon),
                iconView -> iconView.setSelected(zenMode.isActive()));
                /* isSelected= */ zenMode.isActive());
    }
}
+9 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;

import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -33,12 +34,17 @@ class ZenModeIconPickerIconPreferenceController extends AbstractZenModeHeaderCon
        super(context, key, fragment);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        setUpHeader(screen, mContext.getResources().getDimensionPixelSize(
                R.dimen.zen_mode_icon_list_header_circle_diameter));
    }

    @Override
    void updateState(Preference preference, @NonNull ZenMode zenMode) {
        updateIcon(preference, zenMode,
                mContext.getResources().getDimensionPixelSize(
                        R.dimen.zen_mode_icon_list_header_circle_diameter),
                icon -> IconUtil.makeIconPickerHeader(mContext, icon),
                null);
                /* isSelected= */ false);
    }
}