QMUILayout, 让 UI 开发更简单

简介: 在 Android UI开发过程中,我们会觉得非常繁琐的事情是什么呢?分隔线、圆角、边框、阴影、点击态等,在以往的实践中,我们都是通过 drawable 去实现的,非常麻烦。以分隔线为例,如果左右都打通,那还能复用,但现在的设计师都喜欢左边或右边有一定的 inset,而 inset 的值并非一成不变的,这不经意间就使得项目添加了数不清的 drawable,因此目前大多数人都开始尝试不使用 drawble 去解决这些问题了,QMUI 也不例外。

在 Android UI开发过程中,我们会觉得非常繁琐的事情是什么呢?分隔线、圆角、边框、阴影、点击态等,在以往的实践中,我们都是通过 drawable 去实现的,非常麻烦。以分隔线为例,如果左右都打通,那还能复用,但现在的设计师都喜欢左边或右边有一定的 inset,而 inset 的值并非一成不变的,这不经意间就使得项目添加了数不清的 drawable,因此目前大多数人都开始尝试不使用 drawble 去解决这些问题了,QMUI 也不例外。


QMUI 1.1.0 版本带来的新的组件套装 QMUILayout (QMUILinearLayout、QMUIRelativeLayout、QMUIFramelayout),这篇文章将介绍 QMUI 提出的解决方法。

点击态


点击态最为简单,QMUI 早已经提出用 alpha 来表示点击态,因此提供了了 QMUIAlpha 系列,QMUILayout 继承自 QMUIAlpha 系列,但默认禁止了 alpha 行为, 你可以通过以下两个方法开启:

// change alpha when pressed
setChangeAlphaWhenPress(boolean changeAlphaWhenPress);
// change alpha when disabled
setChangeAlphaWhenDisable(boolean changeAlphaWhenDisable)  

当然,点击时背景变灰也是非常常见的。qmui 最开始提供了一系列的用于 list item 的 drawable, 现在我们基本只需要 qmui_s_list_item_bg_with_border_none, 因为现在分割线不再受背景控制了。

分隔线


分隔线是平常使用得非常多的,上下分隔下用的较多,左右分隔线用得比较少,QMUILayout 都提供了 xml 和 java 代码的支持:

<declare-styleable name="QMUILayout">  
    ...
    <attr name="qmui_bottomDividerHeight" format="dimension"/>
    <attr name="qmui_bottomDividerColor" format="color|reference"/>
     <attr name="qmui_bottomDividerInsetLeft" format="dimension"/>
     <attr name="qmui_bottomDividerInsetRight" format="dimension"/>
     <attr name="qmui_topDividerHeight" format="dimension"/>
     <attr name="qmui_topDividerColor" format="color|reference"/>
    <attr name="qmui_topDividerInsetLeft" format="dimension"/>
    <attr name="qmui_topDividerInsetRight" format="dimension"/>
    <attr name="qmui_leftDividerWidth" format="dimension"/>
    <attr name="qmui_leftDividerColor" format="color|reference"/>
    <attr name="qmui_leftDividerInsetTop" format="dimension"/>
    <attr name="qmui_leftDividerInsetBottom" format="dimension"/>
    <attr name="qmui_rightDividerWidth" format="dimension"/>
    <attr name="qmui_rightDividerColor" format="color|reference"/>
    <attr name="qmui_rightDividerInsetTop" format="dimension"/>
    <attr name="qmui_rightDividerInsetBottom" format="dimension"/>
    ...
</declare-styleable>  

四个维度的支持,使用非常方便, java 接口:

/**
 * config the top divider
 */
void updateTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor);
/**
 * show top divider, and hide others
 */
void onlyShowTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor);
// same for others

其实现原理也很简单,就是在 dispatchDraw 里主动 draw 上去的,那我们为什么是在 dispatchDraw 而不是在 onDraw 里操作呢? 因为我们不想分隔线被子元素、背景等因素遮挡。

阴影、圆角、边框


这是 QMUILayout 最令人兴奋的地方,大家可以在 QMUIDemo 上体验下效果:

