加载自定义属性实现app换肤功能
2016-11-25 15:48
841 查看
在各大app中的换肤换主题的功能实现。博主的理解就是一种当用户点击更换主题按钮,从服务器下载主题。这种就是插件化加载。另一种就是自定义多套的属性,当用户点击的时候,就通过反射机制,在达到更换主题皮肤的效果。
下面,就通过一个小例子来实现换肤的功能,初次尝试,如有纰漏的地方望大神指出,多多交流
。
怎么自定义属性,不明白的戳这里:http://blog.csdn.net/qq_17387361/article/details/53330969
1:在values文件夹下新建attr.xml文件(这里就拿颜色变化来说,当然也可以定义图片资源。)
2:在styles.xml中定义2套主题(里面的color值我用汉语拼音写的,通俗易懂)
3:maniactivity的布局文件layout:
注意其中自定义属性的引用:
两个按钮,跳转是跳到另一个activity中。来模拟点击换肤的时候app其他的页面是否也做了变换。
另一个activity的布局很简单,这里直接给出效果图
这里注意仔细看,默认的颜色第一个activity背景是白色,按钮上面的字体颜色是黑色,第二个activity背景是白色,字体颜色是黑色
3:在来看activity类的代码
建了一个baseactivity便于统一管理,sputils是保存当前到底是那套皮肤的标识。大家可以自由发挥
注意:
下面是一个帮助类(这个类拷贝网上大神写的方法)
下面来看最终运行图:
大家可以仔细观察点击换肤前和换肤后的背景颜色和字体颜色。
这里建议大家在点击换肤时弹出一个加载框。来缓冲一下当前界面的刷新。
这是封装的一些列常用控件的jar包:http://download.csdn.net/detail/qq_17387361/9692620
这是本编博文的项目地址:http://download.csdn.net/detail/qq_17387361/9693602
下面,就通过一个小例子来实现换肤的功能,初次尝试,如有纰漏的地方望大神指出,多多交流
。
怎么自定义属性,不明白的戳这里: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
相关文章推荐
- 超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验
- android自定义dialog实现app换肤功能
- Java类加载原理解析及怎样自定义Java类实现特殊的功能
- (五)带属性值的ng-app指令,实现自定义模块的自动加载
- Maven实现项目编译时不同命令加载不同属性值功能
- 分析Android App中内置换肤功能的实现方式
- 如何在App中实现朋友圈功能之六快速实现下拉加载朋友圈功能——箭扣科技Arrownock
- 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)
- 如何在App中实现朋友圈功能之二快速实现用户信息的自定义——箭扣科技Arrownock
- 绘图与动画之使用自定义属性与Quartz实现扇形加载动画
- 如何在App中实现朋友圈功能之六快速实现下拉加载朋友圈功能——箭扣科技Arrownock
- EasyUI DataGrid使用formatter属性实现自定义功能
- EasyUI DataGrid使用formatter属性实现自定义功能
- Android App 实现分享功能及将应用加入分享列表 (分享功能可自定义需要分享的APP)
- 线程的挂起与唤醒之实现app加载广告点击跳转功能
- 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)
- 如何在App中实现朋友圈功能之二快速实现用户信息的自定义——箭扣科技Arrownock
- 【自己动手写类加载器1】实现加密功能:生成加密class文件,复制到bin目录下,AppClassLoader加载出错
- 自定义View实现擦除蒙版显示图片功能/自定义View的存储/自定义View的属性
- 如何在App中实现朋友圈功能之七快速实现上拉加载朋友圈功能——箭扣科技Arrownock