在android应用开发时,可能会用到夜间模式,一般的解决方案就是用主题。夜间模式一般就涉及道背景,亮度,字体颜色等,所以可以简单通过自定义组件实现。接下来就介绍一种解决方案:只需要简单的依赖自定义库,初始化,并使用库里面自定义组件即可。Demo和组件库下载地址:http://download.csdn.net/detail/itjianghuxiaoxiong/8724459 ;
作夜间模式无非就两种状态:一种是夜间,一种是日间。然后就是监听状态的改变,通知布局切换状态。
1.监听状态改变,并发通知:采用观察者模式,当观察者发生改变时通知被观察者刷新组件;
2.自定义布局:自定已常用组件,并添加两种模式属性,方便定义不同模式样式。
初始化类:
package com.ml.dayornight.theme.view; import android.content.Context; import android.content.SharedPreferences; import java.util.Observable; /** * @Package com.ml.dayornight.theme.view * @ClassName: ThemeInit * @Description: 初始化夜间模式 * @author malong * @date May 20, 2015 6:32:57 PM */ public class ThemeInit { public static ViewObservable mViewObservable; public static SharedPreferences sharedPreferences; public static final String THEME_MODE = "isDay"; public ThemeInit(Context context) { mViewObservable = new ViewObservable(); sharedPreferences = context.getSharedPreferences("day_or_night", Context.MODE_PRIVATE); } /** * @Package com.ml.dayornight.theme.view * @ClassName: ViewObservable * @Description: 创建一个被观察者 * @author malong * @date May 20, 2015 3:41:14 PM */ public class ViewObservable extends Observable { public void observableChange() { setChanged(); notifyObservers(); } } /** * @Description: 保存夜间模式状态 * @param key * @param value * @return void * @author malong * @date May 20, 20153:37:51 PM */ public static void saveBoolean(String key, Boolean value) { sharedPreferences.edit().putBoolean(key, value).commit(); } /** * @Description: 读取夜间模式状态 * @param key * @param defValue * @return * @return Boolean * @author malong * @date May 20, 20153:40:39 PM */ public static Boolean getBoolean(String key, Boolean defValue) { return sharedPreferences.getBoolean(key, defValue); } public static Boolean isDay() { return sharedPreferences.getBoolean(THEME_MODE, true); } }
自定义组件类EditText:
package com.ml.dayornight.theme.view; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.EditText; import java.util.Observable; import java.util.Observer; /** * @Package com.ml.dayornight.theme.view * @ClassName: ThemeRelativeLayout * @Description: 可设置夜间模式EditText * @author malong * @date May 18, 2015 6:24:13 PM */ public class ThemeEditText extends EditText { private Drawable nightBackground, dayBackground;// 设置日间和夜间的背景(可以是颜色值,图片,或selector) private float dayAlpha, nightAlpha;// 设置日间和夜间的透明度 private ColorStateList dayTextColor, nightTextColor, dayHintTextColor, nightHintTextColor; /** * @Description: 构造函数,初始化日间夜间模式 * @param @param context * @author malong * @date May 18, 20156:25:12 PM */ public ThemeEditText(Context context) { super(context); init(context, null, 0); } /** * @Description: 构造函数,初始化日间夜间模式 * @param @param context * @param @param attrs * @author malong * @date May 18, 20156:25:12 PM */ public ThemeEditText(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } /** * @Description: 构造函数,初始化日间夜间模式 * @param @param context * @param @param attrs * @param @param defStyle * @author malong * @date May 18, 20159:18:13 PM */ public ThemeEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } /** * @Description: 初始化日间夜间模式 * @return void * @author malong * @date May 18, 20156:25:12 PM */ private void init(Context context, AttributeSet attrs, int defStyle) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.day_or_night); /** * 此处参TextView源码 */ if (a != null) { dayAlpha = a.getFloat(R.styleable.day_or_night_dayAlpha, 1.0f); nightAlpha = a.getFloat(R.styleable.day_or_night_nightAlpha, 1.0f); dayBackground = a.getDrawable(R.styleable.day_or_night_dayBackground); nightBackground = a.getDrawable(R.styleable.day_or_night_nightBackground); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.day_or_night_dayTextColor: dayTextColor = a.getColorStateList(attr); break; case R.styleable.day_or_night_nightTextColor: nightTextColor = a.getColorStateList(attr); break; case R.styleable.day_or_night_dayHintTextColor: dayHintTextColor = a.getColorStateList(attr); break; case R.styleable.day_or_night_nightHintTextColor: nightHintTextColor = a.getColorStateList(attr); break; } } a.recycle(); } if (ThemeInit.mViewObservable != null) { ThemeInit.mViewObservable.addObserver(new ViewObserver()); } changeBackground(); } /** * @Description: 改变控件的背景色 * @param context2 * @return void * @author malong * @date May 18, 20156:25:12 PM */ public void changeBackground() { if (ThemeInit.sharedPreferences != null) { if (ThemeInit.isDay()) {// 日间 if (dayBackground != null) { this.setBackground(dayBackground); } if (dayAlpha != 1.0f) { this.setAlpha(dayAlpha); } if (dayTextColor != null) { this.setTextColor(dayTextColor); } if (dayHintTextColor != null) { this.setHintTextColor(dayHintTextColor); } } else {// 夜间 if (nightBackground != null) { this.setBackground(nightBackground); } if (nightAlpha != 1.0f) { this.setAlpha(nightAlpha); } if (nightTextColor != null) { this.setTextColor(nightTextColor); } if (nightHintTextColor != null) { this.setHintTextColor(nightHintTextColor); } } } } /** * @Package com.ccdt.news.ui.view * @ClassName: ViewObserver * @Description: 观察者 * @author malong * @date May 18, 20156:25:12 PM */ public class ViewObserver implements Observer {// 观察者 @Override public void update(Observable observable, Object data) { changeBackground(); } } }
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="day_or_night"> <attr name="dayAlpha" format="float" /> <attr name="nightAlpha" format="float" /> <attr name="dayTextColor" format="color" /> <attr name="nightTextColor" format="color" /> <attr name="dayHintTextColor" format="color" /> <attr name="nightHintTextColor" format="color" /> <attr name="dayBackground" format="reference|color" /> <attr name="nightBackground" format="reference|color" /> </declare-styleable> </resources>
在xml布局中使用:
<com.ml.dayornight.theme.view.ThemeEditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/title" android:layout_margin="10dp" android:hint="@string/text_hint" android:imeOptions="actionSearch" android:maxLines="2" app:dayBackground="@drawable/theme_edit_text_background_of_day" app:dayHintTextColor="#34d243" app:dayTextColor="@android:color/black" app:nightBackground="@drawable/theme_edit_text_background_of_night" app:nightHintTextColor="#55DDDDDD" app:nightTextColor="#DD00DD" />
package com.ml.dayornightdome; import android.app.Activity; import android.os.Bundle; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import com.ml.dayornight.theme.view.ThemeInit; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new ThemeInit(getApplicationContext());// 初始化夜间模式,可在Application中初始化,只需初始化一次。 setContentView(R.layout.activity_main); CheckBox mCheckBox = (CheckBox) findViewById(R.id.setting_night_check_box); mCheckBox.setChecked(!ThemeInit.isDay()); mCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { ThemeInit.saveBoolean(ThemeInit.THEME_MODE, !isChecked); if (ThemeInit.mViewObservable != null) { ThemeInit.mViewObservable.observableChange(); } } }); } }
当然,我们不用自定义所有view,而是选在改变父view的颜色,子view一般可以透明不设置颜色。库里面的view基本够用了,有特殊需求可以按照此方法自定义。