其实原理很简单,利用 android 5.0 后提供的 elevation 来实现的, 大多数人通过阅读官方文档或者别人的教材,了解了 elevation 可以控制 shadow 的大小,但是很少人知道 shadow 还会被另外一个因素所控制:outline 的 alpha。 有了这两个因素,可以更精确的控制 shadow 的深浅,能无限接近设计师的阴影要求,当然,除了阴影颜色,那是 QMUILayout 所不能控制的。


利用 outline 还可以用来实现圆角,以前我们用背景去实现圆角效果,但你需要非常小心的保护圆角背景不被子元素所覆盖,但 outline 不会有这个问题。outline 如此强大,如果还不知道它,那么赶紧去通过View.setOutlineProvider() 了解一下它吧。


但 outline 也有缺陷的,它没办法做到四个圆角分别控制,现实使用过程中,有一个圆角或三个圆角的情况比较少,所以我在 QMUILayout 中支持了 显示两个圆角的方法,但可惜的是会丢失阴影,现实总是不尽人意,尽自己最大努力就好。


另外一个比较关心的话题是, 4.x的手机怎么办?网页重构早就讲究降级兼容,所以我也认为没有必要让 4.x 和 5.x+ 保持同样的用户体验。因此在 4.x 下,阴影肯定是没办法使用的,只能使用圆角和边框,要使用它们,我们需要提供一个额外的参数: qmui_outerNormalColor, 这个参数是什么意思呢?这首先要理解圆角在 4.x 上的实现: 它的实现是在 dispatchDraw 后,draw 上一层 mask, 然后镂空中间部分,因此 qmui_outerNormalColor            就是 mask 的颜色,一般要与 QMUILayout 外部环境相同, 这样在用户眼中,看到的就是圆角了。如果你没有提供这个属性,那么圆角将不会生效。此外,它也无法解决 dialog 这种外部环境透明的场景。


接下来看看提供的非常有用的 API:

/**
 * use the shadow elevation from the theme
 */
void setUseThemeGeneralShadowElevation();  
/**
 * See {@link android.view.View#setElevation(float)}
 *
 * @param elevation
 */
void setShadowElevation(int elevation);
/**
 * See {@link View#getElevation()}
 *
 * @return
 */
int getShadowElevation();
/**
 * set the outline alpha, which will change the shadow
 *
 * @param shadowAlpha
 */
void setShadowAlpha(float shadowAlpha);
/**
 * get the outline alpha we set
 *
 * @return
 */
float getShadowAlpha();
/**
 * set the layout radius
 * @param radius
 */
void setRadius(int radius);
/**
 * set the layout radius with one or none side been hidden
 * @param radius
 * @param hideRadiusSide
 */
void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide);
/**
 * get the layout r
 * @return
 */
int getRadius();  
/**
 * the shadow elevation only work after L, so we provide a downgrading compatible solutions for android 4.x
 * usually we use border, but the border may be redundant for android L+. so will not show border default,
 * if your designer like the border exists with shadow, you can call setShowBorderOnlyBeforeL(false)
 *
 * @param showBorderOnlyBeforeL
 */
void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL);
/**
 * in some case, we maybe hope the layout only have radius in one side.
 * but there is no convenient way to write the code like canvas.drawPath,
 * so we take another way that hide one radius side
 *
 * @param hideRadiusSide
 */
void setHideRadiusSide(@HideRadiusSide int hideRadiusSide);
/**
 * get the side that we have hidden the radius
 *
 * @return
 */
int getHideRadiusSide();
/**
 * this method will determine the radius and shadow.
 *
 * @param radius
 * @param shadowElevation
 * @param shadowAlpha
 */
void setRadiusAndShadow(int radius, int shadowElevation, float shadowAlpha);
/**
 * this method will determine the radius and shadow with one or none side be hidden
 *
 * @param radius
 * @param hideRadiusSide
 * @param shadowElevation
 * @param shadowAlpha
 */
void setRadiusAndShadow(int radius, @HideRadiusSide int hideRadiusSide, int shadowElevation, float shadowAlpha);
/**
 * border color, if you don not set it, the layout will not draw the border
 *
 * @param borderColor
 */
