Android夜间模式的几种实现

2019-05-18 12:40:35

参考文章 Android夜间模式的几种实现  我更倾向于第三种,简单直接,快速



一、直接修改widget颜色,这种方式实现起来最简单,但需要每个控件都去修改,太过复杂。例如:

复制代码

    /**
     * 相应交互,修改控件颜色
     * @param view     */
    public void onMethod1Click(View view) {        if (view.getId() == R.id.btn_method1) {            int theme = NightModeUtils.getSwitchDayNightMode(this);
            NightModeUtils.setBackGroundColor(this, mRootView, theme);
            NightModeUtils.setTextColor(this, findViewById(R.id.text), theme);
            NightModeUtils.setDayNightMode(this, theme);
        }
    }

复制代码

NightModeUitls修改颜色方法

复制代码

    /**
     * 修改背景色
     * @param context
     * @param view
     * @param theme     */
    public static void setBackGroundColor(Context context, View view, int theme) {        int color = context.getResources().getColor(
                theme == THEME_SUN ? R.color.light_color : R.color.night_color);
        view.setBackgroundColor(color);
    }    /**
     * 修改文字色
     * @param context
     * @param view
     * @param theme     */
    public static void setTextColor(Context context, View view, int theme) {        int color = context.getResources().getColor(
                theme == THEME_SUN ? R.color.night_color : R.color.light_color);
        TextView textView = (TextView)view;
        textView.setTextColor(color);
    }

复制代码

二、通过修改Theme,更新应用主题。这种方法问题在于,需要重启Activity才能完成界面渲染。

在Activity中调用setContentView之前进行Theme设置:

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        NightModeUtils.onActivityCreateSetTheme(this);
        setContentView(R.layout.activity_main);
    }

 

NightModeUitls设置Theme方法:

复制代码

    /** Set the theme of the activity, according to the configuration. */
    public static void onActivityCreateSetTheme(Activity activity) {        int theme = getDayNightMode(activity);        switch (theme) {            case THEME_SUN:
                activity.setTheme(R.style.AppSunTheme);                break;            case THEME_NIGHT:
                activity.setTheme(R.style.AppNightTheme);                break;            default:                break;
        }
    }

复制代码

 

三、通过怎加一层遮光罩来实现。效果不是很理想。

通过WindowManager,将一个透明背景的TextView加到Activity主界面中。代码如下:

复制代码

    private void night() {        if (mNightView == null) {
            mNightView = new TextView(this);
            mNightView.setBackgroundColor(0xaa000000);
        }

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        lp.gravity = Gravity.BOTTOM;
        lp.y = 10;        try {
            mWindowManager.addView(mNightView, lp);
        } catch (Exception ex) {
        }
    }    private void day() {        try {
            mWindowManager.removeView(mNightView);
        } catch (Exception ex) {
        }
    }

复制代码

四、最后来看一下Dialog需要怎么实现夜间模式。

AlertDialog.Builder 有一个带style id参数的构造函数,我们就通过这个构造函数来实现Dialog主题的修改,从而达到夜间模式。

复制代码

    public static AlertDialog.Builder createBuilder(Context context) {        if (NightModeUtils.getDayNightMode(context) == NightModeUtils.THEME_SUN) {            return new AlertDialog.Builder(context);
        } else {            return new AlertDialog.Builder(context, R.style.NightDialog);
        }
    }

复制代码

我们通过如上方法来获取Builder,实现主题切换。其中R.style.NightDialog我采用如下方式:

    <style name="NightDialog" parent="android:Theme.Holo.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>

在android honeycomb之前的版本Theme.Dialog.Alert与AlertDialog这两个style是public的,可以通过修改主题时,重新定义这两个style实现dialog主题的修改,但之后的版本已经将他们开放关闭了。所以,我通过上面的办法实现了dialog的主题修改。


  • 2019-11-26 11:08:02

    多边型无序点排序(地图绘制多边形)

    任务需求要做一个区域高亮的功能,用到地图,想到了高德地图的多边形API,但是多边形顶点的顺序是要有序的,需求是无序,在API查找无果的情况下,只能手动实现点集合排序。

  • 2019-11-26 11:11:59

    正多边形的编程绘制(javascript)

    如何用程序来绘制正多边形? 在一般情况下,会使用 x = radius * Math.cos(angle), y = radius * Math.sin(angle) 来进行绘制,但这是关于x轴对称的,如果遇到正多边形的边数为奇数,而你又希望它是以y轴对称时,可按照下面的方法。

  • 2019-11-26 13:36:28

    Vue组件命名找不到的问题以及如何给vue组件命名

    首先,Vue 会将 template 中的内容插到 DOM 中,以方便解析标签。由于 HTML 标签不区分大小写,所以在生成的标签名都会转换为小写。例如,当你的 template 为 <MyComponent></MyComponent> 时,插入 DOM 后会被转换为 <mycomponent></mycomponent>。 然后,通过标签名寻找对应的自定义组件。匹配的优先顺序从高到低为:原标签名、camelCase化的标签名、PascalCase化的标签名。例如 <my-component>会依次匹配 my-component、myComponent、MyComponent。camelCase 和 PascalCase 的代码

  • 2019-11-28 11:00:35

    Vue子组件调用父组件的方法

    下面有三种方法,我自己重点推荐第一种,毕竟这种简单粗暴好用好理解,不过这个有一个弊端,再组件嵌套组件的时候,尤其是用第三方组件里面调用自己的子组件的时候,其实已经是孙子组件了,这个时候就要parent.parent。。。。,这样就不好了,我们就得考虑其他方法了,具体怎么判断是父组件,还是爷爷组件,我会单独出一篇文章讲述。

  • 2019-11-29 13:04:47

    计算一个多边形的重心点坐标(准确版)

    在之前的 《如何判断一个多边形是否合法》 一文中有提到,用无人机规划飞行路线前,往往需要框选一个多边形的区域。 而在地图控件上显示这个多边形区域时,往往会遇到这样一个需求:需要把所要测绘的多边形区域移动到地图中心。 实现这个需求的基本思路就是:获取到多边形区域的重心点坐标,然后利用地图控件的 setCenter方法,就可以把地图的显示中心移动到多边形区域重心了。那么问题来了,如何求出一个多边形的重心点坐标呢?