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

Commit d6865ba5 authored by Matthew Ng's avatar Matthew Ng
Browse files

Merged KeyButtonDrawable with tint drawable and shadow drawable (1/2)

KeyButtonDrawable can now draw its own shadow and tint based on its dark
intensity, no more shadow drawables wrapped by dual layer drawable and
cross fading to change their intensities. Refactored and simplified code
to get the nav bar drawables. AnimatedVectorDrawables can be used however
only dark intensity tinting will work on it. Fixed the clipped shadow in
landscape.

Change-Id: I6e234857f7972974aae34d92c7047086782124f0
Fixes: 112105450
Test: look at nav bar and tap rotate suggestion button
parent a581ae4a
Loading
Loading
Loading
Loading
+2 −8
Original line number Original line Diff line number Diff line
@@ -262,16 +262,10 @@ public class ScreenPinningRequest implements View.OnClickListener {
            }
            }


            if (navigationBarView != null) {
            if (navigationBarView != null) {
                int dualToneDarkTheme = Utils.getThemeAttr(getContext(), R.attr.darkIconTheme);
                int dualToneLightTheme = Utils.getThemeAttr(getContext(), R.attr.lightIconTheme);
                Context lightContext = new ContextThemeWrapper(getContext(), dualToneLightTheme);
                Context darkContext = new ContextThemeWrapper(getContext(), dualToneDarkTheme);
                ((ImageView) mLayout.findViewById(R.id.screen_pinning_back_icon))
                ((ImageView) mLayout.findViewById(R.id.screen_pinning_back_icon))
                        .setImageDrawable(navigationBarView.getBackDrawable(lightContext,
                        .setImageDrawable(navigationBarView.getBackDrawable());
                                darkContext));
                ((ImageView) mLayout.findViewById(R.id.screen_pinning_home_icon))
                ((ImageView) mLayout.findViewById(R.id.screen_pinning_home_icon))
                        .setImageDrawable(navigationBarView.getHomeDrawable(lightContext,
                        .setImageDrawable(navigationBarView.getHomeDrawable());
                                darkContext));
            }
            }


            ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
            ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
+3 −10
Original line number Original line Diff line number Diff line
@@ -49,7 +49,6 @@ import android.content.res.Configuration;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.InputMethodService;
import android.os.Binder;
import android.os.Binder;
import android.os.Bundle;
import android.os.Bundle;
@@ -532,12 +531,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
        KeyButtonDrawable kbd = rotBtn.getImageDrawable();
        KeyButtonDrawable kbd = rotBtn.getImageDrawable();
        if (kbd == null) return;
        if (kbd == null) return;


        // The KBD and AVD is recreated every new valid suggestion because of style changes.
        AnimatedVectorDrawable animIcon = null;
        if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
            animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
        }

        // Clear any pending suggestion flag as it has either been nullified or is being shown
        // Clear any pending suggestion flag as it has either been nullified or is being shown
        mPendingRotationSuggestion = false;
        mPendingRotationSuggestion = false;
        if (getView() != null) getView().removeCallbacks(mCancelPendingRotationProposal);
        if (getView() != null) getView().removeCallbacks(mCancelPendingRotationProposal);
@@ -554,9 +547,9 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
            view.setAlpha(1f);
            view.setAlpha(1f);


            // Run the rotate icon's animation if it has one
            // Run the rotate icon's animation if it has one
            if (animIcon != null) {
            if (kbd.canAnimate()) {
                animIcon.reset();
                kbd.resetAnimation();
                animIcon.start();
                kbd.startAnimation();
            }
            }


            if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
            if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
