
夜间模式代码
public void night() {WindowManager.LayoutParams params = new WindowManager.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,LayoutParams.TYPE_APPLICATION,WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);params.gravity=Gravity.BOTTOM;params.y=10;if(myView==null){myView=new TextView(this);myView.setBackgroundColor(0x80000000);}mWindowManager.addView(myView, params);Editor edit = skinSp.edit();edit.putString("skin", NIGHT);edit.commit();}白天模式public void day(){if(myView!=null){mWindowManager.removeView(myView);Editor edit = skinSp.edit();edit.putString("skin", DAY);edit.commit();}}下面通过实例操作来详细展示如何进行Android主题切换中的白天/夜间模式。

上述两幅图片,正是两款App的夜间模式效果,所以,依据这个功能,来看看切换主题到底是怎么实现的(当然现在github有好多PluginTheme开源插件,很多时候可以使用这些插件,不过我并不想讲怎么用那些插件,正所谓会用轮子还不如会造轮子)。
关于更换主题和换肤
这里提到是做换主题功能,当然与之类似的就是换肤,换肤现在比较流行的是采用插件化动态加载技术来实现的,这样可以起到热插拔作用,需要皮肤时候用户自主的在网上下载便是了,不用皮肤时便删了皮肤插件包而不会影响宿主App的功能,这样就不必把一大堆皮肤图片放在本地而增加apk的大小,关于用插件化实现换肤功能这仅仅是插件化技术的冰山一角,关于插件化技术更多的作用,可以看看360前两天开源的 DroidPlugin插件框架、OpenAltas框架、还有主席的DL框架。
好了,言归正传,现在我们需要实现的是主题切换功能,关于主题切换其实是切换整个App的颜色风格、排版风格、字体风格等,其中并不会有过多的图片资源的切换,如有过多的图片的更换那就是换肤的功能了。
现在我们要实现夜间/白天模式的切换功能,如下效果图:

可以看到上面的效果正是夜间和白天两种模式的切换功能,切换至夜间模式时整个App的背景色、字体颜色、按钮颜色、标题栏颜色等全部需要切为夜间模式的颜色,当切回白天模式又切回原来的颜色,来看看怎么做的?
实现主题切换
首先就是需要在app中准备两套主题:
白天主题
<resources><style name="DayTheme" parent="Theme.AppCompat.Light.DarkActionBar"><!-- Customize your theme here. --><item name="colorPrimary">#03A9F4</item><item name="android:textColorPrimary">#ffffff</item><item name="android:windowBackground">@color/background_material_light</item><item name="colorAccent">#00BCD4</item><item name="colorControlNormal">#00BCD4</item><item name="titleStyle">@style/DayTitleStyle</item><item name="contentStyle">@style/DayContentStyle</item><item name="buttonBg">#2196F3</item><item name="buttonTextColor">#ffffff</item><item name="checkTextColor">#2196F3</item><item name="switchTextColor">#2196F3</item></style><style name="DayTitleStyle"><item name="android:textColor">#212121</item><item name="android:textSize">20sp</item><item name="android:layout_margin">8dp</item></style><style name="DayContentStyle"><item name="android:textColor">#9C27B0</item><item name="android:textSize">16sp</item><item name="android:layout_margin">16dp</item><item name="android:maxLines">10</item></style></resources>夜间主题
<resources><style name="NightTheme" parent="Theme.AppCompat.Light.DarkActionBar"><!-- Customize your theme here. --><item name="colorPrimary">#00796B</item><item name="android:textColorPrimary">#212121</item><item name="android:windowBackground">@color/background_material_dark</item><item name="colorAccent">#00796B</item><item name="colorControlNormal">#212121</item><item name="titleStyle">@style/NightTitleStyle</item><item name="contentStyle">@style/NightContentStyle</item><item name="buttonBg">#00796B</item><item name="buttonTextColor">#9E9E9E</item><item name="checkTextColor">#212121</item><item name="switchTextColor">#212121</item></style><style name="NightTitleStyle"><item name="android:textColor">#212121</item><item name="android:textSize">20sp</item><item name="android:layout_margin">8dp</item></style><style name="NightContentStyle"><item name="android:textColor">#212121</item><item name="android:textSize">16sp</item><item name="android:layout_margin">16dp</item><item name="android:maxLines">10</item></style></resources>上面这两套主题中,各个属性定义完全一模一样,不一样的只是属性的值,其中在DayTheme和NightTheme的style中有这么一段代码:
<item name="titleStyle">@style/DayTitleStyle</item><item name="contentStyle">@style/DayContentStyle</item><item name="buttonBg">#2196F3</item><item name="buttonTextColor">#ffffff</item><item name="checkTextColor">#2196F3</item><item name="switchTextColor">#2196F3</item>正常情况下style中是不存在这些属性的,它们这些是自定义属性,主要是用来控制某些控件或者布局的属性,它们的定义在attr文件中:
<?xml version="1.0" encoding="utf-8"?><resources><attr name="contentStyle" format="reference"/><attr name="titleStyle" format="reference"/><attr name="buttonBg" format="reference|color"/><attr name="buttonTextColor" format="reference|color"/><attr name="checkTextColor" format="reference|color"/><attr name="switchTextColor" format="reference|color"/></resources>然后在布局中引用即可:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewstyle="?attr/titleStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/title" /><TextViewstyle="?attr/contentStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/hello_world" /><CheckBoxandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="CheckBox"android:textColor="?attr/checkTextColor" /><CheckBoxandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="CheckBox"android:textColor="?attr/checkTextColor" /><Switchandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Switch"android:textColor="?attr/switchTextColor" /><Buttonandroid:id="@+id/btn_setting"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置"android:background="?attr/buttonBg"android:textColor="?attr/buttonTextColor" /></LinearLayout>最后在整个App主题的style中使用它们就ok了。这样做有什么好处呢?我们都知道App设置主题时候都是设置一个style,而App中某些控件或者布局的背景或者style样式需要和整个主题样式不同时,这时候可以通过设置个自定义属性,通过在App的style中给与自定义属性不同的值来达到目的。
public class ThemeChangeUtil {public static boolean isChange = false;public static void changeTheme(Activity activity){if(isChange){activity.setTheme(R.style.NightTheme);}}}设置界面:public class ChangeTheme extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {ThemeChangeUtil.changeTheme(this);super.onCreate(savedInstanceState);setContentView(R.layout.activity_change);Button mChangeBtn = (Button) findViewById(R.id.btn_change);mChangeBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (ThemeChangeUtil.isChange) {ThemeChangeUtil.isChange = false;} else {ThemeChangeUtil.isChange = true;}ChangeTheme.this.recreate();//重新创建当前Activity实例}});}@Overridepublic void onBackPressed() {super.onBackPressed();Intent mIntent = new Intent(this, MainActivity.class);mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);startActivity(mIntent);finish();}}主界面:public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {ThemeChangeUtil.changeTheme(this);super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button mSettingBtn = (Button) findViewById(R.id.btn_setting);mSettingBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {MainActivity.this.startActivity(new Intent(MainActivity.this, ChangeTheme.class));}});}}以上就是Android主题切换中的白天/夜间模式的详细过程及代码,一开始先给大家简单的展示了代码,而后详细的介绍过程及代码,需要的朋友参考。