✤ Mar 11, 2015 ✤
好吧,其实这个是之前做的项目中遇到的一个小问题。当时的情况是这样的,我们一直用qml开发app,然后头头希望我们的程序能够有换肤功能,并且在每种皮肤下,都可以替换不同颜色。也就是标题所说的“又可以换肤,每种皮肤下又可换多种颜色”。
嗯,分析下要实现的需求。
换皮肤的话,那就要求在制作页面+组件的时候要小心,尤其是组件的时候,将逻辑功能control和显示样式style进行拆分。然后把style统一放在某个文件夹下,通过一个变量存储style文件夹的地址,然后换肤的过程就是替换style文件夹地址的过程。嗯,类似如下:
图中嘛,皮肤1和皮肤2文件夹内都有一套对应组件的style文件。然后替换不同的地址,造成了组件样式的变化。同时,因为把所有逻辑功能等放在了control文件里,所以样式style文件中,只有外观的定义修改起来也相对简单,并且接口什么的不会因为样式的改变而改变。
再说说换颜色,这个很好实现,我们原来在编写代码的时候,颜色值都是硬编码在代码中的,那么只要把之前用到的颜色值进行归类,然后替换成全局的颜色变量就好了。
不过现在的问题就是,将两者组合起来后,因为不同的皮肤,对于颜色的多少啊,位置啥的定义都不相同,所以提取出来的颜色该以什么结构放在项目中。为了解决这个问题,我在每个皮肤文件夹内都有一个调色板文件,然后在全局有个取色器文件。然后根据当前所选的皮肤来进行取色。嗯,大概的结构如下:
大概就是这样的一个结构,不过在具体实现的时候当然没有就这样把取色器代码放在根上,这样多乱啊=3=
代码如下:
//ColorPalette.qml 即上文所说的取色器
pragma Singleton
import QtQuick 2.4
Item {
id:colorRoot
property string __colorType: "blue" //主题颜色
property string __colorComponentUrl: "."+"/ColorTable.qml" //主题URL
property Component __colorComponent: null
property var __colorTable
function initComponent() {
if (__colorComponent === null) {
colorRoot.__colorComponent = Qt.createComponent(colorRoot.__colorComponentUrl)
if (colorRoot.__colorComponent.status === Component.Ready) {
colorRoot.__colorTable = colorRoot.__colorComponent.createObject(colorRoot);
}
}
}
function color(type) {
colorRoot.initComponent()
try {
if (colorRoot.__colorTable[colorRoot.__colorType].hasOwnProperty(type)){
return colorRoot.__colorTable[colorRoot.__colorType][type]
}else{
return "#000000"
}
}catch (err) {
return "#000000"
}
}
}
下面是每个皮肤里的调色板示例:
//ColorTable.qml 即调色板
import QtQuick 2.4
QtObject {
readonly property var blue: {
1:"#cee9f9",
2:"#90bcd6",
3:"#c0d0df",
4:"#ffffff",
5:"#57a2d8",
6:"#007aff",
7:"#aae0ff",
8:"#227bdd",
9:"#3a6ca9",
10:"#7099bf",
}
readonly property var red: {
1:"#ffe3e3",
2:"#ffa3a3",
3:"#f5d0d1",
4:"#ffffff",
5:"#57a2d8",
6:"#007aff",
7:"#aae0ff",
8:"#227bdd",
9:"#ffbcc0",
10:"#eb7777",
}
}
可以看到在这个皮肤的调色板中,一共定义了2种色调,一个叫做blue
,一个叫做red
,然后每种色调里面都用到了10种颜色。假设在组件里的某个颜色你需要用9号颜色,可以类似ColorPalette.color(9)
这么写。
最后要注意的事,由于当时项目不要求有动态换肤,或者说是用户自己在程序里换肤这个功能,所以你看到在上面的ColorPalette.qml
代码中,创建调色板的Component
只有一次,而没有监控__colorComponentUrl
里的主题url的变化,当它变化的时候重新createComponent
。
嗯,酱油结束,继续干活去,嘿!( ̄▽ ̄)"