您的位置:首页 > 移动开发

加载自定义属性实现app换肤功能

2016-11-25 15:48 841 查看
在各大app中的换肤换主题的功能实现。博主的理解就是一种当用户点击更换主题按钮,从服务器下载主题。这种就是插件化加载。另一种就是自定义多套的属性,当用户点击的时候,就通过反射机制,在达到更换主题皮肤的效果。

下面,就通过一个小例子来实现换肤的功能,初次尝试,如有纰漏的地方望大神指出,多多交流





怎么自定义属性,不明白的戳这里:http://blog.csdn.net/qq_17387361/article/details/53330969

1:在values文件夹下新建attr.xml文件(这里就拿颜色变化来说,当然也可以定义图片资源。)

<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="main_bg" format="reference|color"/>
<attr name="main_textcolor" format="reference|color"/>
<attr name="other_bg" format="reference|color"/>
<attr name="other_textcolor" format="reference|color"/>

</resources>


2:在styles.xml中定义2套主题(里面的color值我用汉语拼音写的,通俗易懂)

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--  主题A  -->
<style name="theme_a" >
<item name="main_bg">@color/bai</item>
<item name="main_textcolor">@color/hei</item>
<item name="other_bg">@color/bai</item>
<item name="other_textcolor">@color/hei</item>
</style>

<!--  主题B -->
<style name="theme_b" >
<item name="main_bg">@color/hei</item>
<item name="main_textcolor">@color/bai</item>
<item name="other_bg">@color/hei</item>
<item name="other_textcolor">@color/bai</item>
</style>
</resources>


3:maniactivity的布局文件layout:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/main_bg"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">

<Button
android:id="@+id/btn_a"
android:text="跳转"
android:layout_centerInParent="true"
android:textColor="?attr/main_textcolor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/btn_b"
android:layout_centerHorizontal="true"
android:text="换肤"
android:layout_below="@id/btn_a"
android:layout_marginTop="30dip"
android:textColor="?attr/main_textcolor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</RelativeLayout>


注意其中自定义属性的引用:

android:textColor="?attr/main_textcolor"
效果图:



两个按钮,跳转是跳到另一个activity中。来模拟点击换肤的时候app其他的页面是否也做了变换。

另一个activity的布局很简单,这里直接给出效果图



这里注意仔细看,默认的颜色第一个activity背景是白色,按钮上面的字体颜色是黑色,第二个activity背景是白色,字体颜色是黑色

3:在来看activity类的代码

/**
* Created by W61 on 2016/11/25.
*/

public class BaseActivity extends AppCompatActivity{

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SpUtils.init(this, "henry_theme");
if(SpUtils.getInt("theme", 0) == 1) {
setTheme(R.style.theme_b);
} else {
setTheme(R.style.theme_a);
}
}
}

public class MainActivity extends BaseActivity {

private Button btn_a,btn_b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
btn_a = (Button) findViewById(R.id.btn_a);
btn_a.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,OtherActivity.class));
}
});
btn_b = (Button) findViewById(R.id.btn_b);
btn_b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(SpUtils.getInt("theme", 0) == 1) {
SpUtils.setInt("theme", 0);
setTheme(R.style.theme_a);
} else {
SpUtils.setInt("theme", 1);
setTheme(R.style.theme_b);
}
final View rootView = getWindow().getDecorView();
ColorUiUtil.changeTheme(rootView, getTheme());
startActivity(new Intent(MainActivity.this,MainActivity.class));
finish();
}
});
}


建了一个baseactivity便于统一管理,sputils是保存当前到底是那套皮肤的标识。大家可以自由发挥

注意:

startActivity(new Intent(MainActivity.this,MainActivity.class));
finish();
博主这个写这句代码是想点击换肤后当前页面也随之刷新。这里如果大家有更好的方法可以留言指出。

下面是一个帮助类(这个类拷贝网上大神写的方法)

/**
* Created by chengli on 15/6/10.
*/
public class ColorUiUtil {
/**
* 切换应用主题
*
* @param rootView
*/
public static void changeTheme(View rootView, Resources.Theme theme) {
if (rootView instanceof ColorUiInterface) {
((ColorUiInterface) rootView).setTheme(theme);
if (rootView instanceof ViewGroup) {
int count = ((ViewGroup) rootView).getChildCount();
for (int i = 0; i < count; i++) {
changeTheme(((ViewGroup) rootView).getChildAt(i), theme);
}
}
if (rootView instanceof AbsListView) {
try {
Field localField = AbsListView.class.getDeclaredField("mRecycler");
localField.setAccessible(true);
Method localMethod = Class.forName("android.widget.AbsListView$RecycleBin").getDeclaredMethod("clear", new Class[0]);
localMethod.setAccessible(true);
localMethod.invoke(localField.get(rootView), new Object[0]);
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e2) {
e2.printStackTrace();
} catch (NoSuchMethodException e3) {
e3.printStackTrace();
} catch (IllegalAccessException e4) {
e4.printStackTrace();
} catch (InvocationTargetException e5) {
e5.printStackTrace();
}
}
} else {
if (rootView instanceof ViewGroup) {
int count = ((ViewGroup) rootView).getChildCount();
for (int i = 0; i < count; i++) {
changeTheme(((ViewGroup) rootView).getChildAt(i), theme);
}
}
if (rootView instanceof AbsListView) {
try {
Field localField = AbsListView.class.getDeclaredField("mRecycler");
localField.setAccessible(true);
Method localMethod = Class.forName("android.widget.AbsListView$RecycleBin").getDeclaredMethod("clear", new Class[0]);
localMethod.setAccessible(true);
localMethod.invoke(localField.get(rootView), new Object[0]);
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e2) {
e2.printStackTrace();
} catch (NoSuchMethodException e3) {
e3.printStackTrace();
} catch (IllegalAccessException e4) {
e4.printStackTrace();
} catch (InvocationTargetException e5) {
e5.printStackTrace();
}
}
}
}


下面来看最终运行图:



大家可以仔细观察点击换肤前和换肤后的背景颜色和字体颜色。

这里建议大家在点击换肤时弹出一个加载框。来缓冲一下当前界面的刷新。

这是封装的一些列常用控件的jar包:http://download.csdn.net/detail/qq_17387361/9692620

这是本编博文的项目地址:http://download.csdn.net/detail/qq_17387361/9693602
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