+41 −85
Original line number Original line Diff line number Diff line
@@ -80,7 +80,6 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -124,14 +123,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav


    private KeyButtonDrawable mBackIcon;
    private KeyButtonDrawable mBackIcon;
    private KeyButtonDrawable mHomeDefaultIcon;
    private KeyButtonDrawable mHomeDefaultIcon;
    private KeyButtonDrawable mBackCarModeIcon;
    private KeyButtonDrawable mHomeCarModeIcon;
    private KeyButtonDrawable mRecentIcon;
    private KeyButtonDrawable mRecentIcon;
    private KeyButtonDrawable mDockedIcon;
    private KeyButtonDrawable mDockedIcon;
    private KeyButtonDrawable mImeIcon;
    private KeyButtonDrawable mImeIcon;
    private KeyButtonDrawable mMenuIcon;
    private KeyButtonDrawable mMenuIcon;
    private KeyButtonDrawable mAccessibilityIcon;
    private KeyButtonDrawable mAccessibilityIcon;
    private TintedKeyButtonDrawable mRotateSuggestionIcon;
    private KeyButtonDrawable mRotateSuggestionIcon;


    private GestureHelper mGestureHelper;
    private GestureHelper mGestureHelper;
    private final DeadZone mDeadZone;
    private final DeadZone mDeadZone;
@@ -461,62 +458,47 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
                && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
                && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
    }
    }


    private void updateCarModeIcons(Context ctx) {
        mBackCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_back_carmode);
        mHomeCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_home_carmode);
    }

    private void reloadNavIcons() {
    private void reloadNavIcons() {
        updateIcons(mContext, Configuration.EMPTY, mConfiguration);
        updateIcons(Configuration.EMPTY, mConfiguration);
    }
    }


    private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
    private void updateIcons(Configuration oldConfig, Configuration newConfig) {
        int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
        int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
        Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
        Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);

        final boolean orientationChange = oldConfig.orientation != newConfig.orientation;
        final boolean orientationChange = oldConfig.orientation != newConfig.orientation;
        final boolean densityChange = oldConfig.densityDpi != newConfig.densityDpi;
        final boolean densityChange = oldConfig.densityDpi != newConfig.densityDpi;
        final boolean dirChange = oldConfig.getLayoutDirection() != newConfig.getLayoutDirection();
        final boolean dirChange = oldConfig.getLayoutDirection() != newConfig.getLayoutDirection();


        if (orientationChange || densityChange) {
        if (orientationChange || densityChange) {
            mDockedIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_docked);
            mDockedIcon = getDrawable(R.drawable.ic_sysbar_docked);
            mHomeDefaultIcon = getHomeDrawable(lightContext, darkContext);
            mHomeDefaultIcon = getHomeDrawable();
        }
        }
        if (densityChange || dirChange) {
        if (densityChange || dirChange) {
            mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
            mRecentIcon = getDrawable(R.drawable.ic_sysbar_recent);
            mMenuIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_menu);
            mMenuIcon = getDrawable(R.drawable.ic_sysbar_menu);

            mAccessibilityIcon = getDrawable(lightContext, darkContext,
                    R.drawable.ic_sysbar_accessibility_button, false /* hasShadow */);


            mImeIcon = getDrawable(lightContext, darkContext, R.drawable.ic_ime_switcher_default,
            mAccessibilityIcon = getDrawable(R.drawable.ic_sysbar_accessibility_button,
                    false /* hasShadow */);
                    false /* hasShadow */);


            updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
            mImeIcon = getDrawable(R.drawable.ic_ime_switcher_default, false /* hasShadow */);


            if (ALTERNATE_CAR_MODE_UI) {
            updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
                updateCarModeIcons(ctx);
            }
        }
        }
        if (orientationChange || densityChange || dirChange) {
        if (orientationChange || densityChange || dirChange) {
            mBackIcon = getBackDrawable(lightContext, darkContext);
            mBackIcon = getBackDrawable();
        }
        }
    }
    }


    public KeyButtonDrawable getBackDrawable(Context lightContext, Context darkContext) {
    public KeyButtonDrawable getBackDrawable() {
        KeyButtonDrawable drawable = chooseNavigationIconDrawable(lightContext, darkContext,
        KeyButtonDrawable drawable = chooseNavigationIconDrawable(R.drawable.ic_sysbar_back,
                R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_quick_step);
                R.drawable.ic_sysbar_back_quick_step);
        orientBackButton(drawable);
        orientBackButton(drawable);
        return drawable;
        return drawable;
    }
    }


    public KeyButtonDrawable getHomeDrawable(Context lightContext, Context darkContext) {
    public KeyButtonDrawable getHomeDrawable() {
        final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
        final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
        KeyButtonDrawable drawable = quickStepEnabled
        KeyButtonDrawable drawable = quickStepEnabled
                ? getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home_quick_step)
                ? getDrawable(R.drawable.ic_sysbar_home_quick_step)
                : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home);
                : getDrawable(R.drawable.ic_sysbar_home);
        orientHomeButton(drawable);
        orientHomeButton(drawable);
        return drawable;
        return drawable;
    }
    }
