基于Android-Skin-Loader实现换肤效果

skin-loader框架的换肤是通过插件化的形式替换资源文件,实现换肤效果。好处是可以在线更新皮肤换肤

android-skin-loader源码

Demo样例

流程

整个框架大概的流程是加载皮肤包,找到被标记的控件,通过自定义的Factory工程过滤掉其他控件,使用皮肤包中的资源文件更新被标记的ui。

使用操作

1、导入android-skin-loader框架包
androidStudio File->new->import Module选择android-skin-loader
项目右键->open Module Setting->app中加载依赖android-skin-loader库

2、在MyApplication 初始化框架

SkinManager.getInstance().init(this);
SkinManager.getInstance().load();

3、需要换肤的activity需要继承skin-loader中的BaseActivity
需要换肤的控件添加skin:enable=”true”,控件xml添加命名空间xmlns:skin=”http://schemas.android.com/android/skin”

4、准备需要替换的color或drawable同名的资源文件包将其打包,重命名以.skin结尾
本地测试可以使用adb命令将.skin包放在sdcard
adb push 文件目录/test.skin /sdcard

样例代码

xml文件,使用databinding,不知道的自行百度

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:skin="http://schemas.android.com/android/skin">
 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">
  <LinearLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:orientation="horizontal">
   <Button
    android:id="@+id/btn_default"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/text_color"
    android:background="@color/button_background"
    skin:enable="true"
    android:text="默认皮肤"/>
   <Button
    android:id="@+id/btn_change_skin"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:textColor="@color/text_color"
    android:background="@color/button_background"
    skin:enable="true"
    android:text="更改皮肤"/>
   <Button
    android:id="@+id/btn_add"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:textColor="@color/text_color"
    android:background="@color/button_background"
    skin:enable="true"
    android:text="动态添加布局"/>
  </LinearLayout>
  <TextView
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:textColor="@color/text_color"
   android:text="文字文字文字文字文字文字"
   skin:enable="true" />
  <ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:src="@drawable/skin"
   skin:enable="true"/>
  <LinearLayout
   android:id="@+id/add_layout"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   skin:enable="true"
   android:orientation="vertical">
  </LinearLayout>

 </LinearLayout>
</layout>
public class SkinChangeAct extends BaseActivity{
 private ActivitySkinchangeBinding binding;
 //skin包名
 private String SKIN_NAME = "test.skin";
 //skin皮肤包的路径
 private String SKIN_DIR = Environment.getExternalStorageDirectory()+ File.separator+SKIN_NAME;
 @Override
 public void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  binding = DataBindingUtil.setContentView(this, R.layout.activity_skinchange);
  //更换皮肤
  binding.btnChangeSkin.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    File skin = new File(SKIN_DIR);
    if(skin == null || !skin.exists()){
     Toast.makeText(getApplicationContext(), "请检查" + SKIN_DIR + "是否存在", Toast.LENGTH_SHORT).show();
     return;
    }

    SkinManager.getInstance().load(skin.getAbsolutePath(), new ILoaderListener() {
     @Override
     public void onStart() {
      System.out.println("start");
     }

     @Override
     public void onSuccess() {
      System.out.println("onSuccess");
     }

     @Override
     public void onFailed() {
      System.out.println("onFailed");
     }
    });
   }
  });
  //恢复默认皮肤
  binding.btnDefault.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    SkinManager.getInstance().restoreDefaultTheme();
   }
  });
  //动态加载控件
  binding.btnAdd.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    dynamicAddTextView();
   }
  });
 }
 /**动态添加textview*/
 private void dynamicAddTextView() {
  TextView     textView = new TextView(this);
  RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  params.addRule(RelativeLayout.CENTER_IN_PARENT);
  textView.setLayoutParams(params);
  textView.setTextColor(SkinManager.getInstance().getColor(R.color.text_color));
  textView.setText("hellohello");
  textView.setTextSize(28);
  //将动态添加的布局也更换皮肤,否则之前添加的不能更改
  List<DynamicAttr> mDanamicAttr = new ArrayList<DynamicAttr>();
  mDanamicAttr.add(new DynamicAttr(AttrFactory.TEXT_COLOR,R.color.text_color));
  dynamicAddView(textView,mDanamicAttr);
  binding.addLayout.addView(textView);
 }
}

资源文件color.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="colorPrimary">#3F51B5</color>
 <color name="colorPrimaryDark">#303F9F</color>
 <color name="colorAccent">#FF4081</color>
 <color name="text_color">#ff0000</color>
 <color name="button_background">#00ff00</color>
