索引
和核心包一样,UI 支持 htconfig 全局变量配置全局字体、文字颜色等,格式如下:
<script>
htconfig = {
uiTheme: {
font: '14px arial', // 所有组件的字体
inputBackground: 'rgb(22,27,34)' // 所有输入框背景色
}
}
</script>
<script src="ht.js"></script>
<script src="ht-ui.js"></script>
如上所示,在 htconfig 对象中通过 uiTheme 可以为页面中的所有 UI 组件统一指定某些配置,如字体等;
需要注意,htconfig 必须在 ht.js 和 ht-ui.js 之前声明;uiTheme 中可用的配置属性列举如下:
baseColor 用于 RadioButton、CheckBox、ToggleButton,普通按钮的文字颜色和边框,文本框选中文本的背景色等font 字体,可统一修改所有组件中文字的字体textColor 文字颜色,可统一修改所有组件中文字的颜色borderColor 边框颜色,可统一修改有边框组件(TextField、TextArea、Panel、Dialog、ColorPane、 DateTimePane 等)的边框颜色headerBackground 头背景,可统一修改 TableHeader、PropertyPane、Dialog、Panel 的头部背景颜色iconColor 图标颜色,可统一修改 RadioButton、CheckBox 未选中状态的边框颜色,ComboBox 的下拉图标的颜色,Panel 和 Dialog 的 tool 按钮图标的颜色,TreeView 和 TreeTableView 的展开合并图标的颜色lineColor 分割线颜色,可统一修改列表类组件(列表、树、表格等)的行列分割线hoverBackground hover 状态的背景色,可统一修改 RadioButton、CheckBox 未选中状态的 hover 背景色,ComboBox 下拉图标的 hover 状态的背景色,列表类组件(列表、树、表格等)的 hover 背景色、普通按钮 hover 状态的背景色activeBackground active 状态的背景色,可统一修改 RadioButton、CheckBox 未选中状态的 active 背景色,ComboBox 下拉图标的 active 状态的背景色,普通按钮 active 状态的背景色inputBackground 输入框组件的背景色popupBackground 弹出类组件,如:Dialog、ContextMenu、下拉列表等组件的背景popupBoxShadow 弹出类组件,如:Dialog、ContextMenu、下拉列表等组件的阴影okFirst 颜色选择器和日期选择器的弹出面板中的确定按钮是否显示在左侧,默认为 false (即显示在右侧)rowSelectBackground 列表类组件(ListView、TreeView、TableView、TreeTableView、PropertyView)选中的行背景色UI 库对界面外观提供了一套类似 CSS 的配置方式(Style 机制),允许开发者在页面内部或外部文件配置界面风格,从而使界面风格和业务代码分离,便于维护和复用。
内部页面方式:
<!-- 在页面中创建 script 标签,ref 值为 ht-style,内容遵循下面的格式 -->
<!-- type 可以为任意值,但是不要指定为 javascript,因为这会导致 script 标签内的内容被当作 JavaScript 解析 -->
<script rel='ht-style' type='any'>
({
'ht.ui.Button': {
icon: 'node_image' // 所有按钮的图标改为 'node_image'
}
})
</script>
外部文件方式:
<!-- 在页面中创建 link 标签,rel 值为 ht-style,href 值为样式文件路径,mystyle.style 文件格式遵循上面方式中 script 标签的内容格式 -->
<link rel='ht-style' href='mystyle.style'>
本质上来说,样式文件是一段 JavaScript 代码,因此在这里面声明变量也是允许的:
<script rel='ht-style' type='any'>
var nodeIcon = 'node_image'; // Button 和 TextField 的 icon 样式都指向这个变量,方便统一修改
@import(./test.style) // 引入 test.style 文件,注意 @import 必须独占一行
({
'ht.ui.Button': {
icon: nodeIcon,
border: new MyLineBorder('red') // test.style 引入了 MyLineBorder
},
'ht.ui.TextField': {
icon: nodeIcon
}
})
</script>
注意上面代码中的 通过 @import 引入了其它文件,./test.style 的文件内容:
// 自定义一个 Border
var MyLineBorder = function(color) {
MyLineBorder.superClass.constructor.call(this, 2, color);
}
ht.Default.def(MyLineBorder, ht.ui.border.LineBorder, {});
script 和 link 这两种方式可以混用,也可以在一个页面中创建多个 script 和 link;但是需要注意:无论使用哪种方式,script 或 link 标签一定要放置在引入 ht-ui.js 之前。
每个组件可用的样式属性请查阅相应的 API 文档。
基础选择器
* 通用选择器,匹配任何组件;优先级:1element 类型选择器,如 ht.ui.Button: {background: 'red'} 匹配所有按钮;优先级:1&style 样式选择器,如 &styleName: {background: 'red'} 匹配 view.setStyle('styleName') 这种设置了 style 属性的组件;优先级:10element&style 类型样式选择器,如 ht.ui.Button&styleName: {background: 'red'} 匹配所有 style 属性值为 styleName 的 Buttonelement* 子组件选择器,如 ht.ui.ButtonBase: {background: 'red'} 匹配 ButtonBase 类或子类:nth-child() 子组件位置选择器,如 ht.ui.ButtonBase:nth-child(1): {background: 'red'} 匹配容器中第一个 ButtonBase 类或子类;优先级:10,括号内的位置支持:1 开始的last:匹配最后一个子组件odd: 匹配下标为奇数的子组件even: 匹配下标为偶数的子组件组合选择器(basic 代表任意基础选择器, any 指任意基础选择器或组合选择器)
basic basic 后代选择器(可多层嵌套),如 ht.ui.BorderLayout &styleName: {background: 'red'} 匹配 BorderLayout 容器中所有 style 属性值为 styleName 的子孙组件basic>basic 直接后代选择器(可多层嵌套,注意>左右不要有空格),如 ht.ui.BorderLayout>&styleName: {background: 'red'} 匹配 BorderLayout 容器中所有 style 属性值为 styleName 的子组件(TableLayout 比较特殊,直接子组件是指 TableRow 中的子组件,而不是指 TableRow)any, any 多组件选择器(可多个组件),如 ht.ui.Button&styleName, ht.ui.TextField: {background: 'red'} 匹配所有 TextField 和 style 属性值为 styleName 的 Button现在,后代选择器有更简单和明确的书写方式:
'&header': {
font: '12px arial'
},
'&header &title': {
background: 'red'
},
'&header &button': {
icon: 'node_image'
}
可以简化成下面的写法:
'&header': {
font: '12px arial',
'&title': {
background: 'red'
},
'&header': {
icon: 'node_image'
}
}
可以看到,通过嵌套的方式,不但代码量更少,层次结构也更加明确
上面的列表中,只有通用选择器、类型选择器、样式选择器说明了优先级,其它选择器的优先级如何计算?答案是:相加。下面是几个例子:
ht.ui.BorderLayout &styleName: {background: 'red'} 优先级为:(ht.ui.BorderLayout)1 + (&styleName)10 = 11ht.ui.BorderLayout>&styleName: {background: 'red'} 优先级为:(ht.ui.BorderLayout)1 + (&styleName)10 = 11ht.ui.BorderLayout>&styleName:nth-child(odd): {background: 'red'} 优先级为:(ht.ui.BorderLayout)1 + (&styleName)10 + (:nth-child(odd))10 = 21ht.ui.BorderLayout ht.ui.Button: {background: 'red'} 优先级为:(ht.ui.BorderLayout)1 + (ht.ui.Button)1 = 2ht.ui.Button&styleName, ht.ui.TextField: {background: 'red'} 当组件匹配 ht.ui.Button&styleName 规则时,优先级为 1 + 10 = 11 ;当组件匹配 ht.ui.TextField 规则时,优先级为 1样式值类型支持 JavaScript 中的所有标准数据类型,如 int、number、boolean 等,如果值需要经过某些特殊运算,则需要通过 function 指定:
// 样式配置:
({
'ht.ui.Button': {
textColor: 'black',
text: function() {
return 'test' + '2'; // 简单运算
},
// 创建并返回自定义的 Drawable
backgroundDrawable: new ht.ui.drawable.ColorDrawable('yellow'),
border: [ht.ui.border.LineBorder, 1, 'red] // 创建并返回自定义的 Border
}
})
当多个选择器选中了同一个组件,并且样式冲突时怎么处理?这就涉及到样式优先级的问题;看下面的例子:
// 样式配置:
({
'ht.ui.Button': { // 优先级:1
background: 'yellow',
textColor: 'black'
},
'ht.ui.HBoxLayout ht.ui.Button': { // 优先级: 2,ht.ui.HBoxLayout 优先级 1 + ht.ui.Button 优先级 1 = 2
background: 'green'
},
'ht.ui.Button&button-blue': { // 优先级 11,ht.ui.Button 优先级 1 + &button-blue 优先级 10 = 11
background: 'blue'
}
})
// JavaScript 代码,创建布局
var button1 = new ht.ui.Button(),
button2 = new ht.ui.Button(),
button3 = new ht.ui.Button(),
hBox = new ht.ui.HBoxLayout();
button3.setStyle('button-blue');
hBox.addView(button2, {marginLeft: 20, height: 'match_parent'});
hBox.addView(button3, {marginLeft: 20, height: 'match_parent'});
上面例子中,三条样式规则都配置了 Button 组件的 background 属性,其中 button1 只能匹配第一条规则,所以背景色为 yellow;button2 能匹配第一条和第二条规则,由于第二条规则优先级比较高,所以 button2 的背景色为 green;button3 能匹配三条样式规则,但是第三条规则优先级最高,所以 button3 的背景色为 blue
有时候我们需要为页面中所有的文本框设置 focus 状态的边框,参考下面的例子:
// 样式配置:
({
'ht.ui.TextField*': {
border: [ht.ui.border.FocusLineBorder, 1, '#d9d9d9', '#5cb85c'],
redrawOnFocus: true
}
})
自 4.0 开始 UI 库提供了一套全新的样式,这套样式中很多默认值可以通过 htconfig 对象重新配置,如文字颜色、字体等,参考下面的例子(点击顶部色块可切换整体风格):
如果直接从本地磁盘中打开
html可能会遇到浏览器跨域问题,如果碰到此类问题,可以访问在线版本:在线访问; 或尝试用Firefox浏览器打开
在这里例子中,通过 htconfig 对象配置了 baseColor 属性:
<script>
htconfig = {
uiTheme: { // 配置 UI 样式属性
baseColor: '#xxxxxx'
},
extendedUIStyles: { // 扩展样式
'ht.ui.Button': {
textColor: 'black'
}
}
}
</script>
uiTheme 中可以使用 extendUIStyles 配置样式规则(就像 <script rel="ht-style"></script> 那样),和 script 标签方式本质是一样的,只是通过 extendUIStyles 的方式定制的风格可以放到同一个文件中,方便传递共享
如果使用上面提到的静态样式,切换页面整体风格时不可避免的要刷新页面,用户在页面中的操作可能会丢失(比如文本框输入的内容),使用动态样式可以在不刷新页面的前提下切换风格,动态样式需要用到下面的 API:
ht.Default.loadUIStyle(name, config, callback) 加载动态样式ht.Default.removeLoadedUIStyle(name) 删除某个动态加载的样式ht.Default.clearLoadedUIStyles() 清除所有动态加载的样式ht.Default.invalidateUIStyles() 刷新页面中的组件适配新样式下面的代码展示了如何使用这几个 API:
// 假设之前加载过一个名为 green 的动态样式,现在要改为 dark 样式:
// 先删除 green 样式;如果要清除所有动态样式,也可以调用 ht.Default.clearLoadedUIStyles();
ht.Default.removeLoadedUIStyle('green');
// 加载 dark 样式
ht.Default.loadUIStyle('dark', 'styles/dark.style', function() {
// 样式是异步加载的,需要在加载完成的回调函数里刷新页面中的组件
ht.Default.invalidateUIStyles();
});
下面是一个例子:
如果直接从本地磁盘中打开
html可能会遇到浏览器跨域问题,如果碰到此类问题,请访问在线版本:在线访问; 或尝试用Firefox浏览器打开
UI 库内置了几个候选样式,如 button-obvious,如果需要着重提示某个按钮,只需要设置:
button.setStyle('button-obvious');
内置的候选样式列举如下:
button-warn 警告按钮button-obvious 重要按钮button-minor 次要按钮buttongroup 按钮组,此样式需要设置到 HBoxLayout 或 VBoxLayout 容器上,容器内部只能放 ToggleButtonprogressbar-thin 细长条进度条tablayout-line-outside Tab 头外部显示分割线tablayout-buttongroup Tab 头显示为按钮组textfield-search 搜索框样式通过 ht.Default.uiStyles 可以查看这些候选样式的定义