Android夜间模式(多主题)探索
JanisNoguer
8年前
<p>主题功能老早就想研究了,可是看了很多之后,发现想要很好的实现,并没有什么简单的办法。</p> <p>但是如果要求不高,实现起来还是挺简单的。</p> <p><strong>先说说简单的实现步骤</strong></p> <ol> <li>在 styles.xml 中定义不同的主题风格;</li> <li>在 attrs.xml 文件中,定义自己的属性;</li> <li>在 layout 布局文件中,使用 styles.xml 中定义的属性;</li> <li>在 Activity 中切换主题,就好了。</li> </ol> <p>然后来看每一步的详细操作:</p> <p><strong>1. 在 styles.xml 中定义不同的主题风格</strong></p> <p>也就是定义多种风格的主题,设置不同的颜色等。</p> <pre> <code class="language-java"><resources> <style name="AppTheme" parent="Theme.AppCompat.Light"> <!--Toolbar的背景颜色--> <item name="colorPrimary">@color/colorPrimary</item> <!--StatusBar的颜色--> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!--主标题的字体颜色--> <item name="android:textColorPrimary">@color/textColorPrimary</item> <!--控制元件的默认状态颜色--> <item name="android:colorControlNormal">@color/colorControlNormal</item> <!--控制元件在选中状态的颜色--> <item name="colorAccent">@color/colorAccent</item> <!--Activity的背景颜色--> <item name="android:windowBackground">@color/windowBackground</item> <!--自定义的属性--> <item name="Text_bg_Color">@color/Text_bg_Color</item> </style> <style name="AppThemeNight" parent="Theme.AppCompat.Light"> <item name="colorPrimary">@color/NcolorPrimary</item> <item name="colorPrimaryDark">@color/NcolorPrimaryDark</item> <item name="android:textColorPrimary">@color/NtextColorPrimary</item> <item name="android:colorControlNormal">@color/NcolorControlNormal</item> <item name="colorAccent">@color/NcolorAccent</item> <item name="android:windowBackground">@color/NwindowBackground</item> <item name="Text_bg_Color">@color/NText_bg_Color</item> </style> </resources></code></pre> <p>大多时候,系统自带的属性并不够用,所以就需要自定义一些属性,比如说上面的最后一个属性。</p> <p>自定义方法如下</p> <p><strong>2. 在 attrs.xml 文件中,定义自己的属性</strong></p> <p>在values文件夹下,新建attrs.xml文件,定义自己的属性。</p> <pre> <code class="language-java"><resources> <attr name="Text_bg_Color" format="color"/> </resources></code></pre> <p><strong>3. 在 layout 布局文件中,使用 styles.xml 中定义的属性</strong></p> <p>布局文件中,在需要改变色调的位置,设置相应的属性。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/3d07c5d634edb3fc2c0bff4008680545.png"></p> <p style="text-align:center">布局文件</p> <p><strong>4. 最后一步,在 Activity 中切换主题</strong></p> <pre> <code class="language-java">public class MainActivity extends AppCompatActivity { /** * recreate() 会使 Activity 重新刷新,所以 这个标志必须是静态的。 */ private static boolean night = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); changeTheme(); setContentView(R.layout.activity_main); findViewById(R.id.email_sign_in_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { change(); } }); } private void change() { night = !night; changeTheme(); recreate();// 重启 Activity } /** * 根据标志改变主题 */ private void changeTheme() { if (night) { setTheme(R.style.AppThemeNight); } else { setTheme(R.style.AppTheme); } } }</code></pre> <p>到此,就可以实现一个最基本的切换主题了,这样也是会有一个问题,也就是闪屏。</p> <p>但是如果要求不是很高,这也是可以满足需求的。</p> <p>闪屏也是大家想尽各种办法想要解决的一个问题。</p> <p>在此写下大家解决的思路。</p> <p><strong>目前思路是:</strong></p> <ol> <li>利用 setTheme(); 改变主题;</li> <li>用 recreate() 刷新当前Activity,主题就改变了。</li> </ol> <p><strong>解决闪屏办法:</strong></p> <p>不再使用 setTheme();</p> <p>而是将当前 Activity 上的每个控件,分别改成自己设定的颜色。</p> <p><strong>对,没错,就是修改每个控件。</strong></p> <p>各种解决办法,也就是看使用什么办法可以更方便的修改多个控件。</p> <p>找到了两个切换主题的框架,从源码中很明显的可以看出,他们都是把常用的基本控件重写的一遍,而我们要使用这个框架的时候,也必须使用框架所提供的控件。</p> <p>当调用了切换主题的方法后,会遍历使用的控件修改相应的颜色,从而达到 不闪屏切换主题的效果。</p> <p><img src="https://simg.open-open.com/show/493d4659d479fa2ee27a3350f802d67f.png"></p> <p style="text-align:center">MagicaSakura</p> <p><img src="https://simg.open-open.com/show/65991b608369531cebe34170a3100314.png"></p> <p style="text-align:center">MultipleTheme</p> <p>如果是有多个主题,用框架实现还能接受,毕竟很麻烦。</p> <p>但是如果仅仅只是要实现夜间模式,就使用个框架还是不太舒服,而且必须要使用框架带的基本控件。</p> <p>所以还是有一些其他的方式,目的还是那句话:使用更好的方式修改多个控件的颜色。</p> <p>前面都大同小异,主要是修改颜色的那一段代码。</p> <p>将其项目提炼后,只剩修与修改主题相关代码:</p> <p> </p> <p> </p> <p>来自: http://www.jianshu.com/users/320f9e8f7fc9/latest_articles</p> <p> </p> <p> </p>