</resources>

skin皮肤包中的资源文件color.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="colorPrimary">#3F51B5</color>
 <color name="colorPrimaryDark">#303F9F</color>
 <color name="colorAccent">#FF4081</color>
 <color name="text_color">#ffff00</color>
 <color name="button_background">#00ffff</color>
</resources>

对比一下,只是更改了数值,名字相同。

框架迭代,增加功能

android-skin-loader框架是没有对于src属性的修改,案例中使用imageView模拟了src的更改。
在AttrFactory中增加对于src的支持

public class AttrFactory {

 public static final String BACKGROUND = "background";
 public static final String TEXT_COLOR = "textColor";
 public static final String LIST_SELECTOR = "listSelector";
 public static final String DIVIDER = "divider";
 //增加src属性
 public static final String SRC="src";

 public static SkinAttr get(String attrName, int attrValueRefId, String attrValueRefName, String typeName){

  SkinAttr mSkinAttr = null;
  System.out.println("attrName="+attrName);
  if(BACKGROUND.equals(attrName)){
   mSkinAttr = new BackgroundAttr();
  }else if(TEXT_COLOR.equals(attrName)){
   mSkinAttr = new TextColorAttr();
  }else if(LIST_SELECTOR.equals(attrName)){
   mSkinAttr = new ListSelectorAttr();
  }else if(DIVIDER.equals(attrName)){
   mSkinAttr = new DividerAttr();
  }else if(SRC.equals(attrName)){
   //自定义加载src
   mSkinAttr =new SrcAttr();
  }else{
   return null;
  }

  mSkinAttr.attrName = attrName;
  mSkinAttr.attrValueRefId = attrValueRefId;
  mSkinAttr.attrValueRefName = attrValueRefName;
  mSkinAttr.attrValueTypeName = typeName;
  return mSkinAttr;
 }

 /**
  * Check whether the attribute is supported
  * @param attrName
  * @return true : supported <br>
  *   false: not supported
  */
 public static boolean isSupportedAttr(String attrName){
  if(BACKGROUND.equals(attrName)){
   return true;
  }
  if(TEXT_COLOR.equals(attrName)){
   return true;
  }
  if(LIST_SELECTOR.equals(attrName)){
   return true;
  }
  if(DIVIDER.equals(attrName)){
   return true;
  }
  //支持src
  if(SRC.equals(attrName)){
   return true;
  }
  return false;
 }
}

srcAttr继承SkinAttr定义加载src

public class SrcAttr extends SkinAttr{
 @Override
 public void apply(View view) {
  if(view instanceof ImageView){
   ImageView imageView = (ImageView) view;
   if(RES_TYPE_NAME_COLOR.equals(attrValueTypeName)){
    imageView.setImageResource(SkinManager.getInstance().getColor(attrValueRefId));
   }else if(RES_TYPE_NAME_DRAWABLE.equals(attrValueTypeName)){
    Drawable bg = SkinManager.getInstance().getDrawable(attrValueRefId);
    imageView.setImageDrawable(bg);
   }
  }
 }
}

