Android中通过更改Theme来更换皮肤也是常用的一种方法 也是实现夜间模式的一种
具体步骤:
首先在attrs.xml文件中,给需要改变Theme的控件自定义属性值,这里就已根布局的背景,和Textview的颜色为例:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="root_view_bg" format="reference|color"/>
<attr name="text_color" format="reference|color"/>
</resources>
然后再style.xml文件中设置你所需要的主题 有几个主题就设置几个 以便以后切换:
<style name="BlueStyle">
<item name="root_view_bg">@color/blue</item>
<item name="text_color">@color/white</item>
</style>
<style name="GreenStyle">
<item name="root_view_bg">@color/green</item>
<item name="text_color">@color/black</item>
</style>
在布局文件中使用自定义的属性:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/root_view_bg"
>
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="?attr/text_color"
android:textSize="30sp"
android:text="Hello World!" />
<Button
android:id="@+id/btn_change"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="change"/>
</RelativeLayout>
这里的 ?attr/root_view_bg ?attr/text_color 就是我们自己设定的属性,当setTheme的时候可以跟着我们设定改变
这个时候我们只要在Activity中的setContentView ()之前调用setTheme(R.style.xxx)方法就可以使activity成为我们需要的主题颜色。
但是我们要是有一个按钮来点击切换主题的时候,在点击的方法中调用setTheme(R.style.xxx) 你会发现没有反应,因为要想让新生的Theme生效,需要重新启动activity重新刷新UI。这时候我们可以在setTheme(R.style.xxx) 方法的后面再调用一次setContentView()方法来实现更换主题。
setTheme(R.style.GreenStyle);
setContentView(R.layout.activity_main);
但是如果在我们的布局很复杂的情况下,在调用setContentView()就会有界面的闪烁
我们可以通过重置属性来实现
TypedValue typedValue = new TypedValue();
newTheme.resolveAttribute(mArrId, typedValue, true); //<span style="font-family: Arial, Helvetica, sans-serif;">mArrId是自定义的属性的id</span>
为了方便扩展 封装几个类:
package com.chs.changeskin.view;
import android.content.res.Resources;
import android.util.TypedValue;
import android.view.View;
/**
* 作者:chs on 2016/1/20 17:03
* 邮箱:657083984@qq.com
*/
public abstract class ViewEntity {
protected int mViewId;
protected View mView;
protected int mArrId;
public ViewEntity(int mViewId, int mArrId) {
this.mViewId = mViewId;
this.mArrId = mArrId;
}
public ViewEntity(View mView, int mArrId) {
this.mView = mView;
this.mArrId = mArrId;
}
public abstract void setValue(Resources.Theme newTheme, int themeId);
public int getViewId() {
return mViewId;
}
public void setViewId(int viewId) {
mViewId = viewId;
}
public View getView() {
return mView;
}
public void setView(View view) {
this.mView = view;
}
public int getArrId() {
return mArrId;
}
public void setArrId(int arrId) {
this.mArrId = arrId;
}
protected int getColor(Resources.Theme newTheme) {
TypedValue typedValue = new TypedValue();
newTheme.resolveAttribute(mArrId, typedValue, true);
return typedValue.data;
}
}
package com.chs.changeskin.view;
import android.content.res.Resources;
import android.view.View;
/**
* 作者:chs on 2016/1/20 17:08
* 邮箱:657083984@qq.com
*/
public class BgViewEntity extends ViewEntity {
public BgViewEntity(int mViewId, int mArrId) {
super(mViewId, mArrId);
}
public BgViewEntity(View mView, int mArrId) {
super(mView, mArrId);
}
@Override
public void setValue(Resources.Theme newTheme, int themeId) {
if ( mView != null ) {
mView.setBackgroundColor(getColor(newTheme));
}
}
}
package com.chs.changeskin.view;
import android.content.res.Resources;
import android.view.View;
import android.widget.TextView;
/**
* 作者:chs on 2016/1/20 17:08
* 邮箱:657083984@qq.com
*/
public class TextViewEntity extends ViewEntity {
public TextViewEntity(int mViewId, int mArrId) {
super(mViewId, mArrId);
}
public TextViewEntity(View mView, int mArrId) {
super(mView, mArrId);
}
@Override
public void setValue(Resources.Theme newTheme, int themeId) {
if (mView == null) {
return;
}
((TextView) mView).setTextColor(getColor(newTheme));
}
}
activity中初始化所有需要改变的控件
public static List<ViewEntity> ViewEntitys = new ArrayList<>();
private void initViewEntitys() {
ViewEntitys.add(new BgViewEntity(findViewById(R.id.root), R.attr.root_view_bg));
ViewEntitys.add(new TextViewEntity(findViewById(R.id.tv_text), R.attr.text_color));
}
void changeTheme(){
if(curTme){
setTheme(R.style.GreenStyle);
resetAttr(R.style.GreenStyle);
}else {
setTheme(R.style.BlueStyle);
resetAttr(R.style.BlueStyle);
}
curTme = !curTme;//切换使用
}
private void resetAttr(int themeId) {
Resources.Theme curTheme = getTheme();
for(ViewEntity entity:ViewEntitys){
entity.setValue(curTheme,themeId);
}
}
mainActivity代码:
package com.chs.changeskin;
import android.content.Intent;
import android.content.res.Resources;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.chs.changeskin.view.BgViewEntity;
import com.chs.changeskin.view.TextViewEntity;
import com.chs.changeskin.view.ViewEntity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static List<ViewEntity> ViewEntitys = new ArrayList<>();
RelativeLayout root;
TextView tv_text;
Button button;
boolean curTme = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.BlueStyle);
setContentView(R.layout.activity_main);
initView();
initEvent();
initViewEntitys();
}
private void initViewEntitys() {
ViewEntitys.add(new BgViewEntity(findViewById(R.id.root), R.attr.root_view_bg));
ViewEntitys.add(new TextViewEntity(findViewById(R.id.tv_text), R.attr.text_color));
}
private void initView() {
root = (RelativeLayout) findViewById(R.id.root);
tv_text = (TextView) findViewById(R.id.tv_text);
button = (Button) findViewById(R.id.btn_change);
}
private void initEvent() {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeTheme();
// setTheme(R.style.GreenStyle);
// setContentView(R.layout.activity_main);
}
});
}
void changeTheme(){
if(curTme){
setTheme(R.style.GreenStyle);
resetAttr(R.style.GreenStyle);
}else {
setTheme(R.style.BlueStyle);
resetAttr(R.style.BlueStyle);
}
curTme = !curTme;
}
private void resetAttr(int themeId) {
Resources.Theme curTheme = getTheme();
for(ViewEntity entity:ViewEntitys){
entity.setValue(curTheme,themeId);
}
}
}
效果图: