1254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu/*
2254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * Copyright (C) 2015 The Android Open Source Project
3254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu *
4254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * in compliance with the License. You may obtain a copy of the License at
6254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu *
7254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
8254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu *
9254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
10254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
12254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu * the License.
13254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu */
14254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gupackage android.support.v17.leanback.widget;
15254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
16254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.content.Context;
17254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.content.res.Resources;
18254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.graphics.drawable.ColorDrawable;
19254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.graphics.drawable.Drawable;
20254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.support.v17.leanback.R;
21254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.support.v17.leanback.system.Settings;
22254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.view.ViewGroup;
23254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Guimport android.view.View;
24254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
25254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
26254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu/**
2785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * ShadowOverlayHelper is a helper class for shadow, overlay color and rounded corner.
2885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * There are many choices to implement Shadow, overlay color.
2985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * Initialize it with ShadowOverlayHelper.Builder and it decides the best strategy based
3085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * on options user choose and current platform version.
3185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *
324d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu * <li> For shadow:  it may use 9-patch with opticalBounds or Z-value based shadow for
334d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu *                   API >= 21.  When 9-patch is used, it requires a ShadowOverlayContainer
3485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *                   to include 9-patch views.
354d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu * <li> For overlay: it may use ShadowOverlayContainer which overrides draw() or it may
364d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu *                   use setForeground(new ColorDrawable()) for API>=23.  The foreground support
374d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu *                   might be disabled if rounded corner is applied due to performance reason.
384d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu * <li> For rounded-corner:  it uses a ViewOutlineProvider for API>=21.
3985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *
4085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * There are two different strategies: use Wrapper with a ShadowOverlayContainer;
4185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * or apply rounded corner, overlay and rounded-corner to the view itself.  Below is an example
4285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * of how helper is used.
4385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *
4485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * <code>
4585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * ShadowOverlayHelper mHelper = new ShadowOverlayHelper.Builder().
4685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         .needsOverlay(true).needsRoundedCorner(true).needsShadow(true)
4785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         .build();
4885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * mHelper.prepareParentForShadow(parentView); // apply optical-bounds for 9-patch shadow.
4985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * mHelper.setOverlayColor(view, Color.argb(0x80, 0x80, 0x80, 0x80));
5085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * mHelper.setShadowFocusLevel(view, 1.0f);
5185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * ...
5285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * View initializeView(View view) {
5385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *     if (mHelper.needsWrapper()) {
5485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         ShadowOverlayContainer wrapper = mHelper.createShadowOverlayContainer(context);
5585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         wrapper.wrap(view);
5685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         return wrapper;
5785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *     } else {
5885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         mHelper.onViewCreated(view);
5985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *         return view;
6085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *     }
6185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * }
6285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * ...
6385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu *
6485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu * </code>
65254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu */
66254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gupublic final class ShadowOverlayHelper {
67254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
68254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
6985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Builder for creating ShadowOverlayHelper.
7085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
7185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public static final class Builder {
7285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
7385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private boolean needsOverlay;
7485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private boolean needsRoundedCorner;
7585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private boolean needsShadow;
7685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private boolean preferZOrder = true;
7785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private boolean keepForegroundDrawable;
7885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private Options options = Options.DEFAULT;
7985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
8085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
8185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set if needs overlay color.
8285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param needsOverlay   True if needs overlay.
8385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return  The Builder object itself.
8485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
8585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder needsOverlay(boolean needsOverlay) {
8685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.needsOverlay = needsOverlay;
8785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
8885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
8985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
9085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
9185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set if needs shadow.
9285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param needsShadow   True if needs shadow.
9385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return  The Builder object itself.
9485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
9585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder needsShadow(boolean needsShadow) {
9685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.needsShadow = needsShadow;
9785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
9885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
9985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
10085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
10185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set if needs rounded corner.
10285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param needsRoundedCorner   True if needs rounded corner.
10385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return  The Builder object itself.
10485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
10585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder needsRoundedCorner(boolean needsRoundedCorner) {
10685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.needsRoundedCorner = needsRoundedCorner;
10785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
10885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
10985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
11085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
11185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set if prefer z-order shadow.  On old devices,  z-order shadow might be slow,
11285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * set to false to fall back to static 9-patch shadow.  Recommend to read
11385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * from system wide Setting value: see {@link Settings}.
11485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
11585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param preferZOrder   True if prefer Z shadow.  Default is true.
11685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return The Builder object itself.
11785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
11885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder preferZOrder(boolean preferZOrder) {
11985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.preferZOrder = preferZOrder;
12085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
12185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
12285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
12385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
12485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set if not using foreground drawable for overlay color.  For example if
12585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * the view has already assigned a foreground drawable for other purposes.
12685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * When it's true, helper will use a ShadowOverlayContainer for overlay color.
12785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
12885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param keepForegroundDrawable   True to keep the original foreground drawable.
12985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return The Builder object itself.
13085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
13185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder keepForegroundDrawable(boolean keepForegroundDrawable) {
13285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.keepForegroundDrawable = keepForegroundDrawable;
13385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
13485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
13585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
13685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
13785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set option values e.g. Shadow Z value, rounded corner radius.
13885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
13985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param options   The Options object to create ShadowOverlayHelper.
14085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
14185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Builder options(Options options) {
14285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.options = options;
14385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
14485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
14585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
14685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
14785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Create ShadowOverlayHelper object
14885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param context    The context uses to read Resources settings.
14985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return           The ShadowOverlayHelper object.
15085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
15185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public ShadowOverlayHelper build(Context context) {
15285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            final ShadowOverlayHelper helper = new ShadowOverlayHelper();
15385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            helper.mNeedsOverlay = needsOverlay;
15485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            helper.mNeedsRoundedCorner = needsRoundedCorner && supportsRoundedCorner();
15585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            helper.mNeedsShadow = needsShadow && supportsShadow();
15685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
15785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            if (helper.mNeedsRoundedCorner) {
15885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                helper.setupRoundedCornerRadius(options, context);
15985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            }
16085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
16185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            // figure out shadow type and if we need use wrapper:
16285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            if (helper.mNeedsShadow) {
163c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas                // if static shadow is preferred or dynamic shadow is not supported,
16485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                // use static shadow,  otherwise use dynamic shadow.
16585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                if (!preferZOrder || !supportsDynamicShadow()) {
16685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    helper.mShadowType = SHADOW_STATIC;
16785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    // static shadow requires ShadowOverlayContainer to support crossfading
16885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    // of two shadow views.
16985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    helper.mNeedsWrapper = true;
17085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                } else {
17185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    helper.mShadowType = SHADOW_DYNAMIC;
17285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    helper.setupDynamicShadowZ(options, context);
17385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    helper.mNeedsWrapper = ((!supportsForeground() || keepForegroundDrawable)
17485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                            && helper.mNeedsOverlay);
17585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                }
17685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            } else {
17785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                helper.mShadowType = SHADOW_NONE;
17885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                helper.mNeedsWrapper = ((!supportsForeground() || keepForegroundDrawable)
17985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                        && helper.mNeedsOverlay);
18085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            }
18185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
18285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return helper;
18385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
18485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
18585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
18685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
18785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
18885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Option values for ShadowOverlayContainer.
18985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
19085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public static final class Options {
19185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
19285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
19385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Default Options for values.
19485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
19585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public static final Options DEFAULT = new Options();
19685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
19785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private int roundedCornerRadius = 0; // 0 for default value
19885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private float dynamicShadowUnfocusedZ = -1; // < 0 for default value
19985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        private float dynamicShadowFocusedZ = -1;   // < 0 for default value
20085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
20185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set value of rounded corner radius.
20285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
20385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param roundedCornerRadius   Number of pixels of rounded corner radius.
20485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *                              Set to 0 to use default settings.
20585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return  The Options object itself.
20685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
20785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Options roundedCornerRadius(int roundedCornerRadius){
20885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.roundedCornerRadius = roundedCornerRadius;
20985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
21085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
21185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
21285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
21385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Set value of focused and unfocused Z value for shadow.
21485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
21585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @param unfocusedZ   Number of pixels for unfocused Z value.
216c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas         * @param focusedZ     Number of pixels for focused Z value.
21785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return  The Options object itself.
21885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
21985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public Options dynamicShadowZ(float unfocusedZ, float focusedZ){
22085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.dynamicShadowUnfocusedZ = unfocusedZ;
22185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            this.dynamicShadowFocusedZ = focusedZ;
22285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return this;
22385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
22485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
22585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
22685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Get radius of rounded corner in pixels.
22785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
22885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return Radius of rounded corner in pixels.
22985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
23085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public final int getRoundedCornerRadius() {
23185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return roundedCornerRadius;
23285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
23385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
23485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
23585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Get z value of shadow when a view is not focused.
23685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
23785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return Z value of shadow when a view is not focused.
23885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
23985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public final float getDynamicShadowUnfocusedZ() {
24085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return dynamicShadowUnfocusedZ;
24185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
24285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
24385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        /**
24485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * Get z value of shadow when a view is focused.
24585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         *
24685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         * @return Z value of shadow when a view is focused.
24785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu         */
24885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        public final float getDynamicShadowFocusedZ() {
24985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            return dynamicShadowFocusedZ;
25085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
25185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
25285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
25385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
254254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * No shadow.
255254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
256254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static final int SHADOW_NONE = 1;
257254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
258254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
259254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Shadows are fixed.
260254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
261254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static final int SHADOW_STATIC = 2;
262254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
263254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
264254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Shadows depend on the size, shape, and position of the view.
265254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
266254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static final int SHADOW_DYNAMIC = 3;
267254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
268254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    int mShadowType = SHADOW_NONE;
269254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    boolean mNeedsOverlay;
270254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    boolean mNeedsRoundedCorner;
271254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    boolean mNeedsShadow;
272254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    boolean mNeedsWrapper;
273254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
27485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    int mRoundedCornerRadius;
275254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    float mUnfocusedZ;
276254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    float mFocusedZ;
277254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
278254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
279254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Return true if the platform sdk supports shadow.
280254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
281254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static boolean supportsShadow() {
282254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return StaticShadowHelper.getInstance().supportsShadow();
283254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
284254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
285254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
286254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Returns true if the platform sdk supports dynamic shadows.
287254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
288254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static boolean supportsDynamicShadow() {
289254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return ShadowHelper.getInstance().supportsDynamicShadow();
290254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
291254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
292254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
293254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Returns true if the platform sdk supports rounded corner through outline.
294254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
295254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static boolean supportsRoundedCorner() {
296254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return RoundedRectHelper.supportsRoundedCorner();
297254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
298254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
299254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
300254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * Returns true if view.setForeground() is supported.
301254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
302254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public static boolean supportsForeground() {
303254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return ForegroundHelper.supportsForeground();
304254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
305254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
30685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /*
30785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * hide from external, should be only created by ShadowOverlayHelper.Options.
308254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
30985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    ShadowOverlayHelper() {
310254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
311254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
312254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
313254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * {@link #prepareParentForShadow(ViewGroup)} must be called on parent of container
314254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * before using shadow.  Depending on Shadow type, optical bounds might be applied.
315254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
316254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public void prepareParentForShadow(ViewGroup parent) {
317254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        if (mShadowType == SHADOW_STATIC) {
318254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            StaticShadowHelper.getInstance().prepareParent(parent);
319254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        }
320254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
321254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
322254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public int getShadowType() {
323254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return mShadowType;
324254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
325254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
326254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public boolean needsOverlay() {
327254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return mNeedsOverlay;
328254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
329254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
330254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public boolean needsRoundedCorner() {
331254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        return mNeedsRoundedCorner;
332254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
333254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
33485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
33585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Returns true if a "wrapper" ShadowOverlayContainer is needed.
33685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * When needsWrapper() is true,  call {@link #createShadowOverlayContainer(Context)}
33785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * to create the wrapper.
33885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
33985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public boolean needsWrapper() {
34085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        return mNeedsWrapper;
341254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
342254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
34385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
34485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Create ShadowOverlayContainer for this helper.
34585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * @param context   Context to create view.
34685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * @return          ShadowOverlayContainer.
34785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
34885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public ShadowOverlayContainer createShadowOverlayContainer(Context context) {
34985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (!needsWrapper()) {
35085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            throw new IllegalArgumentException();
35185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
35285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        return new ShadowOverlayContainer(context, mShadowType, mNeedsOverlay,
35385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
354254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
355254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
3564d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu    /**
35785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Set overlay color for view other than ShadowOverlayContainer.
35885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * See also {@link ShadowOverlayContainer#setOverlayColor(int)}.
3594d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu     */
36085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public static void setNoneWrapperOverlayColor(View view, int color) {
3614d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        Drawable d = ForegroundHelper.getInstance().getForeground(view);
3624d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        if (d instanceof ColorDrawable) {
3634d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu            ((ColorDrawable) d).setColor(color);
364254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        } else {
3654d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu            ForegroundHelper.getInstance().setForeground(view, new ColorDrawable(color));
366254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        }
367254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
368254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
369254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
37085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Set overlay color for view, it can be a ShadowOverlayContainer if needsWrapper() is true,
37185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * or other view type.
37285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
37385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public void setOverlayColor(View view, int color) {
37485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (needsWrapper()) {
37585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            ((ShadowOverlayContainer) view).setOverlayColor(color);
37685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        } else {
37785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            setNoneWrapperOverlayColor(view, color);
37885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
37985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
38085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
38185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
38285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Must be called when view is created for cases {@link #needsWrapper()} is false.
383254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     * @param view
384254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
385254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    public void onViewCreated(View view) {
38685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (!needsWrapper()) {
387254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            if (!mNeedsShadow) {
388254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                if (mNeedsRoundedCorner) {
38985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    RoundedRectHelper.getInstance().setClipToRoundedOutline(view,
39085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                            true, mRoundedCornerRadius);
391254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                }
392254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            } else {
393254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                if (mShadowType == SHADOW_DYNAMIC) {
394254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    Object tag = ShadowHelper.getInstance().addDynamicShadow(
39585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                            view, mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
396254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    view.setTag(R.id.lb_shadow_impl, tag);
397254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                }
398254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            }
399254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        }
400254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
401254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
402254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    /**
403ce4c2014042fe6e4723bab30741039848adcf4beDake Gu     * Set shadow focus level (0 to 1). 0 for unfocused, 1 for fully focused.
4044d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu     * This is for view other than ShadowOverlayContainer.
40585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * See also {@link ShadowOverlayContainer#setShadowFocusLevel(float)}.
406254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu     */
40785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public static void setNoneWrapperShadowFocusLevel(View view, float level) {
408c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas        setShadowFocusLevel(getNoneWrapperDynamicShadowImpl(view), SHADOW_DYNAMIC, level);
409254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
410254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu
41185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
412ce4c2014042fe6e4723bab30741039848adcf4beDake Gu     * Set shadow focus level (0 to 1). 0 for unfocused, 1 for fully focused.
41385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
41485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public void setShadowFocusLevel(View view, float level) {
41585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (needsWrapper()) {
41685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            ((ShadowOverlayContainer) view).setShadowFocusLevel(level);
41785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        } else {
418c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas            setShadowFocusLevel(getNoneWrapperDynamicShadowImpl(view), SHADOW_DYNAMIC, level);
41985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
42085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
42185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
42285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    void setupDynamicShadowZ(Options options, Context context) {
42385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (options.getDynamicShadowUnfocusedZ() < 0f) {
42485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            Resources res = context.getResources();
42585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mFocusedZ = res.getDimension(R.dimen.lb_material_shadow_focused_z);
42685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mUnfocusedZ = res.getDimension(R.dimen.lb_material_shadow_normal_z);
42785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        } else {
42885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mFocusedZ = options.getDynamicShadowFocusedZ();
42985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mUnfocusedZ = options.getDynamicShadowUnfocusedZ();
43085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
43185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
43285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
43385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    void setupRoundedCornerRadius(Options options, Context context) {
43485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        if (options.getRoundedCornerRadius() == 0) {
43585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            Resources res = context.getResources();
43685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mRoundedCornerRadius = res.getDimensionPixelSize(
43785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                        R.dimen.lb_rounded_rect_corner_radius);
43885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        } else {
43985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mRoundedCornerRadius = options.getRoundedCornerRadius();
44085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        }
44185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
44285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
443c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas    static Object getNoneWrapperDynamicShadowImpl(View view) {
44485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        return view.getTag(R.id.lb_shadow_impl);
44585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
44685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
447254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    static void setShadowFocusLevel(Object impl, int shadowType, float level) {
448254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        if (impl != null) {
449254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            if (level < 0f) {
450254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                level = 0f;
451254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            } else if (level > 1f) {
452254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                level = 1f;
453254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            }
454254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            switch (shadowType) {
455254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                case SHADOW_DYNAMIC:
456254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    ShadowHelper.getInstance().setShadowFocusLevel(impl, level);
457254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    break;
458254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                case SHADOW_STATIC:
459254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    StaticShadowHelper.getInstance().setShadowFocusLevel(impl, level);
460254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu                    break;
461254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu            }
462254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu        }
463254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu    }
464254b417129de2a8c5612826a152f8a26c8f1d0e8Dake Gu}
465