UI组件化--干掉shape终极一战(3)

  • LoadingView

  • ShimmerLayout

  • uikit-module

  • flatButton

  • roundView

  • load

  • dialog

  • imageSelect

  • toast

工程分层

工程架构可以分为5层,分别是:基础控件、组合控件、业务UI组件、桥接、demo。

  • 基础控件:提供原子能力,单点控件,比如层叠布局FlowLayout、骨架控件ShimmerLayout、按钮Flatbutton

  • 组合控件:会依赖基础控件,比如Dialog、ImageSelector,这些控件UI会比较复杂,所以会用到FlatButton、ShimmerLayout等基础组件来提高开发效率

  • 业务UI组件:这个就是我们真正要实现的UI组件,基于设计要求定制开发,在基础控件和组合控件上配置业务偏好,组合成业务组件,开发工作量比较小

  • 桥接:业务层不感知UI组件的个数和依赖关系,业务层只依赖uikit,而UI组件的依赖管理收敛到uikit中,这样的好处就是,后续迭代只在uikit维护依赖关系即可

  • Demo: 一个好的组件除了使用文档,还需要有直观的示例代码,demo可以直接集成到调试面板中

架构分层如下图:

一个好的架构应该层次分明、低耦合、高扩展,对组件的增删支持的足够友好,任何组件都能准确的找到对应的分层,并且不会改动到已有代码,所以review一下刚刚设计的架构,基本上满足需求,架构设计符合预期。架构设计好之后的步骤就是实施了,如何和现有的工程做结合呢,UI组件按阶段可以分为:开发阶段、稳定阶段,理想的开发模式为开发阶段在宿主工程中开发调试,但是放宿主工程中会带了编译慢的问题,组件开发和业务是接耦的,所以希望代码在宿主工程,demo和组件开发可以单独运行,当组件开发完成,到了稳定阶段,组件代码修改频率降低,同时加快编译速度,UIKit组件发布到远程maven仓库,最终uikit工程独立出来,单独迭代,下面是工程架构实现

UI组件和宿主打包编译

settings.gradle

includeIfAbsent ‘:uikit:uikit’

includeIfAbsent ‘:uikit:demo’

includeIfAbsent ‘:uikit:imgselector’

includeIfAbsent ‘:uikit:roundview’

includeIfAbsent ‘:uikit:widget’

includeIfAbsent ‘:uikit:photodraweeview’

includeIfAbsent ‘:uikit:flatbutton’

includeIfAbsent ‘:uikit:dialog’

includeIfAbsent ‘:uikit:widgetlayout’

includeIfAbsent ‘:uikit:statusbar’

includeIfAbsent ‘:uikit:toolbar’

common_business.gradle中一键依赖

apply from: rootProject.file(“library_base.gradle”)

dependencies {

.​…

implementation project(“:uikit:uikit”)

}

UI组件独立编译

uikit/shell/settings.gradle

include ‘:app’

includeModule(‘widget’,‘…/’)

includeModule(‘demo’,‘…/’)

includeModule(‘flatbutton’,‘…/’)

includeModule(‘imgselector’,‘…/’)

includeModule(‘photodraweeview’,‘…/’)

includeModule(‘roundview’,‘…/’)

includeModule(‘uikit’,‘…/’)

includeModule(‘widgetlayout’,‘…/’)

includeModule(‘dialog’,‘…/’)

includeModule(‘statusbar’,‘…/’)

includeModule(‘toolbar’,‘…/’)

def includeModule(name, filePath = name) {

def projectDir = new File(filePath+name)

if (projectDir.exists()) {

include ‘:uikit:’ + name

project(‘:uikit:’ + name).projectDir = projectDir

} else {

print(“settings:could not find module $name in path $filePath”)

}

}

UI组件lib的build.gradle中

if (rootProject.ext.is_in_uikit_project) {

apply from: rootProject.file(‘…/uikit.gradle’)

} else {

apply from: rootProject.file(‘uikit/uikit.gradle’)

}

这样就实现了宿主工程UIKit代码单独运行的效果了

组件架构


组件可以分为2类:工具型、业务类型,2个类型的组件迭代思路差异非常的大,工具型组件,只要单点做到极致就ok了,整体比较简单,复用性也比较强,而业务型组件就会稍显复杂,既要考虑复用性,也要考虑可扩展性,下面分别介绍这2个类型组件的实现思路