各种控件的支持都可以自己添加。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android使用SkinManager实现换肤功能的示例

    试着用鸿洋大神写的SkinManager实现了换肤功能. 一.配置 在app下build.gradle中添加依赖: //换肤功能 compile 'com.zhy:changeskin:4.0.2' 这样就配置好了,然后在程序入口进行初始化. 二.全局初始化 在自己创建的继承application的类中添加: //换肤sdk初始化 SkinManager.getInstance().init(this); 这个类肯定要在清单文件<application/>节点配置的. 接下来还需要注册. 三.

  • Android编程实现换肤功能实例

    本文实例讲述了Android编程实现换肤功能的方法.分享给大家供大家参考,具体如下: 本系列专题培训适用范围:初级Android程序员,即有J2SE基础和Android初级水平.J2SE基础是指掌握JAVA语法,1.5.1.6新增的语法不完全掌握也没关系.了解基本的面向对象思想.能编写简单的J2SE程序,掌握基本的调试方法,熟悉Swing更好.Android初级是指掌握Activity.Service.BroadcastReceiver.Intent.SQLite.UI组件的使用,能参照例子编写

  • Android开发实现切换主题及换肤功能示例

    本文实例讲述了Android开发实现切换主题及换肤功能.分享给大家供大家参考,具体如下: 废话不说先看效果: 创建ColorTheme类用于主题更换: public class ColorTheme { AppCompatActivity ap; public ColorTheme(AppCompatActivity _ap){ap=_ap;} public void updateTheme(int _data){ String data=Integer.toString(_data); Fil

  • Android实现换肤的两种思路分析

    本文分析了Android实现换肤的两种思路.分享给大家供大家参考,具体如下: 这里来了解换肤实现及不同方案的差异和使用场合. 一.从功能上划分 1) 软件内置多个皮肤,用户不能修改: 2) 官方提供皮肤下载,用户使用下载的皮肤: 3) 官方提供皮肤制作工具或方法,用户自制皮肤. 二.皮肤定义 软件皮肤包括图标.字体.布局.交互风格等,换肤就是换掉皮肤包括的部分或所有资源. 三.皮肤与APP分离 1)打包皮肤文件 默认格式是apk.例如Launcher,它的桌面皮肤格式是一个apk: 自定义的格式

  • Android应用开发中实现apk皮肤文件换肤的思路分析

    在android的项目开发中,都会遇到后期功能拓展增强与主程序代码变更的现实矛盾,也就是程序的灵活度. 由于linux平台的安全机制,再加上dalvik的特殊机制,各种权限壁垒,使得开发一个灵活多变的程序,变得比较困难,不像pc平台下那么容易. 这里实际上可以借鉴传统软件中扩展程序的方法: 也就是插件的实现. 如目前所有的浏览器,比如我们使用的eclipse,以及很多优秀的软件,都使用了此种方式. 这样轻松实现了软件的功能扩展,而升级功能时只用更新对应插件, 而不是需要更新整个应用,降低了程序的

  • 分析Android App中内置换肤功能的实现方式

    Android平台api没有特意为换肤提供一套简便的机制,这可能是外国的软件更注重功能和易用,不流行换肤.系统不提供直接支持,只能自行研究. 换肤,可以认为是动态替换资源(文字.颜色.字体大小.图片.布局文件--).这个使用编程语言来动态设置是可以做到的,例如使用View的setBackgroundResource.setTextSize.setTextColor等函数.但我们不可能在每个activity里对页面里的所有控件都通过调用这些函数来换肤,这样的程序代码难以维护.扩展,也违背了UI和代

  • Android 换肤技术资料整理

    Android换肤技术总结 背景 纵观现在各种Android app,其换肤需求可以归为 - 白天/黑夜主题切换(或者别的名字,通常2套),如同花顺/自选股/天天动听等,UI表现为一个switcher. - 多种主题切换,通常为会员特权,如QQ/QQ空间. 对于第一种来说,目测应该是直接通过本地theme来做的,即所有图片/颜色的资源都在apk里面打包了. 而对于第二种,则相对复杂一些,由于作为一种线上服务,可能上架新皮肤,且那么多皮肤包放在apk里面实在太占体积了,所以皮肤资源会在选择后再进行

  • android换肤功能 如何动态获取控件中背景图片的资源id?

    这个是在在做一个换肤功能时遇到的问题. 对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像R.drawable.background(喂,这不是废话嘛).这个换肤的方案原理就是,自身应用的资源名称是R.drawable.background,那皮肤包中应该也是这个名称,然后通过这个名称获取该资源在皮肤包中的具体id,代码: //先获取本地资源引用名称,type name是R.drawable.background中的"drawable"

  • Android实现apk插件方式换肤的实例讲解

    1.什么时候换肤? xml加载前换肤,如果xml加载后换肤,用户将会看见换肤之前的色彩,用户体验不好. 2.皮肤是什么? 皮肤就是apk,是一个资源包,包含了颜色.图片等. 3.什么样的控件应该进行换肤? 包含背景图片的控件,例如textView文字颜色. 4.皮肤与已安装的资源如何匹配? 资源名字匹配 步骤: 1.xml加载前换肤,意味着需要将所需要换肤的控件收集起来.因此要监听xml加载的过程. public class BaseActivity extends Activity { Ski

  • 基于Android-Skin-Loader实现换肤效果

    skin-loader框架的换肤是通过插件化的形式替换资源文件,实现换肤效果.好处是可以在线更新皮肤换肤 android-skin-loader源码 Demo样例 流程 整个框架大概的流程是加载皮肤包,找到被标记的控件,通过自定义的Factory工程过滤掉其他控件,使用皮肤包中的资源文件更新被标记的ui. 使用操作 1.导入android-skin-loader框架包 androidStudio File->new->import Module选择android-skin-loader 项目右

  • 基于webpack4+vue-cli3项目实现换肤功能

    起因 最近因公司需求,需要实现主题换肤功能,不仅仅是颜色的更改,还需要包括图片,字体等文件等更换,因此在百度里各种实现方案后,决定根据scss+style-loader/useable做换肤. 项目开始 首先我们用vue-element-admin这个开源的后台管理系统项目来做demo演示,为了便于做二次开发,下载vue-admin-template来开发. // 从github下载vue-admin-template clone https://github.com/PanJiaChen/vu

  • jQuery实现的网页换肤效果示例

    本文实例讲述了jQuery实现的网页换肤效果.分享给大家供大家参考,具体如下: 现在许多后台网站都有换皮肤的效果,今天我用 jquery 写了这个效果,主要思路是改变 link 标签的 href 属性值. html 代码如下: <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"/> <title>网页换肤效果</title&

  • jQuery实现简单的网页换肤效果示例

    本文实例讲述了jQuery实现简单的网页换肤效果.分享给大家供大家参考,具体如下: 这里有4个文件:skin.html.blue.css.green.html.red.html,都放在同一目录下. 1.skin.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&

  • 基于Vue结合ElementUI的换肤解决方案

    目录 写在前面 方案一.使用全局的样式覆盖(前端通用) 方案二.自定义自己的Element-ui配色 方案三.快速改变网站颜色 方案四.实时更换主色调 写在前面 换肤这个功能,不能算是很常见,但是也是有需求的,所以这里提供几种前端的换肤解决方案,供大家参考. 本文将介绍几种基于Vue.Element-UI的换肤实现方案,力争通俗易懂,易上手,希望大家喜欢~ 方案一.使用全局的样式覆盖(前端通用) 这个应该是最常见,也是大家最容易想到的,也是最容易实现的一种方案. 我们单独写一份样式表(css 文

  • js实现一键换肤效果

    本文实例为大家分享了js实现一键换肤效果的具体代码,供大家参考,具体内容如下 方法1 <!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8">   <meta http-equiv="X-UA-Compatible" content="IE=edge">   <meta name="

  • js+css简单实现网页换肤效果

    本文实例讲述了js+css简单实现网页换肤效果.分享给大家供大家参考,具体如下: 这里做了3套外观,分别使用不同文件夹下的同名css文件,那么怎样实现js替换加载呢? 3个按钮如下: <a id="skin1" href="javascript:void(0)" class="easyui-linkbutton" onclick="changeCss('default')">蓝色皮肤</a><br

  • JavaScript实现换肤效果(换背景)

    本文实例为大家分享了JavaScript实现换肤效果的具体代码,供大家参考,具体内容如下 换肤效果:点击不同图片,更换相应页面背景 实现思路 1.定义一组图片,每个src属性赋值背景图片路径 2.获取一组图片元素对象(得到伪数组) 3.for循环给图片绑定点击事件- - -onclick,事件处理程序中设置body元素对象的背景图片为- - -当前被点击的图片的路径 4.注意:body元素对象的获取为- - -document.body,js为背景图片路径赋值注意路径的拼接- - -docume

  • 基于Android实现可滚动的环形菜单效果

    效果 首先看一下实现的效果: 可以看出,环形菜单的实现有点类似于滚轮效果,滚轮效果比较常见,比如在设置时间的时候就经常会用到滚轮的效果.那么其实通过环形菜单的表现可以将其看作是一个圆形的滚轮,是一种滚轮实现的变式. 实现环形菜单的方式比较明确的方式就是两种,一种是自定义View,这种实现方式需要自己处理滚动过程中的绘制,不同item的点击.绑定数据管理等等,优势是可以深层次的定制化,每个步骤都是可控的.另外一种方式是将环形菜单看成是一个环形的List,也就是通过自定义LayoutManager来

  • js+css实现换肤效果

    本文实例为大家分享了js+css实现换肤效果的具体代码,供大家参考,具体内容如下 效果图如下: 需求:点击对应小圆点,下面内容颜色跟着改变 主要思路: 1.在css中把对应的样式先写好:2.获取小圆点给它绑定点击事件:3.获取当前点击元素的类名:4.将该类名设置给body: js主要考察的是获取属性值和设置属性值: <style>         *{             margin:0;             padding:0;             list-style: no

随机推荐