夜间模式的实现
来源:互联网 发布:淘宝卖家心酸 编辑:程序博客网 时间:2024/04/19 13:45
常见的实现夜间模式的方法有三种:
一.使用自定义的Theme来实现
二.使用DayNight主题来实现
三.使用映射id的方法来实现
现在让我们来分析这三种方法。
1.使用自定义的Theme来实现,这种方法也是Android官方推荐的方式。
首先我们应该在attrs.xml里定义切换到夜间模式时需要改变颜色的属性。
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="textColor" format="color|reference" /> <attr name="mainBackground" format="color|reference" /></resources>
其次我们需要在style.xml里添加我们的自定义属性:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!--这是我们自定义的属性--> <item name="textColor">#000000</item> <item name="mainBackground">#ffffff</item> </style>
上面的是正常状态下的字体颜色和布局颜色,然后我们在添加一个夜间模式的style:
<style name="Night" parent="Theme.AppCompat.Light.DarkActionBar" > <item name="textColor">#ffffff</item> <item name="mainBackground">#000000</item> <!--自定义属性--> <item name="colorPrimaryDark">#000000</item> <item name="colorPrimary">#000000</item> </style>
这样我们的日间模式和夜间模式的style就配置好了。接下来我们要在layout布局里使用我们的自定义属性:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?attr/mainBackground"> <TextView android:id="@+id/textView" android:layout_width="300dp" android:layout_height="300dp" android:text="Hello World!" android:gravity="center" android:layout_centerInParent="true" android:textSize="60sp" android:textColor="?attr/textColor"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/button" android:text="切换主题~~~"/></RelativeLayout>
现在我们只需要在对应的Activity来调用set Theme()方法来切换主题就好了:
public class CustomTheme extends AppCompatActivity implements View.OnClickListener{ private boolean isNormalTheme; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_theme); isNormalTheme = true; mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(this); } @Override public void onClick(View v) { if (isNormalTheme) { setTheme(R.style.Night); isNormalTheme = false; } else { setTheme(R.style.AppTheme); isNormalTheme = true; } setContentView(R.layout.activity_custom_theme); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(this); }}
注意上述代码种在onClick方法中调用了setContentView来重新加载布局。此时必须重新加载布局中的组件,否则就会失效。当然下面会讲到一个recreate()方法会比重新加载布局好一点(个人观点)。好了第一种方法就讲到这里。剩下的自己琢磨。嘻嘻~
2.使用DayNight来实现夜间模式
首先我们需要在style.xml里定义一个DayNight的style:
<style name="DayNight" parent="Theme.AppCompat.DayNight.DarkActionBar"> <!--可以自己添加东东--></style>
然后在Activity里实现它:
public class DayNightTheme extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_daynight_theme); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); } @Override public void onClick(View v) { //获取的当前资源的配置和默认uiMode int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; getDelegate().setLocalNightMode(currentNightMode == Configuration.UI_MODE_NIGHT_NO ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO); // 调用recreate方法使之生效 recreate(); }}
完成啦。补充说明一下
MODE_NIGHT_NO: 使用亮色(light)主题,不使用夜间模式
MODE_NIGHT_YES:使用暗色(dark)主题,使用夜间模式
MODE_NIGHT_AUTO:根据当前时间自动切换 亮色(light)/暗色(dark)主题
MODE_NIGHT_FOLLOW_SYSTEM(默认选项):设置为跟随系统,通常为 MODE_NIGHT_NO
AppCompatDelegate.setDefaultNightMode()是对整个App中theme为DayNight主题生效
getDelegate().setLocalNightMode()只对特定的组件生效
3.使用映射id的方法来实现夜间模式(我个人偏爱这种方法)。
首先我们需要在color上定义两套颜色。一套对应正常模式,一套对应夜间模式:
<color name="colorPrimary">#3F51B5</color> <color name="colorPrimary_night">#3b3b3b</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorPrimaryDark_night">#383838</color> <color name="colorAccent">#FF4081</color> <color name="colorAccent_night">#a72b55</color> <color name="textColor">#FF000000</color> <color name="textColor_night">#FFFFFF</color> <color name="backgroundColor">#FFFFFF</color> <color name="backgroundColor_night">#3b3b3b</color>
然后我们需要一个ThemeManager类:
public class ThemeManager { // 默认是日间模式 private static ThemeMode mThemeMode = ThemeMode.DAY; // 主题模式监听器 private static List<OnThemeChangeListener> mThemeChangeListenerList = new LinkedList<>(); // 夜间资源的缓存,key : 资源类型, 值<key:资源名称, value:int值> private static HashMap<String, HashMap<String, Integer>> sCachedNightResrouces = new HashMap<>(); // 夜间模式资源的后缀,比如日件模式资源名为:R.color.activity_bg, 那么夜间模式就为 :R.color.activity_bg_night private static final String RESOURCE_SUFFIX = "_night"; /** * 主题模式,分为日间模式和夜间模式 */ public enum ThemeMode { DAY, NIGHT } /** * 设置主题模式 * * @param themeMode */ public static void setThemeMode(ThemeMode themeMode) { if (mThemeMode != themeMode) { mThemeMode = themeMode; if (mThemeChangeListenerList.size() > 0) { for (OnThemeChangeListener listener : mThemeChangeListenerList) { listener.onThemeChanged(); } } } } /** * 根据传入的日间模式的resId得到相应主题的resId,注意:必须是日间模式的resId * * @param dayResId 日间模式的resId * @return 相应主题的resId,若为日间模式,则得到dayResId;反之夜间模式得到nightResId */ public static int getCurrentThemeRes(Context context, int dayResId) { if (getThemeMode() == ThemeMode.DAY) { return dayResId; } // 资源名 String entryName = context.getResources().getResourceEntryName(dayResId); // 资源类型 String typeName = context.getResources().getResourceTypeName(dayResId); HashMap<String, Integer> cachedRes = sCachedNightResrouces.get(typeName); // 先从缓存中去取,如果有直接返回该id if (cachedRes == null) { cachedRes = new HashMap<>(); } Integer resId = cachedRes.get(entryName + RESOURCE_SUFFIX); if (resId != null && resId != 0) { return resId; } else { //如果缓存中没有再根据资源id去动态获取 try { // 通过资源名,资源类型,包名得到资源int值 int nightResId = context.getResources().getIdentifier(entryName + RESOURCE_SUFFIX, typeName, context.getPackageName()); // 放入缓存中 cachedRes.put(entryName + RESOURCE_SUFFIX, nightResId); sCachedNightResrouces.put(typeName, cachedRes); return nightResId; } catch (Resources.NotFoundException e) { e.printStackTrace(); } } return 0; } /** * 注册ThemeChangeListener * * @param listener */ public static void registerThemeChangeListener(OnThemeChangeListener listener) { if (!mThemeChangeListenerList.contains(listener)) { mThemeChangeListenerList.add(listener); } } /** * 反注册ThemeChangeListener * * @param listener */ public static void unregisterThemeChangeListener(OnThemeChangeListener listener) { if (mThemeChangeListenerList.contains(listener)) { mThemeChangeListenerList.remove(listener); } } /** * 得到主题模式 * * @return */ public static ThemeMode getThemeMode() { return mThemeMode; } /** * 主题模式切换监听器 */ public interface OnThemeChangeListener { /** * 主题切换时回调 */ void onThemeChanged(); }}
对这里代码的理解可以参考这篇文章。我这里也做一些自己的理解。这个类的关键就是 getCurrentThemeRes 这个方法,这个方法里实现了color id的切换。然后在主方法里来实现它:
public class ReflectID extends AppCompatActivity implements View.OnClickListener,ThemeManager.OnThemeChangeListener{ private static boolean isNormalTheme; private ActionBar mActionBar; private TextView mTextView; private Button mButton; private RelativeLayout mRelativeLayout; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_reflect_id); ThemeManager.registerThemeChangeListener(this); isNormalTheme = true; mActionBar = getSupportActionBar(); mButton = (Button) findViewById(R.id.button); mTextView = (TextView) findViewById(R.id.textView); mButton.setOnClickListener(this); mRelativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout); } @Override public void onClick(View v) { ThemeManager.setThemeMode(ThemeManager.getThemeMode() == ThemeManager.ThemeMode.DAY ? ThemeManager.ThemeMode.NIGHT : ThemeManager.ThemeMode.DAY); } public void initTheme() { mTextView.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(ReflectID.this, R.color.textColor))); mButton.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(ReflectID.this, R.color.textColor))); mRelativeLayout.setBackgroundColor(getResources().getColor(ThemeManager.getCurrentThemeRes(ReflectID.this, R.color.backgroundColor))); // 设置标题栏颜色 if(mActionBar != null){ mActionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(ThemeManager.getCurrentThemeRes(ReflectID.this, R.color.colorPrimary)))); } // 设置状态栏颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.setStatusBarColor(getResources().getColor(ThemeManager.getCurrentThemeRes(ReflectID.this, R.color.colorPrimary))); } } @Override public void onThemeChanged() { initTheme(); }}
然后就完成啦!!!!!
表示博主就一入门新手如果有什么写错的啊,啥的就请多多指出来。谢谢大家!!!
Demo源码
参考文章:(http://www.jianshu.com/p/f3aaed57fa15)
- 夜间模式的实现
- 夜间模式的实现
- 夜间模式的实现
- 夜间模式的实现
- 夜间模式的实现
- 夜间模式的实现
- android夜间模式的实现
- Android夜间模式的实现
- android 夜间模式的实现
- iOS 夜间模式的实现
- 夜间模式的实现套路
- 夜间模式的简单实现
- Android 夜间模式的实现
- android夜间模式的实现
- 实现夜间模式的方法
- android夜间模式的实现
- 夜间模式的切换的实现方式
- 三种实现夜间模式的方法
- UWP 入门笔记之学习资源
- poj 1850 Code(组合计数)
- 关于Ubuntu系统无法搜索到wifi信号的解决办法
- String为什么不可变
- thinkphp模板标签用法大全
- 夜间模式的实现
- Collection接口API
- 关于js中 alert(1&&2)的 输出(研究了半天,是懂非懂吧)
- 遍历集合
- 如何消除内存泄漏
- Java写爬虫
- ACM-约瑟夫问题
- 计划
- 使用TreeSet