@@ -549,33 +531,26 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        drawable.setRotation(mVertical ? 90 : 0);
        drawable.setRotation(mVertical ? 90 : 0);
    }
    }


    private KeyButtonDrawable chooseNavigationIconDrawable(Context lightContext,
    private KeyButtonDrawable chooseNavigationIconDrawable(@DrawableRes int icon,
            Context darkContext, @DrawableRes int icon, @DrawableRes int quickStepIcon) {
            @DrawableRes int quickStepIcon) {
        final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
        final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
        return quickStepEnabled
        return quickStepEnabled ? getDrawable(quickStepIcon) : getDrawable(icon);
                ? getDrawable(lightContext, darkContext, quickStepIcon)
                : getDrawable(lightContext, darkContext, icon);
    }
    }


    private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
    private KeyButtonDrawable getDrawable(@DrawableRes int icon) {
            @DrawableRes int icon) {
        return getDrawable(mContext, icon, true /* hasShadow */);
        return getDrawable(lightContext, darkContext, icon, true /* hasShadow */);
    }
    }


    private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
    private KeyButtonDrawable getDrawable(@DrawableRes int icon, boolean hasShadow) {
            @DrawableRes int icon, boolean hasShadow) {
        return getDrawable(mContext, icon, hasShadow);
        return KeyButtonDrawable.create(lightContext, lightContext.getDrawable(icon),
                darkContext.getDrawable(icon), hasShadow);
    }
    }


    private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon) {
    private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon, boolean hasShadow) {
        // Legacy image icons using a single image will not support shadows
        final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
        return KeyButtonDrawable.create(ctx, ctx.getDrawable(icon), null, false /* hasShadow */);
        final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
    }
        Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);

        Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
    private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
        return KeyButtonDrawable.create(lightContext, darkContext, icon, hasShadow);
            @ColorInt int lightColor, @ColorInt int darkColor) {
        return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
    }
    }


    @Override
    @Override
