xamarin.android 沉浸式状态栏

    public class SystemBarTintManager
    {
        /**  
        * The default system bar tint color value.  
        */
        public static Color DEFAULT_TINT_COLOR = Color.Black;

        private static string sNavBarOverride;

        private SystemBarConfig mConfig;
        private bool mStatusBarAvailable;
        private bool mNavBarAvailable;
        private bool mStatusBarTintEnabled;
        private bool mNavBarTintEnabled;
        private View mStatusBarTintView;
        private View mNavBarTintView;
        private Activity activity;


        static SystemBarTintManager()
        {
            // Android allows a system property to override the presence of the navigation bar.
            // Used by the emulator.
            // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            {
                try
                {
                    Class c = Class.ForName("android.os.SystemProperties");
                    Method m = c.GetDeclaredMethod("get");
                    m.Accessible = true;
                    sNavBarOverride = (string)m.Invoke(null, "qemu.hw.mainkeys");
                }
                catch (Throwable)
                {
                    sNavBarOverride = null;
                }
            }
        }

            /// <summary>
            /// Constructor. Call this in the host activity onCreate method after its  
            /// content view has been set.You should always create new instances when  
            /// the host activity is recreated.
            ///
            /// @param activity The host activity.
            /// </summary>
            /// <param name="activity"></param>
            [TargetApi(Value =19)]
            public SystemBarTintManager(Activity activity)
            {
                this.activity = activity;
                Window win = activity.Window;
                ViewGroup decorViewGroup = (ViewGroup)win.DecorView;

                if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
                {
                    // check theme attrs
                    int[] attrs = {Android.Resource.Attribute.WindowTranslucentStatus,
                                    Android.Resource.Attribute.WindowTranslucentNavigation};
                    TypedArray a = activity.ObtainStyledAttributes(attrs);
                    try
                    {
                        mStatusBarAvailable = a.GetBoolean(0, false);
                        mNavBarAvailable = a.GetBoolean(1, false);
                    }
                    finally
                    {
                        a.Recycle();
                    }
                    
                    // check window flags  
                    WindowManagerLayoutParams winParams = win.Attributes;
                    if ((winParams.Flags & WindowManagerFlags.TranslucentStatus) != 0)
                    {
                        mStatusBarAvailable = true;
                    }
                    if ((winParams.Flags & WindowManagerFlags.TranslucentNavigation) != 0)
                    {
                        mNavBarAvailable = true;
                    }
                }

                mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
                // device might not have virtual navigation keys  
                if (!mConfig.hasNavigtionBar())
                {
                    mNavBarAvailable = false;
                }

                if (mStatusBarAvailable)
                {
                    setupStatusBarView(activity, decorViewGroup);
                }
                if (mNavBarAvailable)
                {
                    setupNavBarView(activity, decorViewGroup);
                }
            }

            /**  
             * Enable tinting of the system status bar.  
             *  
             * If the platform is running Jelly Bean or earlier, or translucent system  
             * UI modes have not been enabled in either the theme or via window flags,  
             * then this method does nothing.  
             *  
             * @param enabled True to enable tinting, false to disable it (default).  
             */
            public void setStatusBarTintEnabled(bool enabled)
            {
                mStatusBarTintEnabled = enabled;
                if (mStatusBarAvailable)
                {
                    mStatusBarTintView.Visibility = enabled ? ViewStates.Visible : ViewStates.Gone;
                }
            }

            /**  
             * Enable tinting of the system navigation bar.  
             *  
             * If the platform does not have soft navigation keys, is running Jelly Bean  
             * or earlier, or translucent system UI modes have not been enabled in either  
             * the theme or via window flags, then this method does nothing.  
             *  
             * @param enabled True to enable tinting, false to disable it (default).  
             */
            public void setNavigationBarTintEnabled(bool enabled)
            {
                mNavBarTintEnabled = enabled;
                if (mNavBarAvailable)
                {
                    mNavBarTintView.Visibility=enabled ? ViewStates.Visible : ViewStates.Gone;
                }
            }

            /**  
             * Apply the specified color tint to all system UI bars.  
             *  
             * @param color The color of the background tint.  
             */
            public void setTintColor(Color color)
            {
                setStatusBarTintColor(color);
                setNavigationBarTintColor(color);
            }

            /**  
             * Apply the specified drawable or color resource to all system UI bars.  
             *  
             * @param res The identifier of the resource.  
             */
            public void setTintResource(int res)
            {
                setStatusBarTintResource(res);
                setNavigationBarTintResource(res);
            }

            /**  
             * Apply the specified drawable to all system UI bars.  
             *  
             * @param drawable The drawable to use as the background, or null to remove it.  
             */
            public void setTintDrawable(Drawable drawable)
            {
                setStatusBarTintDrawable(drawable);
                setNavigationBarTintDrawable(drawable);
            }

            /**  
             * Apply the specified alpha to all system UI bars.  
             *  
             * @param alpha The alpha to use  
             */
            public void setTintAlpha(float alpha)
            {
                setStatusBarAlpha(alpha);
                setNavigationBarAlpha(alpha);
            }

            /**  
             * Apply the specified color tint to the system status bar.  
             *  
             * @param color The color of the background tint.  
             */
            public void setStatusBarTintColor(Color color)
            {
                if (mStatusBarAvailable)
                {
                    mStatusBarTintView.SetBackgroundColor(color);
                }
            }

            /**  
             * Apply the specified drawable or color resource to the system status bar.  
             *  
             * @param res The identifier of the resource.  
             */
            public void setStatusBarTintResource(int res)
            {
                if (mStatusBarAvailable)
                {
                    mStatusBarTintView.SetBackgroundResource(res);
                }
            }

            /**  
             * Apply the specified drawable to the system status bar.  
             *  
             * @param drawable The drawable to use as the background, or null to remove it.  
             */
            [SuppressWarnings(Value =new[] { "deprecation" })]
            public void setStatusBarTintDrawable(Drawable drawable)
            {
                if (mStatusBarAvailable)
                {
                    mStatusBarTintView.SetBackgroundDrawable(drawable);
                }
            }

            /**  
             * Apply the specified alpha to the system status bar.  
             *  
             * @param alpha The alpha to use  
             */
            [TargetApi( Value = 11)]
            public void setStatusBarAlpha(float alpha)
            {
                if (mStatusBarAvailable &&  Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
                {
                   mStatusBarTintView.Alpha = alpha;
                }
            }

            /**  
             * Apply the specified color tint to the system navigation bar.  
             *  
             * @param color The color of the background tint.  
             */
            public void setNavigationBarTintColor(Color color)
            {
                if (mNavBarAvailable)
                {
                    mNavBarTintView.SetBackgroundColor(color);
                }
            }

            /**  
             * Apply the specified drawable or color resource to the system navigation bar.  
             *  
             * @param res The identifier of the resource.  
             */
            public void setNavigationBarTintResource(int res)
            {
                if (mNavBarAvailable)
                    mNavBarTintView.SetBackgroundResource(res);
            }
            /**  
             * Apply the specified drawable to the system navigation bar.  
             *  
             * @param drawable The drawable to use as the background, or null to remove it.  
             */
            [SuppressWarnings( Value = new string[] { "deprecation" })]
            public void setNavigationBarTintDrawable(Drawable drawable)
            {
                if (mNavBarAvailable)
                {
                    mNavBarTintView.SetBackgroundDrawable(drawable);
                }
            }

            /**  
             * Apply the specified alpha to the system navigation bar.  
             *  
             * @param alpha The alpha to use  
             */
            [TargetApi(Value = 11)]
            public void setNavigationBarAlpha(float alpha)
            {
                if (mNavBarAvailable && Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
                {
                    mNavBarTintView.Alpha=alpha;
                }
            }

            /**  
             * Get the system bar configuration.  
             *  
             * @return The system bar configuration for the current device configuration.  
             */
            public SystemBarConfig getConfig()
            {
                return mConfig;
            }

            /**  
             * Is tinting enabled for the system status bar?  
             *  
             * @return True if enabled, False otherwise.  
             */
            public bool isStatusBarTintEnabled()
            {
                return mStatusBarTintEnabled;
            }

            /**  
             * Is tinting enabled for the system navigation bar?  
             *  
             * @return True if enabled, False otherwise.  
             */
            public bool isNavBarTintEnabled()
            {
                return mNavBarTintEnabled;
            }

            private void setupStatusBarView(Context context, ViewGroup decorViewGroup)
            {
                mStatusBarTintView = new View(context);
                LayoutParams param = new LayoutParams(LayoutParams.MatchParent, mConfig.getStatusBarHeight());
                param.Gravity = GravityFlags.Top;
                if (mNavBarAvailable && !mConfig.isNavigationAtBottom())
                {
                    param.RightMargin = mConfig.getNavigationBarWidth();
                }
                mStatusBarTintView.LayoutParameters = param;
                mStatusBarTintView.SetBackgroundColor(DEFAULT_TINT_COLOR);
                mStatusBarTintView.Visibility = ViewStates.Gone;

            decorViewGroup.AddView(mStatusBarTintView);

            var view = getRootView(activity);
                view.SetPadding(0, Tool.dip2px(context, 73), 0, 0);
            }

            private static View getRootView(Activity context)
            {
                return context.FindViewById(Android.Resource.Id.Content);
            }

            private void setupNavBarView(Context context, ViewGroup decorViewGroup)
            {
                mNavBarTintView = new View(context);
                LayoutParams param = null;
                if (mConfig.isNavigationAtBottom())
                {
                    param = new LayoutParams(LayoutParams.MatchParent, mConfig.getNavigationBarHeight());
                    param.Gravity = GravityFlags.Bottom;
                }
                else
                {
                    param = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MatchParent);
                    param.Gravity = GravityFlags.Right;
                }
                mNavBarTintView.LayoutParameters=param;
                mNavBarTintView.SetBackgroundColor(DEFAULT_TINT_COLOR);
                mNavBarTintView.Visibility= ViewStates.Gone;
                decorViewGroup.AddView(mNavBarTintView);
            }


           /// <summary>
           /// Class which describes system bar sizing and other characteristics for the current  
           /// device configuration.
           /// </summary>
            public class SystemBarConfig
            {

                private static string STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
                private static string NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
                private static string NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
                private static string NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
                private static string SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";

                private bool mTranslucentStatusBar;
                private bool mTranslucentNavBar;
                private int mStatusBarHeight;
                private int mActionBarHeight;
                private bool mHasNavigationBar;
                private int mNavigationBarHeight;
                private int mNavigationBarWidth;
                private bool mInPortrait;
                private float mSmallestWidthDp;

                public SystemBarConfig(Activity activity, bool translucentStatusBar, bool traslucentNavBar)
                {
                    Resources res = activity.Resources;
                    mInPortrait = (res.Configuration.Orientation == Android.Content.Res.Orientation.Portrait);
                    mSmallestWidthDp = getSmallestWidthDp(activity);
                    mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
                    mActionBarHeight = getActionBarHeight(activity);
                    mNavigationBarHeight = getNavigationBarHeight(activity);
                    mNavigationBarWidth = getNavigationBarWidth(activity);
                    mHasNavigationBar = (mNavigationBarHeight > 0);
                    mTranslucentStatusBar = translucentStatusBar;
                    mTranslucentNavBar = traslucentNavBar;
                }


                [TargetApi(Value = 14)]
                private int getActionBarHeight(Context context)
                {
                    int result = 0;
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.IceCreamSandwich)
                    {
                        TypedValue tv = new TypedValue();
                        context.Theme.ResolveAttribute(Android.Resource.Attribute.ActionBarSize, tv, true);
                        result = TypedValue.ComplexToDimensionPixelSize(tv.Data, context.Resources.DisplayMetrics);
                    }
                    return result;
                }


                [TargetApi(Value = 14)]
                private int getNavigationBarHeight(Context context)
                {
                    Resources res = context.Resources;
                    int result = 0;
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.IceCreamSandwich)
                    {
                        if (hasNavBar(context))
                        {
                            string key;
                            if (mInPortrait)
                            {
                                key = NAV_BAR_HEIGHT_RES_NAME;
                            }
                            else
                            {
                                key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
                            }
                            return getInternalDimensionSize(res, key);
                        }
                    }
                    return result;
                }


                [TargetApi(Value = 14)]
                private int getNavigationBarWidth(Context context)
                {
                    Resources res = context.Resources;
                    int result = 0;
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.IceCreamSandwich)
                    {
                        if (hasNavBar(context))
                        {
                            return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
                        }
                    }
                    return result;
                }


                [TargetApi(Value = 14)]
                private bool hasNavBar(Context context)
                {
                    Resources res = context.Resources;
                    int resourceId = res.GetIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
                    if (resourceId != 0)
                    {
                        bool hasNav = res.GetBoolean(resourceId);
                        // check override flag (see static block)  
                        if ("1".Equals(sNavBarOverride))
                        {
                            hasNav = false;
                        }
                        else if ("0".Equals(sNavBarOverride))
                        {
                            hasNav = true;
                        }
                        return hasNav;
                    }
                    else
                    { // fallback  
                        return !ViewConfiguration.Get(context).HasPermanentMenuKey;
                    }
                }

                private int getInternalDimensionSize(Resources res, string key)
                {
                    int result = 0;
                    int resourceId = res.GetIdentifier(key, "dimen", "android");
                    if (resourceId > 0)
                    {
                        result = res.GetDimensionPixelSize(resourceId);
                    }
                    return result;
                }


                [SuppressLint(Value = new string[] { "NewApi" })]
                private float getSmallestWidthDp(Activity activity)
                {
                    DisplayMetrics metrics = new DisplayMetrics();
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
                    {
                        activity.WindowManager.DefaultDisplay.GetRealMetrics(metrics);
                    }
                    else
                    {
                        // TODO this is not correct, but we don't really care pre-kitkat  
                        activity.WindowManager.DefaultDisplay.GetMetrics(metrics);
                    }
                    float widthDp = metrics.WidthPixels / metrics.Density;
                    float heightDp = metrics.HeightPixels / metrics.Density;
                    return Java.Lang.Math.Min(widthDp, heightDp);
            }

            /// <summary>
            /// * Should a navigation bar appear at the bottom of the screen in the current  
            ///   * device configuration? A navigation bar may appear on the right side of  
            ///   * the screen in certain configurations.
            ///   *  
            ///   * @return True if navigation should appear at the bottom of the screen, False otherwise.  
            /// </summary>
            /// <returns></returns>
            public bool isNavigationAtBottom()
            {
                return (mSmallestWidthDp >= 600 || mInPortrait);
            }

            /**  
            * Get the height of the system status bar.  
            *  
            * @return The height of the status bar (in pixels).  
            */
            public int getStatusBarHeight()
            {
                return mStatusBarHeight;
            }

            /**  
            * Get the height of the action bar.  
            *  
            * @return The height of the action bar (in pixels).  
            */
            public int getActionBarHeight()
            {
                return mActionBarHeight;
            }

            /**  
            * Does this device have a system navigation bar?  
            *  
            * @return True if this device uses soft key navigation, False otherwise.  
            */
            public bool hasNavigtionBar()
            {
                return mHasNavigationBar;
            }

            /**  
            * Get the height of the system navigation bar.  
            *  
            * @return The height of the navigation bar (in pixels). If the device does not have  
            * soft navigation keys, this will always return 0.  
            */
            public int getNavigationBarHeight()
            {
                return mNavigationBarHeight;
            }

            /**  
            * Get the width of the system navigation bar when it is placed vertically on the screen.  
            *  
            * @return The nbsp;width of the navigation bar (in pixels). If the device does not have  
            * soft navigation keys, this will always return 0.  
            */
            public int getNavigationBarWidth()
            {
                return mNavigationBarWidth;
            }

            /**  
            * Get the layout inset for any system UI that appears at the top of the screen.  
            *  
            * @param withActionBar True to include the height of the action bar, False otherwise.  
            * @return The layout inset (in pixels).  
            */
            public int getPixelInsetTop(bool withActionBar)
            {
                return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
            }

            /**  
            * Get the layout inset for any system UI that appears at the bottom of the screen.  
            *  
            * @return The layout inset (in pixels).  
            */
            public int getPixelInsetBottom()
            {
                if (mTranslucentNavBar && isNavigationAtBottom())
                {
                    return mNavigationBarHeight;
                }
                else
                {
                    return 0;
                }
            }

            /**  
            * Get the layout inset for any system UI that appears at the right of the screen.  
            *  
            * @return The layout inset (in pixels).  
            */
            public int getPixelInsetRight()
            {
                if (mTranslucentNavBar && !isNavigationAtBottom())
                {
                    return mNavigationBarWidth;
                }
                else
                {
                    return 0;
                }
            }
         }
    }
 protected override void OnCreate(Bundle savedInstanceState)
 {
            /*状态栏沉浸效果*/
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
                setTranslucentStatus(this, true);
            SystemBarTintManager tintManager = new SystemBarTintManager(this);
            tintManager.setStatusBarTintEnabled(true);
            // 使用颜色资源
            tintManager.setStatusBarTintResource(Resource.Color.main_color);

            base.OnCreate(savedInstanceState);
 }

 

      [TargetApi(Value = 19)]
        private static void setTranslucentStatus(Activity activity, bool on)
        {
            Window win = activity.Window;
            WindowManagerLayoutParams winParams = win.Attributes;
            if (on)
                winParams.Flags = WindowManagerFlags.TranslucentStatus;
            else
                winParams.Flags &= ~WindowManagerFlags.TranslucentStatus;

            win.Attributes = winParams;
        }

 

posted @ 2016-07-11 14:29  mycing  阅读(1080)  评论(0编辑  收藏  举报