void setBorderColor(@ColorInt int borderColor);
/**
 * border width, default is 1px, usually no need to set
 *
 * @param borderWidth
 */
void setBorderWidth(int borderWidth);  

QMUILayout 所有的 API 都由 IQMUILayout 所规范, 由 QMUILayoutHelper 所实现,如果你需要为自己的自定义 view 实现这些方法, 那么你可以在你的类中引入 QMUILayoutHelper,具体可以参考 QMUILinearLayout/QMUIFrameLayout/QMUIRelativeLayout


最后一点,关于性能,View.setOutlineProvider() 会存在性能消耗,不过就我们的测试数据统计,这点消耗是可以容忍的。目前 QMUILayout 已经为读书项目服务了几个版本了,稳定性应该是蛮好的,希望大家喜欢。

目录
相关文章
|
9天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
1月前
|
开发框架 JavaScript 前端开发
鸿蒙NEXT开发声明式UI是咋回事?
【10月更文挑战第15天】鸿蒙NEXT的声明式UI基于ArkTS,提供高效简洁的开发体验。ArkTS扩展了TypeScript,支持声明式UI描述、自定义组件及状态管理。ArkUI框架则提供了丰富的组件、布局计算和动画能力。开发者仅需关注数据变化,UI将自动更新,简化了开发流程。此外,其前后端分层设计与编译时优化确保了高性能运行,利于生态发展。通过组件创建、状态管理和渲染控制等方式,开发者能快速构建高质量的鸿蒙应用。
118 3
|
26天前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
84 8
|
29天前
|
JavaScript API 开发者
掌握ArkTS,打造HarmonyOS应用新视界:从“Hello World”到状态管理,揭秘鸿蒙UI开发的高效秘诀
【10月更文挑战第19天】ArkTS(ArkUI TypeScript)是华为鸿蒙系统中用于开发用户界面的声明式编程语言,结合了TypeScript和HarmonyOS的UI框架。本文介绍ArkTS的基本语法,包括组件结构、模板和脚本部分,并通过“Hello World”和计数器示例展示其使用方法。
61 1
|
6月前
|
Android开发 缓存 双11
android的基础ui组件,Android开发社招面试经验
android的基础ui组件,Android开发社招面试经验
android的基础ui组件,Android开发社招面试经验
|
1月前
|
缓存 测试技术 C#
使用Radzen Blazor组件库开发的基于ABP框架炫酷UI主题
【10月更文挑战第20天】本文介绍了使用 Radzen Blazor 组件库开发基于 ABP 框架的炫酷 UI 主题的步骤。从准备工作、引入组件库、设计主题、集成到 ABP 框架,再到优化和调试,详细讲解了每个环节的关键点和注意事项。通过这些步骤,你可以打造出高性能、高颜值的应用程序界面。
|
2月前
|
前端开发 开发者 UED
前端只是切图仔?来学学给开发人看的UI设计
该文章针对前端开发者介绍了UI设计的基本原则与实践技巧,覆盖了布局、色彩理论、字体选择等方面的知识,并提供了设计工具和资源推荐,帮助开发者提升产品的视觉与交互体验。
|
1月前
|
JavaScript 索引
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
115 0
|
3月前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
3月前
|
前端开发 JavaScript C#
C#开发者的新天地:Blazor如何颠覆传统Web开发,打造下一代交互式UI?
【8月更文挑战第28天】Blazor 是 .NET 生态中的革命性框架,允许使用 C# 和 .NET 构建交互式 Web UI,替代传统 JavaScript。本文通过问答形式深入探讨 Blazor 的基本概念、优势及应用场景,并指导如何开始使用 Blazor。Blazor 支持代码共享、强类型检查和丰富的生态系统,简化 Web 开发流程。通过简单的命令即可创建 Blazor 应用,并利用其组件化和数据绑定特性快速搭建界面。无论对于 .NET 还是 Web 开发者,Blazor 都是一个值得尝试的新选择。
128 1