@@ -585,10 +560,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        super.setLayoutDirection(layoutDirection);
        super.setLayoutDirection(layoutDirection);
    }
    }


    private KeyButtonDrawable getBackIcon(boolean carMode) {
        return carMode ? mBackCarModeIcon : mBackIcon;
    }

    public void setNavigationIconHints(int hints) {
    public void setNavigationIconHints(int hints) {
        if (hints == mNavigationIconHints) return;
        if (hints == mNavigationIconHints) return;
        final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
        final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
@@ -626,9 +597,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        // to recent icon is not required.
        // to recent icon is not required.
        final boolean useAltBack =
        final boolean useAltBack =
                (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
                (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
        KeyButtonDrawable backIcon = getBackIcon(mUseCarModeUi);
        KeyButtonDrawable backIcon = mBackIcon;
        orientBackButton(backIcon);
        orientBackButton(backIcon);
        KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
        KeyButtonDrawable homeIcon = mHomeDefaultIcon;
        if (!mUseCarModeUi) {
        if (!mUseCarModeUi) {
            orientHomeButton(homeIcon);
            orientHomeButton(homeIcon);
        }
        }
@@ -845,31 +816,20 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        mRotateBtnStyle = style;
        mRotateBtnStyle = style;
        final Context ctx = getContext();
        final Context ctx = getContext();


        // Extract the dark and light tints
        final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
        final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
        Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
        Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
        final int lightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
        final int darkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);

        // Use the supplied style to set the icon's rotation parameters
        // Use the supplied style to set the icon's rotation parameters
        Context rotateContext = new ContextThemeWrapper(ctx, style);
        Context rotateContext = new ContextThemeWrapper(ctx, style);


        // Recreate the icon and set it if needed
        // Recreate the icon and set it if needed
        TintedKeyButtonDrawable priorIcon = mRotateSuggestionIcon;
        float previousIntensity = mRotateSuggestionIcon != null
                ? mRotateSuggestionIcon.getDarkIntensity() : 0;
        mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
        mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
                lightColor, darkColor);
                false /* hasShadow */);

        mRotateSuggestionIcon.setDarkIntensity(previousIntensity);
        // Apply any prior set dark intensity
        if (priorIcon != null && priorIcon.isDarkIntensitySet()) {
            mRotateSuggestionIcon.setDarkIntensity(priorIcon.getDarkIntensity());
        }


        if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
        if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
    }
    }


    public int setRotateButtonVisibility(final boolean visible) {
    public int setRotateButtonVisibility(boolean visible) {
        // Never show if a11y is visible
        // Never show if a11y is visible
        final boolean adjVisible = visible && !mShowAccessibilityButton;
        final boolean adjVisible = visible && !mShowAccessibilityButton;
        final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
        final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
@@ -881,13 +841,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        mShowRotateButton = visible;
        mShowRotateButton = visible;


        // Stop any active animations if hidden
        // Stop any active animations if hidden
        if (!visible) {
        if (!visible && mRotateSuggestionIcon.canAnimate()) {
            Drawable d = mRotateSuggestionIcon.getDrawable(0);
            mRotateSuggestionIcon.clearAnimationCallbacks();
            if (d instanceof AnimatedVectorDrawable) {
            mRotateSuggestionIcon.resetAnimation();
                AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d;
                avd.clearAnimationCallbacks();
                avd.reset();
            }
        }
        }


        // Hide/restore other button visibility, if necessary
        // Hide/restore other button visibility, if necessary
@@ -1082,7 +1038,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        super.onConfigurationChanged(newConfig);
        super.onConfigurationChanged(newConfig);
        boolean uiCarModeChanged = updateCarMode(newConfig);
        boolean uiCarModeChanged = updateCarMode(newConfig);
        updateTaskSwitchHelper();
        updateTaskSwitchHelper();
        updateIcons(getContext(), mConfiguration, newConfig);
        updateIcons(mConfiguration, newConfig);
        updateRecentsIcon();
        updateRecentsIcon();
        mRecentsOnboarding.onConfigurationChanged(newConfig);
        mRecentsOnboarding.onConfigurationChanged(newConfig);
        if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
        if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
+0 −242
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 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.systemui.statusbar.phone;


import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

/**
 * A drawable which adds shadow around a child drawable.
 */
public class ShadowKeyDrawable extends Drawable {
    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

    private final ShadowDrawableState mState;

    public ShadowKeyDrawable(Drawable d) {
        this(d, new ShadowDrawableState());
    }

    private ShadowKeyDrawable(Drawable d, ShadowDrawableState state) {
        mState = state;
        if (d != null) {
            mState.mBaseHeight = d.getIntrinsicHeight();
            mState.mBaseWidth = d.getIntrinsicWidth();
            mState.mChangingConfigurations = d.getChangingConfigurations();
            mState.mChildState = d.getConstantState();
        }
    }

    public void setRotation(float degrees) {
        if (mState.mRotateDegrees != degrees) {
            mState.mRotateDegrees = degrees;
            mState.mLastDrawnBitmap = null;
            invalidateSelf();
        }
    }

    public void setTranslationX(float x) {
        setTranslation(x, mState.mTranslationY);
    }

    public void setTranslationY(float y) {
        setTranslation(mState.mTranslationX, y);
    }

    public void setTranslation(float x, float y) {
        if (mState.mTranslationX != x || mState.mTranslationY != y) {
            mState.mTranslationX = x;
            mState.mTranslationY = y;
            mState.mLastDrawnBitmap = null;
            invalidateSelf();
        }
    }

    public void setShadowProperties(int x, int y, int size, int color) {
        if (mState.mShadowOffsetX != x || mState.mShadowOffsetY != y
                || mState.mShadowSize != size || mState.mShadowColor != color) {
            mState.mShadowOffsetX = x;
            mState.mShadowOffsetY = y;
            mState.mShadowSize = size;
            mState.mShadowColor = color;
            mState.mLastDrawnBitmap = null;
            invalidateSelf();
        }
    }

    public float getRotation() {
        return mState.mRotateDegrees;
    }

    public float getTranslationX() {
        return mState.mTranslationX;
    }

    public float getTranslationY() {
        return mState.mTranslationY;
    }

    @Override
    public void draw(Canvas canvas) {
        Rect bounds = getBounds();
        if (bounds.isEmpty()) {
            return;
        }

        // If no cache or previous cached bitmap is hardware/software acceleration does not match
        // the current canvas on draw then regenerate
        if (mState.mLastDrawnBitmap == null
                || mState.mIsHardwareBitmap != canvas.isHardwareAccelerated()) {
            mState.mIsHardwareBitmap = canvas.isHardwareAccelerated();
            regenerateBitmapCache();
        }
        canvas.drawBitmap(mState.mLastDrawnBitmap, null, bounds, mPaint);
    }

    @Override
    public void setTint(int tintColor) {
        super.setTint(tintColor);
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
        invalidateSelf();
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();
    }

    @Override
    public ConstantState getConstantState() {
        return mState;
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicHeight() {
        return mState.mBaseHeight;
    }

    @Override
    public int getIntrinsicWidth() {
        return mState.mBaseWidth;
    }

    @Override
    public boolean canApplyTheme() {
        return mState.canApplyTheme();
    }

    private void regenerateBitmapCache() {
        final int width = getIntrinsicWidth();
        final int height = getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.save();
        final float radians = (float) (mState.mRotateDegrees * Math.PI / 180);

        // Rotate canvas before drawing original drawable if no shadow
        if (mState.mShadowSize == 0) {
            canvas.rotate(mState.mRotateDegrees, width / 2, height / 2);
        }

        // Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
        final Drawable d = mState.mChildState.newDrawable().mutate();
        d.setBounds(0, 0, mState.mBaseWidth, mState.mBaseHeight);
        canvas.translate(mState.mTranslationX, mState.mTranslationY);
        d.draw(canvas);

        if (mState.mShadowSize > 0) {
            // Draws the shadow
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
            paint.setMaskFilter(new BlurMaskFilter(mState.mShadowSize, Blur.NORMAL));
            int[] offset = new int[2];

            final Bitmap shadow = bitmap.extractAlpha(paint, offset);

            paint.setMaskFilter(null);
            paint.setColor(mState.mShadowColor);
            bitmap.eraseColor(Color.TRANSPARENT);

            canvas.rotate(mState.mRotateDegrees, width / 2, height / 2);

            final float shadowOffsetX = (float) (Math.sin(radians) * mState.mShadowOffsetY
                    + Math.cos(radians) * mState.mShadowOffsetX) - mState.mTranslationX;
            final float shadowOffsetY = (float) (Math.cos(radians) * mState.mShadowOffsetY
                    - Math.sin(radians) * mState.mShadowOffsetX) - mState.mTranslationY;

            canvas.drawBitmap(shadow, offset[0] + shadowOffsetX, offset[1] + shadowOffsetY, paint);
            d.draw(canvas);
        }

        if (mState.mIsHardwareBitmap) {
            bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
        }

        mState.mLastDrawnBitmap = bitmap;
        canvas.restore();
    }

    private static class ShadowDrawableState extends ConstantState {
        int mChangingConfigurations;
        int mBaseWidth;
        int mBaseHeight;
        float mRotateDegrees;
        float mTranslationX;
        float mTranslationY;
        int mShadowOffsetX;
        int mShadowOffsetY;
        int mShadowSize;
        int mShadowColor;

        boolean mIsHardwareBitmap;
        Bitmap mLastDrawnBitmap;
        ConstantState mChildState;

        @Override
        public Drawable newDrawable() {
            return new ShadowKeyDrawable(null, this);
        }

        @Override
        public int getChangingConfigurations() {
            return mChangingConfigurations;
        }

        @Override
        public boolean canApplyTheme() {
            return true;
        }
    }
}
+332 −61

File changed.

Preview size limit exceeded, changes collapsed.

Loading