工具型

工具型组件迭代的思路就是不断的完善基础能力,尽可能的功能全面,在已有的能力上不断的支持新的功能,比较重要的就是兼容已有api,比较代表性的组件有FlatButton、RoundView、StatusBar,可以参考下FlatButton&RoundView迭代历程:

业务型

如何做好一个业务组件呢,实现可以是具象的,也可以是抽象的,好的组件设计应该是2者兼备,最底层的实现应该是足够抽象,而上层实现又应该是具象的,所以需要带着容器化的思路来实现,那么怎么个思路呢,如下图:

组件实现


下面以FlatButton为例介绍组件实现方式,其它组件实现思路类似。在实现前,我们先看下视觉稿

按钮样式特别多,实现方式也可以有很多种,现有工程也给出了实现方案,具体如下:

第一步:分别定义noraml下的shape和pressed的shape,如果enable = false,还得再定义一个dissable的shape

normal (ui_standard_bg_btn_corner_28_ripple)

<?xml version="1.0" encoding="utf-8"?>

<ripple xmlns:android=“http://schemas.android.com/apk/res/android”

android:color=“@color/button_pressed_cover”>

<item

android:drawable=“@drawable/ui_standard_bg_btn_corner_28_enable”>

pressed(ui_standard_bg_btn_corner_28_disable)

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android=“http://schemas.android.com/apk/res/android”

android:shape=“rectangle”>

<gradient

android:angle=“0”

android:endColor=“@color/button_disable_end”

android:startColor=“@color/button_disable_start”

android:useLevel=“false”

android:type=“linear” />

第二步:定义selector

selector(ui_standard_bg_btn_corner_28)

<?xml version="1.0" encoding="utf-8"?>

第三步:使用

<TextView

android:background=“@drawable/ui_standard_bg_btn_corner_28”

android:textColor=“@color/white”/>

这样按钮的背景按压就实现了,如果在此基础上,文字也需要按压态,那么就重复上面的步骤,对颜色再创建一个选择器,当实现完上面UI定义的样式后,工程中的画风如下:

我是谁,我在哪里,这该怎么玩,长得都差不多,基本没有开发体验,复用性、扩展性都非常的差,如果来个UI大改版,又得从头再来一次。那怎么解决上面的问题呢,答案是定义按钮通用能力,业务上层再实现,按这个思路做,需要删除上面所有shape、selector,然后自定义控件,我们都知道,上面定义的shape、selector xml文件,android系统最终都是会解析生成对应的对象,所以我们借鉴一下系统代码,实现起来就so easy

看下这个shape xml

<shape xmlns:android=“http://schemas.android.com/apk/res/android”

android:shape=“rectangle”>

<gradient

android:angle=“0”

android:endColor=“@color/button_disable_end”

android:startColor=“@color/button_disable_start”

android:useLevel=“false”

android:type=“linear” />

解析后的对象为GradientDrawable

public void setOrientation(Orientation orientation)

public void setColors(@Nullable @ColorInt int[] colors)

public void setCornerRadii(@Nullable float[] radii)

public void setStroke(int width, @ColorInt int color)

也就是说,xml中定义的属性,代码中都可以实现,除了GradientDrawable,还会用到RippleDrawable实现水波纹,同理文字颜色选择器代码中对应的为ColorStateList,有了上面铺垫,具体实现如下:

第一步:定义自定义属性
第二步:核心实现逻辑

private fun setBackgroundCompat() {

val stateListDrawable = createStateListDrawable()

val pL = paddingLeft

val pT = paddingTop

val pR = paddingRight

val pB = paddingBottom

background = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && isRippleEnable) {

val rippleDrawable = RippleDrawable(createRippleColorStateList(), stateListDrawable, null)

rippleDrawable

} else {

stateListDrawable

}

setPadding(pL, pT, pR, pB)

}

private fun createStateListDrawable(): StateListDrawable {

var normalDrawable = StateListDrawable()

normalDrawable.addState(

intArrayOf(android.R.attr.state_pressed),

createPressedDrawable()

)

最后

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-7NgX34w5-1715877489265)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值