实现夜间模式,不需要recreate,不闪屏

通过资源 id 映射,回调自定义 ThemeChangeListener 接口来处理日间/夜间模式的切换。


在values下面colors.xml里面

    <?xml version="1.0" encoding="utf-8"?>  
    <resources>  
       
     <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>  
       
    </resources>  
需要一个主题管理类 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();  
 }  
} 
activity_main.xml里面只需要写一个按钮,然后给根布局一个id(因为需要改变根布局的背景颜色)

在MainActivity.java找到按钮的id和根布局的id

在 MainActivity 中实现了 OnThemeChangeListener 接口,这样就可以在主题改变的时候执行回调方法。然后在 initTheme() 中去重新设置 UI 的相关颜色属性值。还有别忘了要在 onDestroy() 中移除 ThemeChangeListener 。

    public class MainActivity extends AppCompatActivity implements ThemeManager.OnThemeChangeListener {  
      
     private TextView tv;  
     private Button btn_theme;  
     private RelativeLayout relativeLayout;  
     private ActionBar supportActionBar;  
      
     @Override  
     protected void onCreate(Bundle savedInstanceState) {  
      super.onCreate(savedInstanceState);  
      setContentView(R.layout.activity_main);  
      ThemeManager.registerThemeChangeListener(this);  
      supportActionBar = getSupportActionBar();  
      btn_theme = (Button) findViewById(R.id.btn_theme);  
      relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);  
      tv = (TextView) findViewById(R.id.tv);  
      btn_theme.setOnClickListener(new View.OnClickListener() {  
       @Override  
       public void onClick(View v) {  
        ThemeManager.setThemeMode(ThemeManager.getThemeMode() == ThemeManager.ThemeMode.DAY  
          ? ThemeManager.ThemeMode.NIGHT : ThemeManager.ThemeMode.DAY);  
       }  
      });  
     }  
      
     public void initTheme() {  
      tv.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));  
      btn_theme.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));  
      relativeLayout.setBackgroundColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.backgroundColor)));  
      // 设置标题栏颜色  
      if(supportActionBar != null){  
       supportActionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary))));  
      }  
      // 设置状态栏颜色  
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {  
       Window window = getWindow();  
       window.setStatusBarColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary)));  
      }  
     }  
      
     @Override  
     public void onThemeChanged() {  
      initTheme();  
     }  
      
     @Override  
     protected void onDestroy() {  
      super.onDestroy();  
      ThemeManager.unregisterThemeChangeListener(this);  
     }  
      
    }  






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值