Ranger Skin 安卓应用换肤的最佳实践

简介

   Android原生应用一款优雅精致的插件化换肤框架。框架以安卓View绘制原理为基础,基于主流LayoutInflaterCompat.setFactory2方案,运用Kotlin协程与Flow进行高效封装,实现对View属性的AOP(面向切面编程)定制。通过此框架,开发者能轻松实现应用的个性化换肤功能,提升用户体验,同时保持代码的清晰与可维护性。
  RangerSkin是安卓设备上的轻量级换肤解决方案。历经百天性能压测,确保在不影响设备性能的前提下,为用户提供个性化的界面体验。无论是手机还是车机,RangerSkin都能轻松适配,让界面焕然一新。同时RangerSkin安全性也得到充分考虑,保障用户数据安全。选择RangerSkin,享受流畅而美观的换肤之旅。

优势

  • 皮肤包可工程独立。出色的项目安全和稳定性,对原工程侵入小,几乎没有改造风险
  • 采用增量订制的方式,项目适配改动工作小,支持项目分期适配
  • API极简,功能强大,涵盖几乎所有原生换肤定制场景
  • 支持minifyEnabled和shrinkResources
  • 性能的极致要求,充分验证,开发者无需关注内存泄漏等性能风险

效果演示

在这里插入图片描述

方案对比

  想要了解换肤方案和主流实践的同学请移步对 Android 应用换肤方案的总结,文章已经进行较为深度的对比总结,且文中提过的框架早已不再维护,作者认为没有可比性,在此不再进行赘述。前期设计和研发SDK借鉴了文章中提到的主要的细节的点尤其是各方案的不足,并在RangerSkin中进行补充完善。在此对文章作者开发者如是说以及相关方案框架的作者表示感谢。

接入流程

  1. 集成
    SDK版本要求和注意事项: 安卓21及以上,Kotlin1.4及以上版本(项目中如果不存在Kotlin可以不用关注)。
repositories {
    mavenCentral()
}
dependencies {
    implementation "io.github.rangerleoio.rangerskin:skin-lite:1.0.0" //请及时同步最新Release SDK版本
}
  1. 适配流程
               Rang.drawio.png

  2. SDK支持换肤的属性脑图
    rangerskin-lite.png

  3. 属性定制
    扩展定制的Api概览

    //获取动画
    Int.getAnim()
    //获取颜色
    Int.getColorStateList()
    Int.getColor()
    //获取背景
    Int.getBackground()
    //获取尺寸
    Int.getDimension()
    //获取文本
    Int.getString()
    //获取资源名称
    Int.getRaw()
    //获取drawable
    Int.getDrawable()
    //设置背景
    View.setBackground2(Int)
    //设置src
    ImageView.setImageDrawable2(Int)
    //设置字体颜色
    TextView.setTextColor2(Int)
    //设置字体大小
    TextView.setTextSize2(Int)
    //设置文本
    TextView.setText2(Int)

  代码示例

    ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 0 ).let {
        //尺寸
        it.topMargin = R.dimen.dp_50.getDimension().toInt()  
        it.topToBottom = R.id.demo_view  
        it.startToStart = R.id.demo_view  
        it.endToEnd = R.id.demo_view  
        TextView(this).apply {  
            layoutParams = it  
            //Alternatively,use the View#obtainSingleSkinJob method  
            addOnSkinChangeListener {  
                //动态文本
                setText2(R.string.extra)  
                //动态尺寸
                setTextSize2(R.dimen.sp_20)
                //动态颜色
                setTextColor2(R.color.blue_100)  
            }  
        }  
    }.also { binding.root.addView(it) }

示例演示的为动态代码添加View的场景

完整Demo请访问:https://github.com/RangerLeoIo/RangerSkin

制作皮肤包

  RangerSkin是通过替换同名资源设置View的属性的方式实现,因此换肤锚点在于XML中引用资源文件名称(以此类推,在复杂的场景中只要能满足该条件即可实现换肤功能,方便开发者自行进行场景化定制)。与此同时,SDK的加载方案是增量设计的,即SDK会优先加载皮肤包的资源如果没有则会使用原有资源。请认真阅读此段描述,敲黑板~~~。

          001.png
  如图:res-c01为将要制作的主题资源文件夹。以动画资源left_out.xml为例。主题包中的资源名称与应用中的名称必须保持一致。皮肤制作的工作只要修改res-c01中left_out.xm的内容使之成为皮肤包需要的样式即可。(该示例为主工程和皮肤包工程同工程实例,建议为不同工程)
  对于皮肤工程提供gradle脚本支持,用于规范和简化打皮肤包流程:

def ignoreTasks = ['kotlin', 'java', 'aidl', 'java', 'dex', 'kapt', 'dataBinding', 'annotationProcessor', 'ksp','apklistingfileredirect'] //皮肤包res路径
def skinRes = ['src/main/res-c01'] //皮肤包res路径
def skinName = 'CO1' //皮肤包名称
android {  
    if (isSkinPackage.toBoolean()) {  
        sourceSets.main {  
            res.srcDirs = skinRes
            manifest.srcFile 'src/main/AndroidManifest2.xml'
        }  
        tasks.configureEach { task ->  
            ignoreTasks.forEach {  
                if (task.name.containsIgnoreCase(it)) {  
                    task.enabled = false  
                }  
            }  
        }  
        applicationVariants.configureEach { variant ->  
            variant.getPackageApplicationProvider().configure {  
                it.outputDirectory = new File(rootProject.buildDir.absolutePath + "/skins/${variant.buildType.name}")  
            }  
            variant.outputs.configureEach {  
                outputFileName = "${skinName}.skin"  
            }  
      }  
}

  执行app的assembleReslease或者assembleDebug会在工程根目录的build/skin中的release或者debug文件夹中生成生产皮肤包,皮肤包的后缀以.skin结尾。
  最后将皮肤包放置在指定的资源目录(放置方式可以是系统集成、可以放置在asset文件夹、也可以网络动态下发,根据自身应用实际需要的使用场景进行放置)。然后应用在所需的场景下触发SDK加载即可。

关于作者&Github链接

  RangerSkin这个名字,其实源自我的英文名字“Ranger Leo”。作为摸爬滚打了10年的老程序员,我在行业领域经历了不少风风雨雨,也积累了许多宝贵的经验。

  这么多年来,我遇到了无数的问题和挑战。有些问题本身就没有完美的解决方案,有些则在Kotlin普及和AGP7之后,开源方案出现了断档,而我却乐于寻找和实践最佳解决方案。因此,我自研了进程通信、进程消息总线、换肤等项目,希望能为行业带来一些新的思考和解决方案。

   RangerSkin不仅仅是一个项目名称,它更代表了我对技术的热情和追求。我希望通过这个项目,能够为开发者们提供一个灵活、稳定且易于使用的界面定制方案,满足他们对性能和稳定性的需求。 愚人浅见,望各路英豪不吝赐教。

  此外,特别声明,RangerSkin本次释放为lite版。和完整版相比,仅功能存在阉割和内存性能上的微小差异。不影响正常使用,且作者会长期维护。创作不易,请尊重别人的劳动成果,共同营造良好环境。如需完整版请联系作者。

  您的支持是我更新的动力,欢迎评论转发。详细接入介绍请点击Github链接:RangerSkin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值