/** * 相应交互,修改控件颜色 * @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) { } } 此方法记得提取出来作为一个工具来用不要在像Activity这样有生命周期的东东里乱写东西,不然莫名其妙的被销毁,然后新建,
但早已经是物是人非,最后就是状态异常、空指针各种Crash各种坑。
我们要实现的效果是:点击显示Button-addView,点击消除Button-removeView,
我想removeView可是想在哪就在哪,随心所欲,游离于Activity的生命周期之外~
直接上代码,将WindowManager抽离出来即可,一个小Demo:
首先添加相应权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> public class Windowutils { private static WindowManager mWindowManager; private static View mNightView; public static void showWindow(Context context) { mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mNightView = new View(context); 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); mNightView.setBackgroundColor(0xaa000000); mWindowManager.addView(mNightView, lp); } public static void removeWindow() { // TODO Auto-generated method stub if(mWindowManager==null||mNightView==null){ return; } mWindowManager.removeViewImmediate(mNightView); } }
四、最后来看一下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的主题修改。