背景:现在做的软件颜色是白色的,如果在晚上看就会觉的很刺眼,对眼睛不好。于是想要实现夜间模式,然后在网上找了一写demo,有了实现思路,来看看具体的实现过程吧..
我使用的工具是android studio1.4 ,gradle:1.5.0,为什么使用1.4呢,之前一直使用1.0的版本,最近想要研究material, android studio 1.4可以直接创建material风格的项目,而且代码已经自动生成,非常方便,但是你之前用gradle是1.5.0以下的版本的话,运行程序会直接崩溃,如果你也遇到这样的问题,请看我的另一篇博客,http://blog.youkuaiyun.com/tuibiansoar/article/details/50778079
先看下切换主题的效果图:
APEC蓝
脑残粉主题:
夜间模式主题:
首先我们要通过设置主题的方式进行切换皮肤,怎么去切换主题呢?
在androidManifest.xml中系统默认会设置主题,进入style文件中就可以看到主题
这里是在xml里直接设置的默认主题,我们要切换主题需要动态的去加载不同的主题,所以我们要用到activity中的setTheme()方法设置主题。我们在设置主题的时候不可能只设置一个toolbar的颜色就ok了,还需要设值一些其他的颜色,例如点击效果,或者字体颜色要和主题颜色相对应,如果主题颜色为黑色,字体也是黑色,这样就造成问题看不到的问题,所以我们要自定义一些属性供我们使用。首先我们要在attr.xml中自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="colorPrimaryLight" format="reference|color" />
<attr name="colorTextLight" format="reference|color"/>
<attr name="colorTextDark" format="reference|color"/>
<attr name="colorBackground" format="reference|color"/>
<attr name="colorNavItem" format="reference|color"/>
<attr name="colorDivider" format="reference|color"/>
</resources>
有了这些属性就可以自定义一些主题了,新建一个theme.xml,里边定义不同风格的主题
</pre><pre class="html" name="code"><?xml version="1.0" encoding="utf-8"?>
<resources>
<!--中国红主题-->
<style name="Red_theme" parent="BaseTheme">
<item name="colorPrimary">@color/red_primary</item>
<item name="colorPrimaryDark">@color/red_primary_dark</item>
<item name="colorAccent">@color/red_primary_light</item>
<item name="colorTextLight">@color/red_text_light</item>
<item name="colorTextDark">@color/red_text_dark</item>
<item name="colorBackground">@color/comment_backgroud</item>
<item name="colorNavItem">@color/item_nav_red_seletor</item>
<item name="colorDivider">@color/comment_divider</item>
</style>
<!--琥珀主题-->
<style name="Amber_theme" parent="BaseTheme">
<item name="colorPrimary">@color/amber_primary</item>
<item name="colorPrimaryDark">@color/amber_primary_dark</item>
<item name="colorAccent">@color/amber_primary_light</item>
<item name="colorTextLight">@color/amber_text_light</item>
<item name="colorTextDark">@color/amber_text_dark</item>
<item name="colorBackground">@color/comment_backgroud</item>
<item name="colorNavItem">@color/item_nav_amber_seletor</item>
<item name="colorDivider">@color/comment_divider</item></style>
<!--APEC蓝主题-->
<style name="Indigo_theme" parent="BaseTheme">
<item name="colorPrimary">@color/indigo_primary</item>
<item name="colorPrimaryDark">@color/indigo_primary_dark</item>
<item name="colorAccent">@color/indigo_primary_light</item>
<item name="colorTextLight">@color/indigo_text_light</item>
<item name="colorTextDark">@color/indigo_text_dark</item>
<item name="colorBackground">@color/comment_backgroud</item>
<item name="colorNavItem">@color/item_nav_indigo_seletor</item>
<item name="colorDivider">@color/comment_divider</item></style>
<!--脑残粉主题-->
<style name="Pink_theme" parent="BaseTheme">
<item name="colorPrimary">@color/pink_primary</item>
<item name="colorPrimaryDark">@color/pink_primary_dark</item>
<item name="colorAccent">@color/pink_primary_light</item>
<item name="colorTextLight">@color/pink_text_light</item>
<item name="colorTextDark">@color/pink_text_dark</item>
<item name="colorBackground">@color/comment_backgroud</item>
<item name="colorNavItem">@color/item_nav_pink_seletor</item>
<item name="colorDivider">@color/comment_divider</item></style>
<!--夜间主题-->
<style name="Night_theme" parent="BaseTheme.Night">
<item name="colorPrimary">@color/black_primary</item>
<item name="colorPrimaryDark">@color/black_primary_dark</item>
<item name="colorAccent">@color/black_primary_light</item>
<item name="colorTextLight">@color/black_text_light</item>
<item name="colorTextDark">@color/black_text_dark</item>
<item name="colorBackground">@color/grey_800</item>
<item name="colorNavItem">@color/item_nav_night_seletor</item>
<item name="colorDivider">@color/comment_divider</item></style>
</resources>
下边我们就可以用来改变主题了,以下是java代码的实现
ThemeUtils.java
public class ThemeUtils {
public static final String TAG = "ThemeUtils";
private static final String THEME = "pre_theme";
private static Activity mContext;
public static void changeTheme(Activity activity) {
mContext = activity;
final ChoiceOnClickListener listener = new ChoiceOnClickListener();
final int index = 0;
new AlertDialog.Builder(activity)
.setTitle(R.string.theme)
.setSingleChoiceItems(new TAdapter(activity, R.layout.item_theme, R.id.check, Theme.getThemes()), index, listener)
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
setTheme(mContext, listener.getWhich());
mContext.startActivity(new Intent(mContext, MainActivity.class));
mContext.finish();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.create()
.show();
}
/**
*
* @param activity
*/
public static void setTheme(Activity activity,int index) {
setTheme(activity, Theme.getThemes().get(index));
}
/**
*
* @param activity
* @param theme
*/
public static void setTheme(Activity activity, Theme theme) {
if (theme == null) {
return;
}
activity.setTheme(theme.style);
}
/**
*
*/
private static class ChoiceOnClickListener implements DialogInterface.OnClickListener {
private int which = 0;
@Override
public void onClick(DialogInterface dialogInterface, int which) {
this.which = which;
}
public int getWhich() {
return which;
}
}
/**
* Theme
*/
public static class Theme {
public String name;
public String tag;
public int color;
public int style;
private static List<Theme> THEME_MAP = new ArrayList<>();
static {
THEME_MAP.add(new Theme(getString(R.string.theme_name_indigo), getString(R.string.theme_tag_indigo), R.color.indigo_primary, R.style.Indigo_theme));
THEME_MAP.add(new Theme(getString(R.string.theme_name_red), getString(R.string.theme_tag_red), R.color.red_primary, R.style.Red_theme));
THEME_MAP.add(new Theme(getString(R.string.theme_name_amber), getString(R.string.theme_tag_amber), R.color.amber_primary, R.style.Amber_theme));
THEME_MAP.add(new Theme(getString(R.string.theme_name_pink), getString(R.string.theme_tag_pink), R.color.pink_primary, R.style.Pink_theme));
THEME_MAP.add(new Theme(getString(R.string.theme_name_night), getString(R.string.theme_tag_night), R.color.black_primary, R.style.Night_theme));
}
public Theme(String name, String tag, @ColorRes int color, int style) {
this.name = name;
this.tag = tag;
this.color = color;
this.style = style;
}
protected static List<Theme> getThemes() {
return THEME_MAP;
}
@Override
public String toString() {
return name;
}
}
private static class TAdapter extends ArrayAdapter<Theme> {
private int mTextId;
public TAdapter(Context context, int resource, int textViewResourceId, List<Theme> objects) {
super(context, resource, textViewResourceId, objects);
this.mTextId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Theme theme = getItem(position);
View view = super.getView(position, convertView, parent);
CheckedTextView textView = (CheckedTextView) view.findViewById(mTextId);
// MDTintHelper.setTint(textView, getContext().getResources().getColor(theme.color));
textView.setTextColor(getContext().getResources().getColor(theme.color));
// textView.setChecked(convertView.getiss);
// textView.setChecked(true);
return view;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public long getItemId(int position) {
return position;
}
}
private static String getString(int resid) {
return mContext.getString(resid);
}
点击跳转之后需要在MainActivity 的onCreate()方法中调用ThemeUtils.setTheme(activity)方法设置,为了方便建议写一个BaseActivity,在这里的onCreate调用, 然后继承BaseActivity。
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtils.changeTheme(this);
}
}
这样就进行切换皮肤和主题了,但是非夜间模式的主题你会发现切换后的主题是这个样子的,有没有发现有点怪,toolbar的字体和菜单颜色白色会不会更好看呢,但是这个要怎么去修改呢?在android 5.0里新的控件就已经支持设置theme了,是不是很神奇。
呐
既然这样,那我们就给toolbar设置一个主题,代码如下:
<style name="MyActionBar" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:background">?attr/colorPrimary</item>
<item name="android:actionModeBackground">?attr/colorPrimary</item>
<item name="android:fitsSystemWindows">true</item>
<item name="android:windowActionModeOverlay">true</item>
</style>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/MyActionBar"
/>
在toolbar上设置给theme就好了,在看下效果
这样是不是看着更爽呢!!
有的人在运行的demo中发现滑出的菜单点击某一菜单时,点击效果和主题的风格是相同的,这个怎么实现呢?
可以用这两个属性itemTextColor和ItemIconTint
关于夜间模式,需要把整体的主题设置成暗色调的,所以自定义的主题和其他主题有所不同。
以上就是切换主题的实现方式了。有问题欢迎大家纠正...
下载demo地址:http://download.youkuaiyun.com/detail/tuibiansoar/9462210
切换主题其他相关资料: