AppCan开发框架详细介绍

1UI2.0UI1.0的对比

2012年初,我们发布了AppCan移动应用开发平台,在这个版本中,我们内置了基于JQMobile方案的CSS UI框架。这个框架可以帮助开发者遵循一套规则下,快速的开发应用。这套方案中主要采用了组合的概念。例如对一个按钮的描述,可以通过多个CSS类来组合进行定义,也可以通过视频了解更多。
这样通过不同的组合可以生成多变的效果。在实际商用应用开发过程中,它起到了帮助我们加快开发进度的作用。但是在开发过程中,我们还是遇到了一些问题,JQMobile CSS框架在这些问题上,表现得比较乏力:
1
1 自动填充宽度


上图中同样一个编辑框加上一个刷新按钮的组合。在不同分辨率下,如果希望,刷新按钮保持一个基本宽度,编辑框自动填充剩余区域,在不使用JS的情况下是很难做到的,如果使用百分比控制刷新钮的宽度,那么在低分辨率和高分辨率之间将会有非常大的偏差。
1
2 类名称过长
JQMobile
方案中,为了帮助开发者能够更直观的了解代码,每一个功能类的名称都比较长。例如ui-page ui-mobile-viewport等。这造成了网页代码大小变大,降低了解析速度。
1
3 类功能拆分度低
JQMobile方案中,很多类定义,代码重复较多,例如预制的多种色彩方案。同时由于拆分度低,经常需要重复定义类来覆盖其他类中的属性。
1
4 控件组合复杂
JQMobile
方案中,控件的实现代码量很大,一个按钮需要多个div span嵌套配合多个类才能实现。这造成开发中,界面代码量增大,不好控制界面。

我们综合各个项目中的开发经验,整理汇总了AppCan UI2.0架构,它继承了UI1.0的优点,并很好地解决了UI1.0的问题,可以使开发能够更加的简单。UI2.0框架图如下:

上图中,我们可以看到AppCan UI2.0框架在基础的屏幕适配(RESOLUTION ADAPTER CLASS)基础上,对元素基本属性进行了拆分。通过如下步骤来设定一个元素。
   定位-对元素进行布局,确定元素的现实位置大小等[LAYOUT CLASS]
   描边-对元素基础属性进行设定,例如边框圆角等
[BASE CLASS]
   添色-对元素的边框、文字和背景进行设定
[COLOR CLASS]
   插图-如果元素中需要图片,从资源中引入图片类
[RES CLASS]

基于基础元素之上,为了方便开发者,我们重新定义了控件,包含BUTTONLISTFOLDINPUTTABRADIOCHECKSWITCH。这些控件可以认为是UI2.0框架的具体事例。通过UI2.0完成的控件,代码大小和复杂度,都有明显的降低,如下例:


UI1.0
框架实现的按键

<div class="ui-btn ui-corner-all ui-shadow ui-btn-b"> 
  
<span class="ui-btn-inner ui-corner-all">
  <span class="ui-btn-text ">确定
</span>
</span>
</div>


UI2.0
框架实现的按键

<div class="btn btn-act ubb uc-t1 b-bla uinn c-blu2 c-m4 ">确定 </div>

从上述代码中可以看到,同样功能和效果的控件可以减少三分之二的代码,嵌套减少到一层,代码复杂度极大降低。
接着我们详细介绍如何使用UI2.0框架。

2UI2.0框架的设计来源——弹性盒子模型

弹性盒子模型是CSS3.0推出的一种布局机制。这种机制与常见的流式布局有很大区别。简单的理解为,流式布局是通过内容决定父容器大小,弹性盒子模型是,在指定大小的父容器里来为子元素分配空间,简单的流式布局例子。
效果:

代码:

<div style="display:inline;border:1px solid blue">
  
<div style="display:inline;background:#E00">aaaa </div>
  
<div style="display:inline;background:#0E0">bbbb </div>
</div>

上述代码中是一个简单的流式布局范例,第1行的div的宽度,是由第2和第3行的div宽度相加来决定的。即如果第2行或第3行的div宽度变化,第1行的宽度也会随之变化。我们调整一下代码,使用弹性盒子模型来布局。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
  
<div style="-webkit-box-flex:1;background:#E00">aaaa </div>
  
<div style="background:#0E0">bbbb </div>
</div>

上述代码中,指定第1行的div使用BOX方式布局子元素。并指定这个div200px。第3行的div的宽度由内容撑开,可以认为是一个指定宽度的div,通过模拟器可以看到宽32px。第2行指定这个div为弹性,占用1份空间,就代表这个div的宽度是总宽度200px-32px=168px。如果我们改动第1行的div宽度为320px,那么第2div的宽度就是 320px-32px=288px。这个机制对于适配各种分辨率的屏幕无疑是一把利器。
我们再调整一下代码。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
  
<div style="-webkit-box-flex:1;background:#E00">aaaa </div>
  
<div style="-webkit-box-flex:2;background:#0EE">bbbb </div>
  
<div style="background:#0E0">cccc </div>
</div>

我们加入了一个占用2份空间的div。这个时候这两个弹性DIV到底如何分配空间呢?按照规则来说,第2行应该占用168px/3=56px,第3行占用112px,但实际上宽度并不是如此,通过模拟器可以看到,第34行占用66px,第35行占用102px。这是由于当弹性DIV中有内容时,引擎会自动进行调整。那么如何在有内容的情况下还能够保持12的比率呢?我们再调整一下代码。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
<div style="-webkit-box-flex:1;background:#E00;position:relative">
 
<div style="position:absolute;width:100%;height:100%;">aaaa </div>
</div>
<div style="-webkit-box-flex:2;background:#0EE;position:relative">
<div style="position:absolute;width:100%;height:100%;">bbbb </div>
</div>
<div style="background:#0E0">cccc </div>
</div>

这次修改中,我们把内容"aaaa"通过一个使用绝对定位的div进行包含,这时通过模拟器去看会发现,两个弹性div按照1:2的比率自动分配了空间。上面我们使用弹性盒子布局时元素都是横向排序的,那么怎么才能让元素纵向排布呢。我们接着调整一下代码。
效果:

代码:

<div style="display:-webkit-box;height:200px;border:1px solid blue;-webkit-box-orient:vertical;">
<div style="-webkit-box-flex:1;background:#E00;position:relative">
 
<div style="position:absolute;width:100%;height:100%;">aaaa </div>
</div>
<div style="-webkit-box-flex:2;background:#0EE;position:relative">
<div style="position:absolute;width:100%;height:100%;">bbbb </div>
</div>
<div style="background:#0E0">cccc </div>
</div>

上述代码中,我们在第1行的div中指定了高度为200px,使用-webkit-box-orient:vertical来控制子元素为纵向排列。
弹性盒子模型还提供了其他几个强大的属性。
 -webkit-box-direction:reverse;
通过在父DIV中设定这个属性可以让子元素反向排列。如下图:

使用前子元素按照1 2 3 的顺序进行排列显示,当在父DIV中使用此属性时,自动把子元素倒序排列。这个时候,我们并没有真的重新按照3 2 1顺序排布子元素。
 -webkit-box-align:center;
通过在父元素中设定这个属性,当子元素横向排布时,可以使子元素间实现上边界对齐、中线对齐和下边界对齐的效果

如果是纵向排列时,那么可以实现子元素左边界对齐、中线对齐和右边界对齐。

 -webkit-box-pack:center;
通过在父元素中设定这个属性,当子元素横向排布时,可以使子元素间左边界对齐、中线对齐和右边界对齐

如果是纵向排列时,那么可以实现子元素间上边界对齐、中线对齐和下边界对齐的效果。

如果父元素中只包含一个子元素,混合使用-webkit-box-align -webkit-box-pack可以使子元素实现居左上、居中上、局右上等9个方位的定位。
弹性BOX架构可以同时兼容流式布局,即当所有子元素都没有设定弹性份数时,父元素可以被子元素自动撑开。如下代码
效果:

代码:

<div style="display:-webkit-box;border:1px solid blue;-webkit-box-orient:vertical;">
  
<div>aaaa </div>
  
<div>bbbb </div>
  
<div>cccc </div>
</div>

在上述代码中所有子元素都未使用box-flex定义弹动属性,容器div也未设定高度,此时,容器div的高度为三个子元素的高度和,并且随着子元素的高度变化而变化。
AppCan UI2.0架构中,我们把上面遇到的情况进行了CSS类封装
● ub
元素采用弹性BOX布局
● ub-rev
子元素反序排列
● ub-con
在子元素中加入一个容器,用于避免内容引起子元素大小变化。
  对应CSS代码为position:absolute;width:100%;height:100%;
● ub-ac
ub-ae 子元素垂直居中对齐和尾对齐

● ub-pc
ub-peub-pj 子元素水平居中对齐、尾对齐和两端对齐
● ub-ver
子元素纵向排列
● ub-f1 ub-f2 ub-f3 ub-f4
子元素占用区域份数
通过上述类,我们可以完成各种各样的排版布局,极大地降低学习难度和元素排版复杂度,使代码更加简练。

32UI2.0框架开发指南

3.1 基石 (UI的分辨率适配)

  每一个手机应用,如果需要在众多的移动终端上保持一致的效果,UI适配是工作的重中之重。UI2.0框架与UI1.0框架在屏幕适配机制这一部分依然保持一致。设计原理是为不同分辨率的系统,选取最贴近于人直观感受舒适度的一个字体大小作为参考量。例如在320x480分辨率的手机上,采用16px大小字体作为参考量。在480x800分辨率的终端上,采用24px大小字体作为参考量。一切元素的大小都是以参考量的相对比值来定义。在CSS里面对应的是em。那么在320x480分辨率下 1em=16px,在480x800分辨率下1em=24px。 
  通过这种方式,我们可以保证,同样代码的界面,在不同分辨率下都能够保持最贴近用户的交互效果。
  在UI1.0中,我们在HTML文件中引用ui-media.css,即可处理当前常见分辨率的适配。但是由于各手机平台不同,和各种新分辨率手机的问世,都对适配工作提出了更高的要求。
  UI2.0中,我们在中间件中为不同屏幕密度(单位尺寸中可显示的点数),默认定义好了字体,开发者不再需要在代码中引入ui-media.css文件,即使有新的分辨率手机问世,也会自动适配。目前参照Andorid屏幕密度划分为低密度、普通密度、高密度、超高密度,分别定义字体为14px 16px 24px 32px

3.2 骨架(元素布局与定位)

在选定好的基石之上,我们需要为我们的目标界面,搭建骨架。骨架从构建上可以分为主干和旁支。
主干
主干可以认为是整个页面的整体框架布局

上图是截取与ZAKER(原生开发)、正益无线(HTML5开发)ZAKER微博界面(原生开发)HTML5中国(HTML5开发)。参考上述界面我们看到大部分应用的页面都遵循标题+内容+底部栏的布局方式。AppCan UI2.0提供了简单的布局架构模板来适配这种布局。Demo007范例下载

模板代码中我们可以看到默认存在index.htmlindex_content.html两个文件。我们通过对这两个文件的分析来讲解AppCan UI2.0推荐的应用开发模式。index.html文件分为三部分HEADBODYSCRIPT
HEAD
部分:

<head>
<title></title>6
<meta charset="utf-8">
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"<
<link rel="stylesheet" href="css/ui-base.css">
<link rel="stylesheet" href="css/ui-box.css">
<link rel="stylesheet" href="css/ui-color.css">
<link rel="stylesheet" href="css/ui-res.css">
<script src="js/zy_control.js">
</script<
<script src="js/zy_click.js">
</script>
</head>

这一部分定义了网页引用的CSSJS文件。上面代码中ui-base.css代表基础类文件,ui-box.css是弹性盒子封装类文件,ui-color是色彩基础类文件。zy_control.js是默认控件和网页需要的一些默认功能支持类。zy_click.jsClick事件模拟类,用于替代默认的onclick事件(手机中onclick响应较慢使应用体验性差)
BODY
部分

<body class="um-vp c-wh" ontouchstart>
 
<div id="page_0" class="up ub ub-ver" tabindex="0">
<!--header
开始
-->
 
<div id="header" class="uh c-org c-m1 t-wh">
 
<h1 class="ut ulev0 ut-s tx-c" tabindex="0">AppCan</h1>
</div>
<!--header
结束--> <!--content开始
-->
 
<div id="content" class="ub-f1 tx-l t-bla ub-img6 res10">
</div>
<!--content
结束--> <!--footer开始
-->
 
<div id="footer" class="uf c-m2 c-bla t-wh">
 
<h1 class="ut ulev-2 tx-c" tabindex="0">(c) Copyright 3G2WIN and others 2011.
<br>
All rights reserved. </h1>
</div>
<!--footer
结束
-->
</div>
</body>

Body部分定义了一个页面page_0,这个页面的高度为屏幕高度(up),使用弹性盒子布局(ub),它的子元素纵向排列(ub-ver)。这个页面中包含headercontentfooter三个区域。
header
footer部分是一个DIV,是一个定高的区域(通过内容撑开)content是一个弹性区域,它会占满page_0中除了headerfooter外的区域。如果headerfooter的高度变化,content的高度也会随之变化。但是这种布局当内容区域有内容时会引起整个content的高度撑高,由于大部分移动终端都不支持DIV的内部区域滚动,这回造成整个页面能够被拖动,这是与我们要求不符的。我们通过SCRIPT区域的代码来处理这个问题。
SCRIPT
部分:

<script>
zy_init();
window.uexOnload = function(type){
if (!type) {
zy_con("content", "index_content.html", 0, $$("header").offsetHeight);
}
window.onorientatiοnchange=window.οnresize=function()
{
zy_resize("content",0,$$("header").offsetHeight);
}
}
</script>

上述代码中zy_init函数用于在模拟器中实现字体的自动适配。在手机中无作用。
window.uexOnload
事件用于在AppCan中间件扩展对象加载完成后调用。在这个函数里,我们调用了封装在zy_control.js里的zy_con函数创建了一个浮动VIEW。这个Viewcontent的区域保持同样的大小,位置也与content区域的位置保持相同。这个View显示的内容来自于index_content.html页面。也就是说,我们的index.html页面中content区域其实并不包含内容,它只起到一个定位的作用,为浮动View提供定位支持。
window.onorientatiοnchange=window.onresize
这行代码为iOSAndorid平台的屏幕旋转事件指定了回调函数,当发生屏幕旋转时,会调用这个函数,此时我们调用封装的zy_resize接口参照content区域的新的高宽位置重新定位了浮动窗口。
更方便的是,开发者可以为content区域开发不同的content页面,可以根据的操作随时使用zy_con接口变更content区域的页面内容来实现不同的功能。例如可以配合下方的导航条控实现功能切换。

AppCan UI2.0框架推荐这种方式来编写页面,相对于UI1.0框架来说,处理逻辑更加简单,适配更加方便,并且在一个窗口中,并不是只允许包含一个浮动窗口,我们可以创建多个浮动窗口来完成不同的功能,轻松的实现功能的拆分,减少在一个页面中实现众多功能引起的逻辑问题。同时这种方式可以轻松的实现固定的背景图片。上述代码中,我们看到我们为content区域指定了一张背景图,而我们在index_content.html没有指定背景色,这样显示index_content.html网页时会显示出盖在在下方的content区域。由于浮动窗口是独立的窗口,因此它的页面滚动并不会影响下方content区域。当然这种布局我们使用iscrollJS包也可以很方便的实现,但是在很多Android手机上,由于性能原因体验相对于原生应用还是会有很大差距。
AppCan UI2.0
框架支持浮动窗口的弹动效果,开发者可以很方便的实现弹动效果,在index_content.html中我们已经默认提供了范例代码。接着我们看一下实际的内容区域网页index_content.html。这个页面与index.html一样同样分为三个部分HEADBODYSCRIPTHEAD部分与index.htmlHEAD部分一样没什么区别。BODY部分开发者可以根据需求添加列表、表单、地图等功能实现。SCRIPT部分的代码我们看一下:

<script>
zy_init();
window.uexOnload=function(type)
{
if(!type){
uexWindow.setBounce("1");
uexWindow.showBounceView("0","#FFF","0");
uexWindow.showBounceView("1","#FFF","0");
}
}
</script>

上述代码中zy_init()用于在模拟器状态下实现字体自适配,手机上无作用。uexOnload事件定义了浮动窗口AppCan扩展加载后的回调函数。当加载成功后,我们会调用AppCan弹动接口为浮动窗口添加弹动效果,并设定弹动背景色。大家可以使用范例应用来体验一下。
旁支
在完成页面后,我们需要对页面中的元素进行布局。使用弹性盒子,将使这个布局工作的难度降低很多。我们定一个目标,如下图

我们可以对他进行如下区域划分。

 左侧定宽图片区域
  图片子区域
右侧文字区域
  文字正文区域
  文章属性区域
我们在index_content.html种进行布局,代码如下
效果:

代码:

<div οnmοusedοwn="zy_touch('btn-act')" class="ubb ub b-gra t-bla lis">
<div class="lis-th ub-img im">
<div class="ub-f1 ub ub-ver">
<div class="ulev1"><
标题名
>
<div class="ulev-1 umh4 t-gra">
文本说明
</div>
<div class="ub ub-ac t-gra ulev-2">
<div class="umh2 umw2 ub-img " style="background-image:url(css/img/icon1.png);">
<div class="ub-f1">
收藏数
</div>
<div class="umh2 umw2 ub-img " style="background-image:url(css/img/icon2.png);">
<div class="ub-f1">
评论数
</div>
</div>
</div>
</div>

上述代码中,我们首先定义了一个容器,通过class="ubb ub b-gra t-bla lis"设定容器的下边框为灰色(ubb b-gra),文字色为黑色(t-bla),容器采用弹性盒子布局(ub),容器是一个list条目(lis)然后我们在容器中构建了一个缩略图元素class="lis-th ub-img im",指定了缩略图大小(lis-th),定义了缩略图的显示方式(ub-img)和缩略图图片资源(im)。由于图片区域定宽,文字区域是弹性的,因此我们为文字区域构建了容器ub-f1 ub ub-ver,容器宽度为弹性(ub-f1),容器也采用弹性盒子布局(ub),容器中的元素采用纵向布局(ub-ver)。我们分别在容器中加入标题、文本说明。收藏评论栏我们认为又是一个容器,这个容器中的字元素采用横向布局。我们在其中加入两个小图片和两段文字收藏数评论数。到此我们就完成了这个界面的布局。
这个例子只是一个简单的布局应用范例,通过这个例子来展示,AppCan UI2.0在布局页面时的简便性。

3.3 皮肤-元素的美化

当我们为一个元素设定完布局和位置后,接着就是要对这个元素进行美化。使人舒服的外表是吸引使用者的重要因素。AppCan UI2.0框架中对一个元素的效果属性分化为几类,通过这些不同类别属性的组合来完成对元素UI的设定。

大小位置形状控制
 圆角类别: uc-{类型}[类型] [类别]
 
uc-tl, uc-tr, uc-bl, uc-br , uc-t, uc-b, uc-r , uc-l, uc-a, uc-n, uc-tl1, uc-tr1, uc-bl1, uc-br1, uc-t1, uc-b1, uc-r1, uc-l1, uc-a1, uc-a2, uc-a3
 阴影类别: us [类别]us-i [类别
]
 
us,us1,us-i
 比例类别:ulev[类别](由于元素的控制主要通过em来进行相对控制,ulev可以对默认比率进行放大缩小
)
 
ulev2,ulev1,ulev0,ulev-1,ulev-2 
 浮动类别: ufl
ufr
 限宽类别
: ulim
 单行类别
: uinl
 边距类别: uinn[类别
]
 
uinn,uinn1,uinn2,uinn3,uinn4 
 最小高宽类别: um{wh}[类别
]
 
umh1,umh2,umh3,umh4,umh5,umh6,umw1,umw2,umw3 
 文字对齐类别:tx-{类型
}
 
tx-l,tx-r,tx-c 
 文字缩略类别
:ut-s
 边框类别:ub{类型}[类别
]
 
ubt,ubb,ubr,ubl,uba,uba1,uba2
 隐藏类别
:uhide
 间隔类别:umar-{类型
}
 
umar-b
色彩控制

UI2.0
框架对元素的色彩划分为边框色、文字色、背景底色和背景遮盖层
 背景遮盖类别: c-m{类别}
 
c-m1,c-m2,c-m3,c-m4,c-m5,c-m6,c-m7
 背景底色类别: c-{色彩}[类别
]
 
c-blu,c-blu1, c-blu2, c-blu3, c-blu4,c-wh, c-bla,c-gra,c-gra1,c-gra2,c-gre,c-red,c-yel
 文字色类别:t-{色彩}[类别
]
 
t-bla,t-wh,t-gra,t-blu
 边框色类别:b-{色彩}[类别
]
 
b-bla,b-wh,b-gra,b-gra1,b-blu
资源控制

UI2.0
框架一些常用图片资源进行了定义。例如搜索图标等。
 资源类别:res{类别}
 
res1,res2,res3,res4,res5,res6,res7,res8,res9,res10
AppCan UI2.0
框架对一个元素的基础属性进行了拆分整理,通过不同的组合来定制元素效果,同时这个方案也是一种规则,开发者可以根据具体的实际情况在对应的类别中扩展自己需要的特效。遵循这个规则可以提高代码的可重复利用率和维护管理效率,避免团队开发中由于各种自定义类别混乱定义引起的UI适配和维护问题。同时使用UI2.0框架构建的控件,代码量将会极大地减少。下面一节我们将对各种常用在应用中的控件的实现来使大家了解UI2.0UI实现上的巨大优势。

4UI2.0中的控件

4.1 按钮

上面图片展示了一些按钮的效果,我们通过代码看一下IDE是如何使用基础类来定义这些按钮的。我们选择index_content.html,在其Body区域添加一个按钮。在AppCan IDE(UI2.0)中,我们选择中标红的按钮,进入按钮制作向导。

在上面这个界面中,我们可以选择建立普通按钮、带图标按钮和特殊定义按钮例如iOS效果按钮等。一般情况下按钮会占满整个容器,选择内联可以使按钮和其他控件在不超出容器宽度的情况下保持在同一行。如果按钮在标题或页脚中,可以选择居于左侧或右侧。高级模式可以对按钮的显示效果进行配置。

上面的界面中,我们可以配置按钮的圆角、边框、边框色、背景色和背景遮盖渐变色。这些效果不光是对按钮起效,对于其他控件也是同样的定义。这里定义的效果只是我们预置的效果,开发者如果需要定义自己的色彩时,只需要在ui-color.css中添加自己的类定义后,对代码中的默认颜色类进行替换即可。我们添加一个深蓝色的按钮。
效果:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束-->

首先使用btn来定义这个DIV是一个按钮(我们为不同控件类型定义了一个标识类,用于定义一些此类控件通用的属性)。然后使用uinn5在文字外定义了一个内边距,这样按钮的高度就是内边距+文字高度。使用uc-a定义按钮四个圆角都为0.6em。接着我们使用c-blu指定背景色为蓝色。在通过c-m1在蓝色上加了一层渐变遮盖层。使用t-wh定义文字为白色。
最后我们通过uba1指定边框所有边都为2px宽,并通过b-bla设定边框色为黑色。到此就完成了一个按钮在不点击状态下的效果。相对于之前UI1.0中一个普通按钮需要一个DIV和两个SPAN的嵌套要简化了2/3的代码,层次也减低到一层。现在我们为这按钮加上点击效果。按照标准CSS3来说,只需要使用伪类:active来设定一个类即可完成鼠标按下弹起的效果变换,但很遗憾,在Andorid平台,这个效果大部分手机支持的都有问题。对于iOS平台这个属性是支持的,但是如果想使这个伪类有效,则必须在代码中加入ontouchstart,才能够激活这个伪类。为了解决这个跨平台问题,我们提供了zy_touch接口,通过这个接口,它可以完成点击效果的处理。
这段代码中,我们加入了ontouchstart="zy_touch('btn-act')"zy_touch是封装在zy_control.js中的扩展函数,btn-act是我们预定义的一个通用控件点击凹陷效果类。通过这个函数,我们构建了一个点击监听类zyClick(如果使用zy_touch还需要引用zy_click.js),他会监听触摸屏事件,来控制为按键增加和去除点击效果,同时可以判断是否为点击操作,如果判定成功,会直接调用参数中的回调函数来达到onclick事件的效果,可以解决手机浏览器中onclick不灵敏的问题。同时zy_touch还支持直接调用HTML代码中的onclick属性实现点击效果。我们调整代码
代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" οnclick="alert(1)" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束-->

上述代码中我们可以看到,我们注册了onclick函数,zy_touch会直接截获onclick事件,代替系统调用onclick代码,而不会调用两次onclick。这种写法更贴近于开发者正常应用的写法。另外,由于目前模拟器中还不支持ontouchstart事件,因此上述代码ontouchstart不会被执行,模拟器重看不到点击效果,但onclick函数还是会被调用。
如果希望在模拟器上看到效果,可以替换ontouchstartonmousedown。虽然手机中也支持onmousedown事件但是他的效果和时序和touch事件有差别,因此我们在手机中运行的时候还是要替换回ontouchstart
上面的按钮是使用DIV实现的,而DIV默认是一个块。因此会占满整个宽度。如果需要使按钮与其他控件在同行显示,我们需要为齐添加uinl类。
效果:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" οnclick="alert(1)" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh uinl">
确定
</div>
<!--
按钮结束-->

我们可以看到按钮的宽度已经不是整行显示而是根据按钮中的文字宽度、边框宽度、内边距宽度来展现。需要注意的是,uinl会和ub有效果冲突,在弹性盒子模型中,子元素需要处于块模式(display:block)。刚才介绍的是一个最简单的按钮,好我们现在为按钮增加一个图标。在IDE中选择按钮向导,在按钮类型中,选择带图标按钮。同样配置为深蓝色。
效果如下:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')"class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

无图标的按钮中,我们直接在DIV中加入了文字。这次因为有图标我们认为按钮中分左右两个区域,左侧文字区域自动适配宽度,右侧图标区域宽度固定。文字和图标中线对齐。首先我们定义按钮的外部效果class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac",这个与之前的按钮无区别,唯一添加的是 ubub-ac分别代表子元素采用弹性盒子布局,子元素中线对齐。我们为文字区域设定了弹性宽度(ub-f1),并指明当文字超出容器宽度时,自动缩略不换行(ut-s)。最后我们定义了一个图片,这个图片高(umh1)(umw1),采用ub-img控制其缩放,res1代表箭头图片,c-bla代表图片区域默认背景色,uc-a使其有圆角,由于图片宽度较小,配合圆角使其象一个圆形。这就是用弹性盒子布局定义的一个带图标按钮。那么如何使图标居于左侧呢?弹性盒子模型的便利性在这里有很好的体现。我们在容器中加入ub-rev类,它设定子元素反向排序,很简单实现图标居于左侧。

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac ub-rev">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

那如何使图标上下布局呢?一样很简单,只需要在容器中加入ub-ver,定义容器中的子元素纵向排序即可。

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac ub-ver">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

通过上面的例子可以看到其实一个按键就是一个容器加一些子元素进行弹性盒子布局,然后为容器和子元素加一些控制和显示效果。而其他控件也是这种方式,只是显示效果定制上稍有不同罢了。

4.2 容器

UI2.0中我们认为所有控件其实都是容器块配合子容器和子元素组合。因此,容器是我们最基础的组件之一。在应用开发中,经常需要把几个按钮、复选框或其他控件合并成一组进行显示。在这种情况下一个满足效果的容器将是必不可少的。我们接下来将讲解,如何利用AppCan来构建一个容器并按照我们的想法对元素进行排列打开AppCan IDE(UI2.0),我们选择中标红的按钮,进入容器制作向导。

可以看到容器分为纵向排列容器和横向排列容器。默认容器中会建立三个子元素,如果用户需要自己控制子元素的话可以选择无条目来建立一个空的容器。同时与按键控件相同,我们可以很简单为容器指定各种效果。我们接下来通过范例来演示如何使用容器。这次的范例是一个登陆的页面

这个页面中,纵向排列的两个编辑区域用来演示纵向排列容器。两个按钮用于演示横向排列。首先此页面高度不会超过一个屏幕,因此我们不需要实现页面的拖动。因此不需要建立一个浮动View来显示内容区域,而可以直接在内容区域添加代码。Demo008为此范例的初始界面。我们在此基础上进行调整来完成登陆页面。Demo008范例首先在插入编辑区域和按钮区域前,我们先对内容区域进行调整。content区域调整后的代码

<div id="content" class="uinn2 c-org1 ub-f1"></div>

上述代码中我们为内容区域设定了橙色背景(c-org1),弹性区域(ub-f1)自动适配屏幕,最后设定其内边距(uinn2),这样可以使后面我们将要添加的元素不会紧贴内容区域边界。准备完成后,我们在页面中添加一个纵向排列容器。

<!--块容器开始-->
<div class="ub ub-ver uba b-gra uc-a1 t-wh ">
<div class="ubb b-gra c-blu c-m1 uinn uc-t1">
条目
1</div>
<div class="ubb b-gra c-blu c-m1 uinn ">
条目
2</div>
<div class="c-blu c-m1 uinn uc-b1 ">
条目
3</div>
</div>
<!--
块容器结束-->

我们构建了一个默认的带三个条目的纵排块容器。由于此范例中只需要两个条目,且背景为统一的白色背景,因此我们需要对生成的代码进行调整,删掉条目2,并去掉条目背景色,同时为容器加上白色背景。修改后效果和代码如下

<!--块容器开始-->
<div class="ub ub-ver uba b-gra uc-a1 t-bla c-wh">
<div class="ubb b-gra uinn uc-t1">
条目
1</div>
<div class="uinn uc-b1 ">
条目
3</div>
</div>
<!--
块容器结束-->

上图我们可以看到,我们调整了容器的背景为白色,字体色彩为黑色,子条目没有背景。这时我们就已经创建了一个符合要求的容器了。接下来,我们假如编辑框控件来替换条目1和条目3
我们先通过IDE中的编辑框向导

插入一个编辑框到条目1位置(选择带标签),替换后的条目1部分代码如下

<div class="ubb b-gra uinn uc-t1">
<!--
文本开始
-->
<div class="ub t-bla ulab"> <div class="uinn ulim">
标签标签
</div>
<div class="ub-f1 c-blu uba uc-a1 b-gra us-i uinput uinn4">
<input placeholder="hello" type="text" class="uc-a1">
</div>
</div><!--
文本开始
-->
</div>

目前的效果和我们需要的效果有些偏差我们需要调整一下。首先标签部分不需要再有一个内边距(uinn),其次编辑框也不需要有任何的背景边框效果,我们删掉这些类。调整后的效果如下

代码:

<div class="ubb b-gra uinn uc-t1">
<!--
文本开始
-->
<div class="ub t-bla ulab ub-ac"> <div class="ulim">
用户名
</div>
<div class="ub-f1 uinput uinn4">
<input placeholder="hello" type="text" class="uc-a1">
</div>
</div><!--
文本开始
-->
</div>

上面的代码可以看到,对于一个编辑框,我们采用了弹性盒子模型,编辑区域通过ub-f1实现了宽度弹性变化。到此,我们完成了条目1部分的替换,接着我们拷贝这个代码替换条目3。最终效果如下

这里用到了一个小技巧,我们看到上面的图示里"用户名:""密码:"并不一样长,造成标签部分宽度不同,这会引起后面的编辑框区域宽度也不同,我们在"密码:"后面添加了一个中文空格来保证界面的排版。这是一个简单但有效的方法。
下面我们再增加两个按钮。首先在编辑区域容器下方再构建一个横向排列容器。

这个容器用来容纳我们的那两个按钮。

<div class="ub uba b-gra c-blu c-m1 t-wh uc-a1 ">
<div class="ubr b-gra ub-f1 uinn uc-l1">
条目
1</div>
<div class="ubr b-gra ub-f1 uinn ">
条目
2</div>
<div class="ub-f1 uinn uc-r1">
条目
3</div>
</div>
</div>

建立好的容器只有两个按钮,也不需要任何背景。我们对模板进行删减。
清理后的代码如下

<!--块容器开始-->
<div class="ub ">
<div class="ub-f1 uinn">
条目
1</div>
<div class="ub-f1 uinn">
条目
2</div>
</div>
</div>
<!--
块容器结束-->

接着我们需要加入两个按钮来替换条目1和条目3的文字,通过IDE的按键控件向导我们插入两个按钮,通过高级模式调整好色彩,并修改文字色。

<!--块容器开始-->
<div class="ub ">
<div class="ub-f1 uinn">
<!--
按钮开始
-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba b-gra uinn5 c-wh c-m1 uc-a t-bla">
确定
</div>
<!--
按钮结束
-->
</div>
<div class="ub-f1 uinn">
<!--
按钮开始
-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba b-org uinn5 c-org c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束
-->
</div>
</div>
<!--
块容器结束-->

到此,我们完成了基本的界面排布。我们再稍微的调整一下几个容器的间距即可。Demo009范例是调整完后的完整代码。我们通过一个范例来展现了AppCan UI2.0中的容器的使用方法。目前我们看到不管是一个容器、一个按钮或一个编辑框,都是依赖于弹性盒子模型实现的布局。

4.3 编辑框

上一节呢,我们用到了编辑框,这里我们对编辑框的使用作一个详细的讲解。AppCan UI2.0平台提供了多种编辑框的默认效果。

有普通单行文本框、文本区域和搜索框。同时控件与按键控件一样,也支持高级模式来定义效果。上一个例子里我们使用了普通的编辑框,这个例子我们主要介绍搜索框和文本区域。
搜索框
一般搜索框常会用在标题下面,我们对index.html页面做一下调整,在标题栏和内容区域之间插入一个搜索框。代码如下

<!--文本开始-->
<form id="search" οnsubmit="alert('submit')">
<div class="t-bla ub uba uc-a b-gra us-i uinput ub-rev uinn4">
<div class="res6 umw1 ub-img ">
</div>
<div class="ub-f1 uinn1">
<input placeholder="search" type="text" class="" style="background:none;">
</div>
</div>
</form>
<!--
文本结束-->

上面代码我们可以看到搜索框被放置到一个form表单里,这样手机的输入法会根据输入框的类型动态的匹配键盘效果。例如在键盘上确认按钮显示"搜索"等。由于在content区域前插入了搜索框,那么下方构建浮动窗口的代码中,浮动窗口位置也需要进行调整为Header高度加上搜索框高度。

zy_con("content", "index_content.html", 0, $$("header").offsetHeight+$$("search").offsetHeight);
zy_resize("content",0,$$("header").offsetHeight+
$$("search").offsetHeight);

调整后的代码见附件Demo0010范例
目前搜索框两边的圆角并没有使其显示成半圆形,我们只需要调整一下搜索框容器的uc-a类为uc-a2即可,uc-a2是一个更大的圆角。最终效果如下

输入域
接下来我们在index_content.html中添加一个输入域。通过编辑框向导创建一个带标签的输入域。

插入代码后效果如下。

<!--文本开始-->
<div class="ub t-bla ulab">
<div class="uinn ulim">
标签标签

</div>
<div class="ub-f1 uba uc-a1 b-gra us-i uinput uinn4 ub ub-ver">
<textarea placeholder="hello" name="area1" class="uc-a1 ub-f1"></textarea>
</div>
</div>
<!--
文本结束-->

这里呢我们希望标签和输入域纵向排列。很简单,我们在容器后面加入ub-ver使子元素纵向排列。

<!--文本开始-->
<div class="ub t-bla ulab ub-ver">
<div class="uinn ulim">
标签标签

</div>
<div class="ub-f1 uba uc-a1 b-gra us-i uinput uinn4 ub ub-ver umh6">
<textarea placeholder="hello" name="area1" class="uc-a1 ub-f1"></textarea>
</div>
</div>

编辑框的高度我们添加umh6来控制,如果需要调整别的高度,可以在ui-base.cssumh6下方参照umh6定义自己的高度类,并替换上述代码中的umh6即可。
我们对上面的代码进行一个分析。
首先最外侧是一个容器,这个容器采用弹性盒子架构(ub),定义了默认文本色(t-bla),由于有标签,所以我们加入了标签类(ulab),他主要控制标签和编辑区域的横向间距,如果纵向排列这个类可以删除。容器中有两个子元素,一个是标签一个是子容器。标签元素使用uinn为齐添加内边距,使用ulim来限制其长度。子容器用于定义编辑框的效果即阴影(us-i)、高度(umh6)、边框(b-grauba)。为了使输入域与边框间留下空隙,我们为子容器加上内边距(uinn4)uinput定义textarea元素的效果,ub定义此子容器依然是一个弹性盒子。由于输入域在适配中的特殊性,我们为子容器定义ub-ver,要求妻子元素纵向排列。接着我们为textarea指定ub-f1,使其撑满整个容器内边距内区域。最后的代码看附件Demo011范例

4.4 下拉列表控件

下拉列表控件经常用于在有限的区域内实现单选效果或多选,这个控件在应用开发中非常常见。我们对select标签进行了封装,使其有可定制化的现实效果。打开AppCan IDE(UI2.0),我们选择中标红的按钮,进入下拉列表制作向导。

下拉列表同之前的控件一样,可以通过高级模式配置效果。我们建立一个带标签的下拉列表,并对其代码进行讲解。Demo012范例
效果:

代码:

<!--下拉列表开始-->
<div class="ub t-bla">
<div class="uinn ulim">
标签标签
</div>
<div class="ub-f1 ub uba uc-a1 c-wh b-org us-i sel"> 
<div class="ub-f1 ut-s uinn ulev-1 tx-l">
下拉列表
</div> 
<div class="ubl b-org c-red c-m2 umw2 ub ub-pc uc-r2 ub-ac"> 
<div class="ub-img umw1 umh1 res3"></div> 
</div> 
<select name="sel0" selectedindex="0" id="sel0" οnchange="zy_slectmenu(this.id)"> 
<option>item1</option> 
<option>item2</option> 
<option>item3</option> 
<option>item4</option> 
</select> 
</div>
</div> 

上面代码中,我们可以看到这个控件是由一个容器中包含的标签部分和下拉列表部分组成。下拉列表中又分三个部分:
  文字区域-用于显示选中的条目内容

  按钮区域-是一个容器包含一个下箭头的图标。这个图标通过弹性盒子进行居中显示
  ■Select控件-是一个与整个下拉列表容器等高宽的透明控件,这样用户看到的是我们的文字区域和按钮区域,但实际点击时,点击的是系统Select控件。在select控件中我们通过zy_selectmenu接口截取用户选中的条目,修改文字区域内容
上述控件中,不管是最外面的容器还是子容器,我们都使用的是弹性盒子模型。

4.5 导航栏

在应用开发中,导航栏是组织内容的一种常见方式。它可以给用户更直观的选择和良好的交互体验。AppCan IDE UI2.0)框架对UI1.0中的导航栏控件进行了调整,使用新的弹性盒子模型重新构建了代码,更加便于开发者进行调整定制。我们通过选择IDE控件栏中标红的按钮,来构建一个导航栏。导航栏也可使用高级模式来设定背景色和渐变。我们在index.html中的footer部分构建一个导航栏。Demo013范例
效果:

代码:

<!--iPhone导航条开始-->
<div class="ub c-bla c-m1 tab t-wh">
<input class="uhide" type="radio" name="tabSwitch" checked="true">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-info"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-home"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-set"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-shop"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-talk"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
</div>

上述代码可以看到,整个导航栏是由一个弹性盒子容器包含5个条目组成的,如果用户需要事先大于5个或小于5个的导航栏,只需要拷贝复制或删除条目即可。每个条目又是由一个radiobox控件和一个纵排的弹性盒子子容器组成。在子容器中,包含图片和文字两个子元素。我们对这些组成部分进行一下分析。
  ■radiobox控件-此控件为隐藏控件,并不现实(uhide),他的作用是通过和其他具有同样name属性的radiobox控件组合使用,来实现条目的单项选择,配合后面子元素的CSS类属性实现选中和未选中效果。
  子容器-用于容纳每一个条目的子元素。同时负责显示选中和未选中状态(tab-act)。我们看一下ui-tab.csstab-act的定义。

input[type="radio"]:checked + div.tab-act
{
background-color:rgba(255,255,255,0.1) !important;
border-radius:0.3em;
border: 0px;
background-image: none;
}

  上面代码可以很清晰的看到当一个radiobox 被选中状态下,他相邻的那个div中的tab-act类表示一个透明度为0.1的圆角矩形。未选中状态下无效果。通过这个类配合之前的单选钮我们可以很简单的实现条目的选中未选中状态变化。
  图片元素-用于显示每一个条目得图片(tp-info)。由于每个条目的图片不同,需要为每个图片元素设定图片资源。目前我们在ui-tab.css中预置了六组图片资源类,用户可以根据需求替换相应的图片资源。每一组图片资源分选中状态和为选中状态,我们以tp-info为例进行分析。

input[type="radio"] + div>div.tp-info{
background: url(res-apple/info.png) 50% 50% no-repeat;
}

input[type="radio"]:checked + div>div.tp-info{
background: url(res-apple/info-act.png) 50% 50% no-repeat;
}

  上述代码中,可以看到当一个radio未选中时,与他相邻的div中的子div元素具有的tp-info属性对应背景图片为info.png。当选中时,与他相邻的div中的子div元素具有的tp-info属性对应背景图片为info-act.png。即配合radiobox我们可以简单的实现图片的变化。
导航栏并不一定都是这种显示效果,我们修改一下代码实现以下另一种效果。

这是上面是中文下方是英文的效果。附件是代码Demo014范例。我们调整了子容器的元素,从一个图片变为了两组文字框。

<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="uinn3 tx-c">新闻</div><div class="uinn ulev-1 tx-c">news</div></div>

上面展示的良种效果会有些问题,我们可以看到每一个子容器都是通过ub-f1进行等分的,但在文章最开始我们介绍时提到过,如果自容器中的内容并不等长时,浏览器会动态的调整每个字元素的宽度即时齐都是相同的flex属性。如果确实出现了文字不等长的情况,我们该如何调整呢?我们调整一下Demo014范例的代码Demo015范例

<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
早间新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>

相对于之前,修改后我们为文字外添加了一个容器,通过ub-con定义此文字区域的高宽与父元素相同。而之前每一个文字区域的高度都是被文字撑开的,所以此时为了保证文字区域的高度,我们分别为两个文字区域设定了umh2umh1的最小高度值。由于ub-con定义使用了position:absoluteheight:100%属性,则其高度是父容器的边框高+内边距高+内容高,因此我们不能为原来的文字区域再指定内边距,我们为条目容器指定了uinn3的内边距来代替原来为文字区域设定的uinn3,通过为上方的文字区域指定上下外边界来为两个文字区域进行分隔。通过这种写法,我们可以在各条目文字长度不同的情况下保持宽度的一致。同样,在页面设计中ub-con也可以用到其它有类似问题的地方。
导航条的目的是为了配合页面的切换。那么下面我们演示一下如何通过导航条快速实现页面切换。我们目前已经有了一个index.html和一个index_content.html,那么我们为index.html页面在建立一个内容页面。复制index_content.html,改名为msg_content.html。这个时候我们就有了两个内容页面。我们在script区域添加两个函数

function loadmsgcontent(){
zy_con("content", "msg_content.html", 0, $$("header").offsetHeight);
}
function loadindexcontent(){
zy_con("content", "index_content.html", 0, $$("header").offsetHeight);
}

第一个函数用于修改名字为content的浮动窗口加载的页面为msg_content.html,第二个函数用于修改content浮动窗口加载的页面为index_content.html。然后我们为导航栏中第一个元素和第二个元素分别加上onclick事件,

<div ontouchstart="zy_touch('',zy_for)" οnclick="loadindexcontent()" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
早间新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>
<div ontouchstart="zy_touch('',zy_for)" οnclick="loadmsgcontent()" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>

此时我们可以看到,当我们点击第一个条目和第二个条目时,中间区域的网页内容发生了改变。范例工程参阅附件Demo016范例

4.6 单选框和复选框

单选和复选框是应用中常见的组件,他们一般都会按组的方式实现。我们通过IDE中标红的两个按钮来生成复选和单选控件。我们打带复选框向导

构建一个单个复选框按钮,并对其代码进行分析

代码:

<!--复选框开始-->
<input type="checkbox" name="che1" class="uhide" checked="checked" value=""> 
<div οnclick="zy_for(event)" ontouchstart="zy_touch('btn-act')" class="ub uc-a1 uba c-gra c-m2 b-gra t-bla uinn5 ">
<div class="ub-f1 ut-s tx-l" >item</div>
<div class="che-icon ub-img umw1"></div> 
</div>
<!--
复选框结束-->

述代码可以看到一个复选框由一个隐藏(uhide)checkbox和一个复选框容器组成。复选框容器包含一个文字区域和一个选中状态图标。当用户点击这个复选框容器时触发onclick函数,会调用zy_for函数,此函数会对这个DIV元素之前的Input标签的checked属性做取反操作,即如果checkedtrue则变为false,为false则变为true。与之前select和导航栏控件机制一样,我们通过input和后面元素的CLASS类组合通过input的状态变化达到更换选中状态图标的效果。我们可以看一下che-icon这个类的定义。

input[type=checkbox]+div>div.che-icon {
background-color: transparent;
background-image: url(images/icons-18-white_39.png);
}
input[type=checkbox]:checked+div>div.che-icon {
background-color: transparent;
background-image: url(images/icons-18-white_37.png);
}

上述代码种,当input被选中时,其相邻的div中的子Div元素的che-icon属性会设定图片为icons-18-white_37.png。如果未选中则设定为icons-18-white_39.png。通过这里我们可以看到,我们在控件中广泛采用了input和类进行组合的方式非常简单的实现各种效果。
复选框还有一种变形,我们看看如下范例Demo017范例,通过向导选择

index_contet.html中添加一个水平分组复选框。效果如下

代码:

<!--复选框开始-->
<div class="ub uc-a1 t-bla c-gra c-m2 uba b-gra tx-c"> 
<input type="checkbox" name="che1" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 ubr b-gra uc-l1 ub-f1 che">item</div> 
<input type="checkbox" name="che2" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 ubr b-gra ub-f1 che">item</div> 
<input type="checkbox" name="che3" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 uc-r1 ub-f1 che">item</div>
</div>
<!--
复选框结束-->

水平复选框分组其实就是一个容器包含了三个子元素,每个子元素配合一个input标签来控制其效果(che)。我们看一下che类的代码

input[type=checkbox]:checked+div.che {
box-shadow:inset 0 1px 2px rgba(0,0,0,0.6);
}

上述代码表示当input被选中时,为元素添加一个内阴影。
对于纵向排列的复选框分组就不作介绍了,大家可以自己通过模板建立一个,研究一下代码。它其实就是一个容器里放了多个单条复选框而已。
单选框和复选框基本代码和设计都是一致的只是单选框的隐藏input标签类型为radio而已。大家可以研究一下ui-input.css中的类定义

4.7 列表控件

有人说80%的应用界面都是列表形式的,没统计过但是从大概的感觉上可以认为没有什么偏差。AppCan IDE UI(2.0)中,提供了新构建的列表模板。我们通过IDE中的列表向导进行构建Demo018范例

这次我们构建一个带图标的列表。
效果:

代码:

<!--列表开始-->
<div class="uba b-gra c-wh us uc-a ">
<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
<div ontouchstart="zy_touch('btn-act')" class=" ub ubb b-gra c-m2 t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
<div ontouchstart="zy_touch('btn-act')" class="uc-b c-m2 ub t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
</div>
<!--
列表结束-->

这是一个三个条目的列表,很明显,这个列表与其他控件基本组成元素都是一致的,也是一个容器、子容器加一些元素构造而成。我们主要对一个条目进行讲解。

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>

这是列表的第一个条目,我们一行一行进行解析。

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">

这是一个容器,由于是第一行,所以他的圆角要和外面容器的圆角保持匹配,因此我们为其设定圆角(uc-t),这个容器和下一行需要一条分割线,我们设定这个子容器右下边界(ubb),边界色彩为(b-gra),这个条目有一点简便效果,我们采用的是(c-m2)由于其位于容器内,这个遮盖层会和父容器背景色进行组合。这个子容器包含多个元素,这些元素也是以弹性盒子模型进行排版(ub),文字色彩定义为黑色(t-bla),由于容器中的子元素高低不定,因此我们要求其子元素中线对其(ub-ac)。最后是设定列表条目的默认效果(lis 建立了内边距)

<div class="lis-icon ub-img im"></div>

这是容器中的第一个元素,它是一个小图片,我们设定了这个图片的高宽(lis-icon),同时设定了这个图片是(im),图片的展示参数通过(ub-img)来设定。 备注:
默认工程中的ui-img.css定义了我们范例中的范例资源图片,而ui-res.css是我们控件需要的资源图片。

<div class="ub-f1 ut-s">设置</div>

这一行设定了一个弹性区域,他会撑满真个容器的空闲区域(ub-f1),当文字长度超过可容纳区域后,进行缩略(ut-s)

<div class="tx-r t-blu ulev-1">Old Phone</div>

这一行定义了一个文字去,这个文字区的大小会根据文字长度进行调整。我们通过ulev-1对此地的文字进行缩小显示。并通过t-blu设定其颜色为兰色。

<div class="res8 lis-sw ub-img"></div>

最后这个元素是一个小箭头图标。lis-sw定义了他的大小,res8指定了所用的资源,ub-img定义了图片的展示方式。
通过这部分解析我们看到一个列表其实也是由最基本的容器和元素组合而成。通过弹性盒子模型,真个列表的排布会非常简洁明了。

4.8 开关按钮

UI2.0框架中,我们对开关按钮进行了重新实现,配合上一个范例,我们在第一个条目中插入开关按钮来体验一下他的效果。Demo019范例

代码:

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<!--
开关按钮开始
-->
<input class="uhide" type="checkbox" checked="true" >
<div class="uba b-gra swi swi-bg uc-a1" οnclick="zy_for(event)"></div>
<!--
开关按钮结束
-->
</div>

上面代码中,我们把前一个范例的第一个条目后面的两个元素删除,替换了一个开关按钮。开关按钮的动画变换也是依赖于input的变化进行控制。其中swi定义了这个控件的变形动画效果,swi-bg定义了这个开关按钮的背景swiinput进行配合定义了不同状态下的效果。

input[type=checkbox]:checked + div.swi{
background-position:-0.1em;
}
input[type=checkbox] + div.swi
{
background-position:-4.01em
}

input标签被选中时,swi的背景位置是-0.3em。当未被选中时,背景位置为-4.01em。通过背景图片位置的变化完成选中状态的变化。
通过上面的讲解,我们展示了UI2.0的框架设计思想。并通过对我们预置组件代码的分析,使大家对如何使用UI2.0框架调整界面有了一个基本的认识。我们总结一下我们公司开发人员的UI设计规则
1.
制作前先考虑好如何组织页面,需要如何布局,在什么地方需要几个容器来进行排版。然后构建架子,使用默认效果类进行排版定位和美化
2.
如果需要使用颜色,请在ui-color.css中根据文本、背景、遮盖、边框等分别扩展自己的类定义
3.
如果需要调整圆角、边距等附加属性请在ui-base.css中进行添加。
4.
如果需要资源,请在ui-res.css中进行扩展
5.
如果需要布局,请在ui-box.css中进行调整
6.
所有调整要遵循默认的命名规则。
遵守这些规则可以使你的代码更容易被其他人阅读,代码复用和调整将会更加简单

 

1UI2.0UI1.0的对比

2012年初,我们发布了AppCan移动应用开发平台,在这个版本中,我们内置了基于JQMobile方案的CSS UI框架。这个框架可以帮助开发者遵循一套规则下,快速的开发应用。这套方案中主要采用了组合的概念。例如对一个按钮的描述,可以通过多个CSS类来组合进行定义,也可以通过视频了解更多。
这样通过不同的组合可以生成多变的效果。在实际商用应用开发过程中,它起到了帮助我们加快开发进度的作用。但是在开发过程中,我们还是遇到了一些问题,JQMobile CSS框架在这些问题上,表现得比较乏力:
1
1 自动填充宽度


上图中同样一个编辑框加上一个刷新按钮的组合。在不同分辨率下,如果希望,刷新按钮保持一个基本宽度,编辑框自动填充剩余区域,在不使用JS的情况下是很难做到的,如果使用百分比控制刷新钮的宽度,那么在低分辨率和高分辨率之间将会有非常大的偏差。
1
2 类名称过长
JQMobile
方案中,为了帮助开发者能够更直观的了解代码,每一个功能类的名称都比较长。例如ui-page ui-mobile-viewport等。这造成了网页代码大小变大,降低了解析速度。
1
3 类功能拆分度低
JQMobile方案中,很多类定义,代码重复较多,例如预制的多种色彩方案。同时由于拆分度低,经常需要重复定义类来覆盖其他类中的属性。
1
4 控件组合复杂
JQMobile
方案中,控件的实现代码量很大,一个按钮需要多个div span嵌套配合多个类才能实现。这造成开发中,界面代码量增大,不好控制界面。

我们综合各个项目中的开发经验,整理汇总了AppCan UI2.0架构,它继承了UI1.0的优点,并很好地解决了UI1.0的问题,可以使开发能够更加的简单。UI2.0框架图如下:

上图中,我们可以看到AppCan UI2.0框架在基础的屏幕适配(RESOLUTION ADAPTER CLASS)基础上,对元素基本属性进行了拆分。通过如下步骤来设定一个元素。
   定位-对元素进行布局,确定元素的现实位置大小等[LAYOUT CLASS]
   描边-对元素基础属性进行设定,例如边框圆角等
[BASE CLASS]
   添色-对元素的边框、文字和背景进行设定
[COLOR CLASS]
   插图-如果元素中需要图片,从资源中引入图片类
[RES CLASS]

基于基础元素之上,为了方便开发者,我们重新定义了控件,包含BUTTONLISTFOLDINPUTTABRADIOCHECKSWITCH。这些控件可以认为是UI2.0框架的具体事例。通过UI2.0完成的控件,代码大小和复杂度,都有明显的降低,如下例:


UI1.0
框架实现的按键

<div class="ui-btn ui-corner-all ui-shadow ui-btn-b"> 
  
<span class="ui-btn-inner ui-corner-all">
  <span class="ui-btn-text ">确定
</span>
</span>
</div>


UI2.0
框架实现的按键

<div class="btn btn-act ubb uc-t1 b-bla uinn c-blu2 c-m4 ">确定 </div>

从上述代码中可以看到,同样功能和效果的控件可以减少三分之二的代码,嵌套减少到一层,代码复杂度极大降低。
接着我们详细介绍如何使用UI2.0框架。

2UI2.0框架的设计来源——弹性盒子模型

弹性盒子模型是CSS3.0推出的一种布局机制。这种机制与常见的流式布局有很大区别。简单的理解为,流式布局是通过内容决定父容器大小,弹性盒子模型是,在指定大小的父容器里来为子元素分配空间,简单的流式布局例子。
效果:

代码:

<div style="display:inline;border:1px solid blue">
  
<div style="display:inline;background:#E00">aaaa </div>
  
<div style="display:inline;background:#0E0">bbbb </div>
</div>

上述代码中是一个简单的流式布局范例,第1行的div的宽度,是由第2和第3行的div宽度相加来决定的。即如果第2行或第3行的div宽度变化,第1行的宽度也会随之变化。我们调整一下代码,使用弹性盒子模型来布局。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
  
<div style="-webkit-box-flex:1;background:#E00">aaaa </div>
  
<div style="background:#0E0">bbbb </div>
</div>

上述代码中,指定第1行的div使用BOX方式布局子元素。并指定这个div200px。第3行的div的宽度由内容撑开,可以认为是一个指定宽度的div,通过模拟器可以看到宽32px。第2行指定这个div为弹性,占用1份空间,就代表这个div的宽度是总宽度200px-32px=168px。如果我们改动第1行的div宽度为320px,那么第2div的宽度就是 320px-32px=288px。这个机制对于适配各种分辨率的屏幕无疑是一把利器。
我们再调整一下代码。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
  
<div style="-webkit-box-flex:1;background:#E00">aaaa </div>
  
<div style="-webkit-box-flex:2;background:#0EE">bbbb </div>
  
<div style="background:#0E0">cccc </div>
</div>

我们加入了一个占用2份空间的div。这个时候这两个弹性DIV到底如何分配空间呢?按照规则来说,第2行应该占用168px/3=56px,第3行占用112px,但实际上宽度并不是如此,通过模拟器可以看到,第34行占用66px,第35行占用102px。这是由于当弹性DIV中有内容时,引擎会自动进行调整。那么如何在有内容的情况下还能够保持12的比率呢?我们再调整一下代码。
效果:

代码:

<div style="display:-webkit-box;width:200px;border:1px solid blue">
<div style="-webkit-box-flex:1;background:#E00;position:relative">
 
<div style="position:absolute;width:100%;height:100%;">aaaa </div>
</div>
<div style="-webkit-box-flex:2;background:#0EE;position:relative">
<div style="position:absolute;width:100%;height:100%;">bbbb </div>
</div>
<div style="background:#0E0">cccc </div>
</div>

这次修改中,我们把内容"aaaa"通过一个使用绝对定位的div进行包含,这时通过模拟器去看会发现,两个弹性div按照1:2的比率自动分配了空间。上面我们使用弹性盒子布局时元素都是横向排序的,那么怎么才能让元素纵向排布呢。我们接着调整一下代码。
效果:

代码:

<div style="display:-webkit-box;height:200px;border:1px solid blue;-webkit-box-orient:vertical;">
<div style="-webkit-box-flex:1;background:#E00;position:relative">
 
<div style="position:absolute;width:100%;height:100%;">aaaa </div>
</div>
<div style="-webkit-box-flex:2;background:#0EE;position:relative">
<div style="position:absolute;width:100%;height:100%;">bbbb </div>
</div>
<div style="background:#0E0">cccc </div>
</div>

上述代码中,我们在第1行的div中指定了高度为200px,使用-webkit-box-orient:vertical来控制子元素为纵向排列。
弹性盒子模型还提供了其他几个强大的属性。
 -webkit-box-direction:reverse;
通过在父DIV中设定这个属性可以让子元素反向排列。如下图:

使用前子元素按照1 2 3 的顺序进行排列显示,当在父DIV中使用此属性时,自动把子元素倒序排列。这个时候,我们并没有真的重新按照3 2 1顺序排布子元素。
 -webkit-box-align:center;
通过在父元素中设定这个属性,当子元素横向排布时,可以使子元素间实现上边界对齐、中线对齐和下边界对齐的效果

如果是纵向排列时,那么可以实现子元素左边界对齐、中线对齐和右边界对齐。

 -webkit-box-pack:center;
通过在父元素中设定这个属性,当子元素横向排布时,可以使子元素间左边界对齐、中线对齐和右边界对齐

如果是纵向排列时,那么可以实现子元素间上边界对齐、中线对齐和下边界对齐的效果。

如果父元素中只包含一个子元素,混合使用-webkit-box-align -webkit-box-pack可以使子元素实现居左上、居中上、局右上等9个方位的定位。
弹性BOX架构可以同时兼容流式布局,即当所有子元素都没有设定弹性份数时,父元素可以被子元素自动撑开。如下代码
效果:

代码:

<div style="display:-webkit-box;border:1px solid blue;-webkit-box-orient:vertical;">
  
<div>aaaa </div>
  
<div>bbbb </div>
  
<div>cccc </div>
</div>

在上述代码中所有子元素都未使用box-flex定义弹动属性,容器div也未设定高度,此时,容器div的高度为三个子元素的高度和,并且随着子元素的高度变化而变化。
AppCan UI2.0架构中,我们把上面遇到的情况进行了CSS类封装
● ub
元素采用弹性BOX布局
● ub-rev
子元素反序排列
● ub-con
在子元素中加入一个容器,用于避免内容引起子元素大小变化。
  对应CSS代码为position:absolute;width:100%;height:100%;
● ub-ac
ub-ae 子元素垂直居中对齐和尾对齐

● ub-pc
ub-peub-pj 子元素水平居中对齐、尾对齐和两端对齐
● ub-ver
子元素纵向排列
● ub-f1 ub-f2 ub-f3 ub-f4
子元素占用区域份数
通过上述类,我们可以完成各种各样的排版布局,极大地降低学习难度和元素排版复杂度,使代码更加简练。

32UI2.0框架开发指南

3.1 基石 (UI的分辨率适配)

  每一个手机应用,如果需要在众多的移动终端上保持一致的效果,UI适配是工作的重中之重。UI2.0框架与UI1.0框架在屏幕适配机制这一部分依然保持一致。设计原理是为不同分辨率的系统,选取最贴近于人直观感受舒适度的一个字体大小作为参考量。例如在320x480分辨率的手机上,采用16px大小字体作为参考量。在480x800分辨率的终端上,采用24px大小字体作为参考量。一切元素的大小都是以参考量的相对比值来定义。在CSS里面对应的是em。那么在320x480分辨率下 1em=16px,在480x800分辨率下1em=24px。 
  通过这种方式,我们可以保证,同样代码的界面,在不同分辨率下都能够保持最贴近用户的交互效果。
  在UI1.0中,我们在HTML文件中引用ui-media.css,即可处理当前常见分辨率的适配。但是由于各手机平台不同,和各种新分辨率手机的问世,都对适配工作提出了更高的要求。
  UI2.0中,我们在中间件中为不同屏幕密度(单位尺寸中可显示的点数),默认定义好了字体,开发者不再需要在代码中引入ui-media.css文件,即使有新的分辨率手机问世,也会自动适配。目前参照Andorid屏幕密度划分为低密度、普通密度、高密度、超高密度,分别定义字体为14px 16px 24px 32px

3.2 骨架(元素布局与定位)

在选定好的基石之上,我们需要为我们的目标界面,搭建骨架。骨架从构建上可以分为主干和旁支。
主干
主干可以认为是整个页面的整体框架布局

上图是截取与ZAKER(原生开发)、正益无线(HTML5开发)ZAKER微博界面(原生开发)HTML5中国(HTML5开发)。参考上述界面我们看到大部分应用的页面都遵循标题+内容+底部栏的布局方式。AppCan UI2.0提供了简单的布局架构模板来适配这种布局。Demo007范例下载

模板代码中我们可以看到默认存在index.htmlindex_content.html两个文件。我们通过对这两个文件的分析来讲解AppCan UI2.0推荐的应用开发模式。index.html文件分为三部分HEADBODYSCRIPT
HEAD
部分:

<head>
<title></title>6
<meta charset="utf-8">
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"<
<link rel="stylesheet" href="css/ui-base.css">
<link rel="stylesheet" href="css/ui-box.css">
<link rel="stylesheet" href="css/ui-color.css">
<link rel="stylesheet" href="css/ui-res.css">
<script src="js/zy_control.js">
</script<
<script src="js/zy_click.js">
</script>
</head>

这一部分定义了网页引用的CSSJS文件。上面代码中ui-base.css代表基础类文件,ui-box.css是弹性盒子封装类文件,ui-color是色彩基础类文件。zy_control.js是默认控件和网页需要的一些默认功能支持类。zy_click.jsClick事件模拟类,用于替代默认的onclick事件(手机中onclick响应较慢使应用体验性差)
BODY
部分

<body class="um-vp c-wh" ontouchstart>
 
<div id="page_0" class="up ub ub-ver" tabindex="0">
<!--header
开始
-->
 
<div id="header" class="uh c-org c-m1 t-wh">
 
<h1 class="ut ulev0 ut-s tx-c" tabindex="0">AppCan</h1>
</div>
<!--header
结束--> <!--content开始
-->
 
<div id="content" class="ub-f1 tx-l t-bla ub-img6 res10">
</div>
<!--content
结束--> <!--footer开始
-->
 
<div id="footer" class="uf c-m2 c-bla t-wh">
 
<h1 class="ut ulev-2 tx-c" tabindex="0">(c) Copyright 3G2WIN and others 2011.
<br>
All rights reserved. </h1>
</div>
<!--footer
结束
-->
</div>
</body>

Body部分定义了一个页面page_0,这个页面的高度为屏幕高度(up),使用弹性盒子布局(ub),它的子元素纵向排列(ub-ver)。这个页面中包含headercontentfooter三个区域。
header
footer部分是一个DIV,是一个定高的区域(通过内容撑开)content是一个弹性区域,它会占满page_0中除了headerfooter外的区域。如果headerfooter的高度变化,content的高度也会随之变化。但是这种布局当内容区域有内容时会引起整个content的高度撑高,由于大部分移动终端都不支持DIV的内部区域滚动,这回造成整个页面能够被拖动,这是与我们要求不符的。我们通过SCRIPT区域的代码来处理这个问题。
SCRIPT
部分:

<script>
zy_init();
window.uexOnload = function(type){
if (!type) {
zy_con("content", "index_content.html", 0, $$("header").offsetHeight);
}
window.onorientatiοnchange=window.οnresize=function()
{
zy_resize("content",0,$$("header").offsetHeight);
}
}
</script>

上述代码中zy_init函数用于在模拟器中实现字体的自动适配。在手机中无作用。
window.uexOnload
事件用于在AppCan中间件扩展对象加载完成后调用。在这个函数里,我们调用了封装在zy_control.js里的zy_con函数创建了一个浮动VIEW。这个Viewcontent的区域保持同样的大小,位置也与content区域的位置保持相同。这个View显示的内容来自于index_content.html页面。也就是说,我们的index.html页面中content区域其实并不包含内容,它只起到一个定位的作用,为浮动View提供定位支持。
window.onorientatiοnchange=window.onresize
这行代码为iOSAndorid平台的屏幕旋转事件指定了回调函数,当发生屏幕旋转时,会调用这个函数,此时我们调用封装的zy_resize接口参照content区域的新的高宽位置重新定位了浮动窗口。
更方便的是,开发者可以为content区域开发不同的content页面,可以根据的操作随时使用zy_con接口变更content区域的页面内容来实现不同的功能。例如可以配合下方的导航条控实现功能切换。

AppCan UI2.0框架推荐这种方式来编写页面,相对于UI1.0框架来说,处理逻辑更加简单,适配更加方便,并且在一个窗口中,并不是只允许包含一个浮动窗口,我们可以创建多个浮动窗口来完成不同的功能,轻松的实现功能的拆分,减少在一个页面中实现众多功能引起的逻辑问题。同时这种方式可以轻松的实现固定的背景图片。上述代码中,我们看到我们为content区域指定了一张背景图,而我们在index_content.html没有指定背景色,这样显示index_content.html网页时会显示出盖在在下方的content区域。由于浮动窗口是独立的窗口,因此它的页面滚动并不会影响下方content区域。当然这种布局我们使用iscrollJS包也可以很方便的实现,但是在很多Android手机上,由于性能原因体验相对于原生应用还是会有很大差距。
AppCan UI2.0
框架支持浮动窗口的弹动效果,开发者可以很方便的实现弹动效果,在index_content.html中我们已经默认提供了范例代码。接着我们看一下实际的内容区域网页index_content.html。这个页面与index.html一样同样分为三个部分HEADBODYSCRIPTHEAD部分与index.htmlHEAD部分一样没什么区别。BODY部分开发者可以根据需求添加列表、表单、地图等功能实现。SCRIPT部分的代码我们看一下:

<script>
zy_init();
window.uexOnload=function(type)
{
if(!type){
uexWindow.setBounce("1");
uexWindow.showBounceView("0","#FFF","0");
uexWindow.showBounceView("1","#FFF","0");
}
}
</script>

上述代码中zy_init()用于在模拟器状态下实现字体自适配,手机上无作用。uexOnload事件定义了浮动窗口AppCan扩展加载后的回调函数。当加载成功后,我们会调用AppCan弹动接口为浮动窗口添加弹动效果,并设定弹动背景色。大家可以使用范例应用来体验一下。
旁支
在完成页面后,我们需要对页面中的元素进行布局。使用弹性盒子,将使这个布局工作的难度降低很多。我们定一个目标,如下图

我们可以对他进行如下区域划分。

 左侧定宽图片区域
  图片子区域
右侧文字区域
  文字正文区域
  文章属性区域
我们在index_content.html种进行布局,代码如下
效果:

代码:

<div οnmοusedοwn="zy_touch('btn-act')" class="ubb ub b-gra t-bla lis">
<div class="lis-th ub-img im">
<div class="ub-f1 ub ub-ver">
<div class="ulev1"><
标题名
>
<div class="ulev-1 umh4 t-gra">
文本说明
</div>
<div class="ub ub-ac t-gra ulev-2">
<div class="umh2 umw2 ub-img " style="background-image:url(css/img/icon1.png);">
<div class="ub-f1">
收藏数
</div>
<div class="umh2 umw2 ub-img " style="background-image:url(css/img/icon2.png);">
<div class="ub-f1">
评论数
</div>
</div>
</div>
</div>

上述代码中,我们首先定义了一个容器,通过class="ubb ub b-gra t-bla lis"设定容器的下边框为灰色(ubb b-gra),文字色为黑色(t-bla),容器采用弹性盒子布局(ub),容器是一个list条目(lis)然后我们在容器中构建了一个缩略图元素class="lis-th ub-img im",指定了缩略图大小(lis-th),定义了缩略图的显示方式(ub-img)和缩略图图片资源(im)。由于图片区域定宽,文字区域是弹性的,因此我们为文字区域构建了容器ub-f1 ub ub-ver,容器宽度为弹性(ub-f1),容器也采用弹性盒子布局(ub),容器中的元素采用纵向布局(ub-ver)。我们分别在容器中加入标题、文本说明。收藏评论栏我们认为又是一个容器,这个容器中的字元素采用横向布局。我们在其中加入两个小图片和两段文字收藏数评论数。到此我们就完成了这个界面的布局。
这个例子只是一个简单的布局应用范例,通过这个例子来展示,AppCan UI2.0在布局页面时的简便性。

3.3 皮肤-元素的美化

当我们为一个元素设定完布局和位置后,接着就是要对这个元素进行美化。使人舒服的外表是吸引使用者的重要因素。AppCan UI2.0框架中对一个元素的效果属性分化为几类,通过这些不同类别属性的组合来完成对元素UI的设定。

大小位置形状控制
 圆角类别: uc-{类型}[类型] [类别]
 
uc-tl, uc-tr, uc-bl, uc-br , uc-t, uc-b, uc-r , uc-l, uc-a, uc-n, uc-tl1, uc-tr1, uc-bl1, uc-br1, uc-t1, uc-b1, uc-r1, uc-l1, uc-a1, uc-a2, uc-a3
 阴影类别: us [类别]us-i [类别
]
 
us,us1,us-i
 比例类别:ulev[类别](由于元素的控制主要通过em来进行相对控制,ulev可以对默认比率进行放大缩小
)
 
ulev2,ulev1,ulev0,ulev-1,ulev-2 
 浮动类别: ufl
ufr
 限宽类别
: ulim
 单行类别
: uinl
 边距类别: uinn[类别
]
 
uinn,uinn1,uinn2,uinn3,uinn4 
 最小高宽类别: um{wh}[类别
]
 
umh1,umh2,umh3,umh4,umh5,umh6,umw1,umw2,umw3 
 文字对齐类别:tx-{类型
}
 
tx-l,tx-r,tx-c 
 文字缩略类别
:ut-s
 边框类别:ub{类型}[类别
]
 
ubt,ubb,ubr,ubl,uba,uba1,uba2
 隐藏类别
:uhide
 间隔类别:umar-{类型
}
 
umar-b
色彩控制

UI2.0
框架对元素的色彩划分为边框色、文字色、背景底色和背景遮盖层
 背景遮盖类别: c-m{类别}
 
c-m1,c-m2,c-m3,c-m4,c-m5,c-m6,c-m7
 背景底色类别: c-{色彩}[类别
]
 
c-blu,c-blu1, c-blu2, c-blu3, c-blu4,c-wh, c-bla,c-gra,c-gra1,c-gra2,c-gre,c-red,c-yel
 文字色类别:t-{色彩}[类别
]
 
t-bla,t-wh,t-gra,t-blu
 边框色类别:b-{色彩}[类别
]
 
b-bla,b-wh,b-gra,b-gra1,b-blu
资源控制

UI2.0
框架一些常用图片资源进行了定义。例如搜索图标等。
 资源类别:res{类别}
 
res1,res2,res3,res4,res5,res6,res7,res8,res9,res10
AppCan UI2.0
框架对一个元素的基础属性进行了拆分整理,通过不同的组合来定制元素效果,同时这个方案也是一种规则,开发者可以根据具体的实际情况在对应的类别中扩展自己需要的特效。遵循这个规则可以提高代码的可重复利用率和维护管理效率,避免团队开发中由于各种自定义类别混乱定义引起的UI适配和维护问题。同时使用UI2.0框架构建的控件,代码量将会极大地减少。下面一节我们将对各种常用在应用中的控件的实现来使大家了解UI2.0UI实现上的巨大优势。

4UI2.0中的控件

4.1 按钮

上面图片展示了一些按钮的效果,我们通过代码看一下IDE是如何使用基础类来定义这些按钮的。我们选择index_content.html,在其Body区域添加一个按钮。在AppCan IDE(UI2.0)中,我们选择中标红的按钮,进入按钮制作向导。

在上面这个界面中,我们可以选择建立普通按钮、带图标按钮和特殊定义按钮例如iOS效果按钮等。一般情况下按钮会占满整个容器,选择内联可以使按钮和其他控件在不超出容器宽度的情况下保持在同一行。如果按钮在标题或页脚中,可以选择居于左侧或右侧。高级模式可以对按钮的显示效果进行配置。

上面的界面中,我们可以配置按钮的圆角、边框、边框色、背景色和背景遮盖渐变色。这些效果不光是对按钮起效,对于其他控件也是同样的定义。这里定义的效果只是我们预置的效果,开发者如果需要定义自己的色彩时,只需要在ui-color.css中添加自己的类定义后,对代码中的默认颜色类进行替换即可。我们添加一个深蓝色的按钮。
效果:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束-->

首先使用btn来定义这个DIV是一个按钮(我们为不同控件类型定义了一个标识类,用于定义一些此类控件通用的属性)。然后使用uinn5在文字外定义了一个内边距,这样按钮的高度就是内边距+文字高度。使用uc-a定义按钮四个圆角都为0.6em。接着我们使用c-blu指定背景色为蓝色。在通过c-m1在蓝色上加了一层渐变遮盖层。使用t-wh定义文字为白色。
最后我们通过uba1指定边框所有边都为2px宽,并通过b-bla设定边框色为黑色。到此就完成了一个按钮在不点击状态下的效果。相对于之前UI1.0中一个普通按钮需要一个DIV和两个SPAN的嵌套要简化了2/3的代码,层次也减低到一层。现在我们为这按钮加上点击效果。按照标准CSS3来说,只需要使用伪类:active来设定一个类即可完成鼠标按下弹起的效果变换,但很遗憾,在Andorid平台,这个效果大部分手机支持的都有问题。对于iOS平台这个属性是支持的,但是如果想使这个伪类有效,则必须在代码中加入ontouchstart,才能够激活这个伪类。为了解决这个跨平台问题,我们提供了zy_touch接口,通过这个接口,它可以完成点击效果的处理。
这段代码中,我们加入了ontouchstart="zy_touch('btn-act')"zy_touch是封装在zy_control.js中的扩展函数,btn-act是我们预定义的一个通用控件点击凹陷效果类。通过这个函数,我们构建了一个点击监听类zyClick(如果使用zy_touch还需要引用zy_click.js),他会监听触摸屏事件,来控制为按键增加和去除点击效果,同时可以判断是否为点击操作,如果判定成功,会直接调用参数中的回调函数来达到onclick事件的效果,可以解决手机浏览器中onclick不灵敏的问题。同时zy_touch还支持直接调用HTML代码中的onclick属性实现点击效果。我们调整代码
代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" οnclick="alert(1)" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束-->

上述代码中我们可以看到,我们注册了onclick函数,zy_touch会直接截获onclick事件,代替系统调用onclick代码,而不会调用两次onclick。这种写法更贴近于开发者正常应用的写法。另外,由于目前模拟器中还不支持ontouchstart事件,因此上述代码ontouchstart不会被执行,模拟器重看不到点击效果,但onclick函数还是会被调用。
如果希望在模拟器上看到效果,可以替换ontouchstartonmousedown。虽然手机中也支持onmousedown事件但是他的效果和时序和touch事件有差别,因此我们在手机中运行的时候还是要替换回ontouchstart
上面的按钮是使用DIV实现的,而DIV默认是一个块。因此会占满整个宽度。如果需要使按钮与其他控件在同行显示,我们需要为齐添加uinl类。
效果:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" οnclick="alert(1)" class="btn uba1 b-bla uinn5 c-blu c-m1 uc-a t-wh uinl">
确定
</div>
<!--
按钮结束-->

我们可以看到按钮的宽度已经不是整行显示而是根据按钮中的文字宽度、边框宽度、内边距宽度来展现。需要注意的是,uinl会和ub有效果冲突,在弹性盒子模型中,子元素需要处于块模式(display:block)。刚才介绍的是一个最简单的按钮,好我们现在为按钮增加一个图标。在IDE中选择按钮向导,在按钮类型中,选择带图标按钮。同样配置为深蓝色。
效果如下:

代码:

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')"class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

无图标的按钮中,我们直接在DIV中加入了文字。这次因为有图标我们认为按钮中分左右两个区域,左侧文字区域自动适配宽度,右侧图标区域宽度固定。文字和图标中线对齐。首先我们定义按钮的外部效果class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac",这个与之前的按钮无区别,唯一添加的是 ubub-ac分别代表子元素采用弹性盒子布局,子元素中线对齐。我们为文字区域设定了弹性宽度(ub-f1),并指明当文字超出容器宽度时,自动缩略不换行(ut-s)。最后我们定义了一个图片,这个图片高(umh1)(umw1),采用ub-img控制其缩放,res1代表箭头图片,c-bla代表图片区域默认背景色,uc-a使其有圆角,由于图片宽度较小,配合圆角使其象一个圆形。这就是用弹性盒子布局定义的一个带图标按钮。那么如何使图标居于左侧呢?弹性盒子模型的便利性在这里有很好的体现。我们在容器中加入ub-rev类,它设定子元素反向排序,很简单实现图标居于左侧。

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac ub-rev">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

那如何使图标上下布局呢?一样很简单,只需要在容器中加入ub-ver,定义容器中的子元素纵向排序即可。

<!--按钮开始-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba1 b-bla c-blu c-m1 uc-a ub t-wh uinn5 ub-ac ub-ver">
<div class="ub-f1 ut-s">
确定
</div>
<div class="umh1 umw1 ub-img res1 c-bla uc-a"></div>
</div>
<!--
按钮结束-->

通过上面的例子可以看到其实一个按键就是一个容器加一些子元素进行弹性盒子布局,然后为容器和子元素加一些控制和显示效果。而其他控件也是这种方式,只是显示效果定制上稍有不同罢了。

4.2 容器

UI2.0中我们认为所有控件其实都是容器块配合子容器和子元素组合。因此,容器是我们最基础的组件之一。在应用开发中,经常需要把几个按钮、复选框或其他控件合并成一组进行显示。在这种情况下一个满足效果的容器将是必不可少的。我们接下来将讲解,如何利用AppCan来构建一个容器并按照我们的想法对元素进行排列打开AppCan IDE(UI2.0),我们选择中标红的按钮,进入容器制作向导。

可以看到容器分为纵向排列容器和横向排列容器。默认容器中会建立三个子元素,如果用户需要自己控制子元素的话可以选择无条目来建立一个空的容器。同时与按键控件相同,我们可以很简单为容器指定各种效果。我们接下来通过范例来演示如何使用容器。这次的范例是一个登陆的页面

这个页面中,纵向排列的两个编辑区域用来演示纵向排列容器。两个按钮用于演示横向排列。首先此页面高度不会超过一个屏幕,因此我们不需要实现页面的拖动。因此不需要建立一个浮动View来显示内容区域,而可以直接在内容区域添加代码。Demo008为此范例的初始界面。我们在此基础上进行调整来完成登陆页面。Demo008范例首先在插入编辑区域和按钮区域前,我们先对内容区域进行调整。content区域调整后的代码

<div id="content" class="uinn2 c-org1 ub-f1"></div>

上述代码中我们为内容区域设定了橙色背景(c-org1),弹性区域(ub-f1)自动适配屏幕,最后设定其内边距(uinn2),这样可以使后面我们将要添加的元素不会紧贴内容区域边界。准备完成后,我们在页面中添加一个纵向排列容器。

<!--块容器开始-->
<div class="ub ub-ver uba b-gra uc-a1 t-wh ">
<div class="ubb b-gra c-blu c-m1 uinn uc-t1">
条目
1</div>
<div class="ubb b-gra c-blu c-m1 uinn ">
条目
2</div>
<div class="c-blu c-m1 uinn uc-b1 ">
条目
3</div>
</div>
<!--
块容器结束-->

我们构建了一个默认的带三个条目的纵排块容器。由于此范例中只需要两个条目,且背景为统一的白色背景,因此我们需要对生成的代码进行调整,删掉条目2,并去掉条目背景色,同时为容器加上白色背景。修改后效果和代码如下

<!--块容器开始-->
<div class="ub ub-ver uba b-gra uc-a1 t-bla c-wh">
<div class="ubb b-gra uinn uc-t1">
条目
1</div>
<div class="uinn uc-b1 ">
条目
3</div>
</div>
<!--
块容器结束-->

上图我们可以看到,我们调整了容器的背景为白色,字体色彩为黑色,子条目没有背景。这时我们就已经创建了一个符合要求的容器了。接下来,我们假如编辑框控件来替换条目1和条目3
我们先通过IDE中的编辑框向导

插入一个编辑框到条目1位置(选择带标签),替换后的条目1部分代码如下

<div class="ubb b-gra uinn uc-t1">
<!--
文本开始
-->
<div class="ub t-bla ulab"> <div class="uinn ulim">
标签标签
</div>
<div class="ub-f1 c-blu uba uc-a1 b-gra us-i uinput uinn4">
<input placeholder="hello" type="text" class="uc-a1">
</div>
</div><!--
文本开始
-->
</div>

目前的效果和我们需要的效果有些偏差我们需要调整一下。首先标签部分不需要再有一个内边距(uinn),其次编辑框也不需要有任何的背景边框效果,我们删掉这些类。调整后的效果如下

代码:

<div class="ubb b-gra uinn uc-t1">
<!--
文本开始
-->
<div class="ub t-bla ulab ub-ac"> <div class="ulim">
用户名
</div>
<div class="ub-f1 uinput uinn4">
<input placeholder="hello" type="text" class="uc-a1">
</div>
</div><!--
文本开始
-->
</div>

上面的代码可以看到,对于一个编辑框,我们采用了弹性盒子模型,编辑区域通过ub-f1实现了宽度弹性变化。到此,我们完成了条目1部分的替换,接着我们拷贝这个代码替换条目3。最终效果如下

这里用到了一个小技巧,我们看到上面的图示里"用户名:""密码:"并不一样长,造成标签部分宽度不同,这会引起后面的编辑框区域宽度也不同,我们在"密码:"后面添加了一个中文空格来保证界面的排版。这是一个简单但有效的方法。
下面我们再增加两个按钮。首先在编辑区域容器下方再构建一个横向排列容器。

这个容器用来容纳我们的那两个按钮。

<div class="ub uba b-gra c-blu c-m1 t-wh uc-a1 ">
<div class="ubr b-gra ub-f1 uinn uc-l1">
条目
1</div>
<div class="ubr b-gra ub-f1 uinn ">
条目
2</div>
<div class="ub-f1 uinn uc-r1">
条目
3</div>
</div>
</div>

建立好的容器只有两个按钮,也不需要任何背景。我们对模板进行删减。
清理后的代码如下

<!--块容器开始-->
<div class="ub ">
<div class="ub-f1 uinn">
条目
1</div>
<div class="ub-f1 uinn">
条目
2</div>
</div>
</div>
<!--
块容器结束-->

接着我们需要加入两个按钮来替换条目1和条目3的文字,通过IDE的按键控件向导我们插入两个按钮,通过高级模式调整好色彩,并修改文字色。

<!--块容器开始-->
<div class="ub ">
<div class="ub-f1 uinn">
<!--
按钮开始
-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba b-gra uinn5 c-wh c-m1 uc-a t-bla">
确定
</div>
<!--
按钮结束
-->
</div>
<div class="ub-f1 uinn">
<!--
按钮开始
-->
<div ontouchstart="zy_touch('btn-act')" class="btn uba b-org uinn5 c-org c-m1 uc-a t-wh">
确定
</div>
<!--
按钮结束
-->
</div>
</div>
<!--
块容器结束-->

到此,我们完成了基本的界面排布。我们再稍微的调整一下几个容器的间距即可。Demo009范例是调整完后的完整代码。我们通过一个范例来展现了AppCan UI2.0中的容器的使用方法。目前我们看到不管是一个容器、一个按钮或一个编辑框,都是依赖于弹性盒子模型实现的布局。

4.3 编辑框

上一节呢,我们用到了编辑框,这里我们对编辑框的使用作一个详细的讲解。AppCan UI2.0平台提供了多种编辑框的默认效果。

有普通单行文本框、文本区域和搜索框。同时控件与按键控件一样,也支持高级模式来定义效果。上一个例子里我们使用了普通的编辑框,这个例子我们主要介绍搜索框和文本区域。
搜索框
一般搜索框常会用在标题下面,我们对index.html页面做一下调整,在标题栏和内容区域之间插入一个搜索框。代码如下

<!--文本开始-->
<form id="search" οnsubmit="alert('submit')">
<div class="t-bla ub uba uc-a b-gra us-i uinput ub-rev uinn4">
<div class="res6 umw1 ub-img ">
</div>
<div class="ub-f1 uinn1">
<input placeholder="search" type="text" class="" style="background:none;">
</div>
</div>
</form>
<!--
文本结束-->

上面代码我们可以看到搜索框被放置到一个form表单里,这样手机的输入法会根据输入框的类型动态的匹配键盘效果。例如在键盘上确认按钮显示"搜索"等。由于在content区域前插入了搜索框,那么下方构建浮动窗口的代码中,浮动窗口位置也需要进行调整为Header高度加上搜索框高度。

zy_con("content", "index_content.html", 0, $$("header").offsetHeight+$$("search").offsetHeight);
zy_resize("content",0,$$("header").offsetHeight+
$$("search").offsetHeight);

调整后的代码见附件Demo0010范例
目前搜索框两边的圆角并没有使其显示成半圆形,我们只需要调整一下搜索框容器的uc-a类为uc-a2即可,uc-a2是一个更大的圆角。最终效果如下

输入域
接下来我们在index_content.html中添加一个输入域。通过编辑框向导创建一个带标签的输入域。

插入代码后效果如下。

<!--文本开始-->
<div class="ub t-bla ulab">
<div class="uinn ulim">
标签标签

</div>
<div class="ub-f1 uba uc-a1 b-gra us-i uinput uinn4 ub ub-ver">
<textarea placeholder="hello" name="area1" class="uc-a1 ub-f1"></textarea>
</div>
</div>
<!--
文本结束-->

这里呢我们希望标签和输入域纵向排列。很简单,我们在容器后面加入ub-ver使子元素纵向排列。

<!--文本开始-->
<div class="ub t-bla ulab ub-ver">
<div class="uinn ulim">
标签标签

</div>
<div class="ub-f1 uba uc-a1 b-gra us-i uinput uinn4 ub ub-ver umh6">
<textarea placeholder="hello" name="area1" class="uc-a1 ub-f1"></textarea>
</div>
</div>

编辑框的高度我们添加umh6来控制,如果需要调整别的高度,可以在ui-base.cssumh6下方参照umh6定义自己的高度类,并替换上述代码中的umh6即可。
我们对上面的代码进行一个分析。
首先最外侧是一个容器,这个容器采用弹性盒子架构(ub),定义了默认文本色(t-bla),由于有标签,所以我们加入了标签类(ulab),他主要控制标签和编辑区域的横向间距,如果纵向排列这个类可以删除。容器中有两个子元素,一个是标签一个是子容器。标签元素使用uinn为齐添加内边距,使用ulim来限制其长度。子容器用于定义编辑框的效果即阴影(us-i)、高度(umh6)、边框(b-grauba)。为了使输入域与边框间留下空隙,我们为子容器加上内边距(uinn4)uinput定义textarea元素的效果,ub定义此子容器依然是一个弹性盒子。由于输入域在适配中的特殊性,我们为子容器定义ub-ver,要求妻子元素纵向排列。接着我们为textarea指定ub-f1,使其撑满整个容器内边距内区域。最后的代码看附件Demo011范例

4.4 下拉列表控件

下拉列表控件经常用于在有限的区域内实现单选效果或多选,这个控件在应用开发中非常常见。我们对select标签进行了封装,使其有可定制化的现实效果。打开AppCan IDE(UI2.0),我们选择中标红的按钮,进入下拉列表制作向导。

下拉列表同之前的控件一样,可以通过高级模式配置效果。我们建立一个带标签的下拉列表,并对其代码进行讲解。Demo012范例
效果:

代码:

<!--下拉列表开始-->
<div class="ub t-bla">
<div class="uinn ulim">
标签标签
</div>
<div class="ub-f1 ub uba uc-a1 c-wh b-org us-i sel"> 
<div class="ub-f1 ut-s uinn ulev-1 tx-l">
下拉列表
</div> 
<div class="ubl b-org c-red c-m2 umw2 ub ub-pc uc-r2 ub-ac"> 
<div class="ub-img umw1 umh1 res3"></div> 
</div> 
<select name="sel0" selectedindex="0" id="sel0" οnchange="zy_slectmenu(this.id)"> 
<option>item1</option> 
<option>item2</option> 
<option>item3</option> 
<option>item4</option> 
</select> 
</div>
</div> 

上面代码中,我们可以看到这个控件是由一个容器中包含的标签部分和下拉列表部分组成。下拉列表中又分三个部分:
  文字区域-用于显示选中的条目内容

  按钮区域-是一个容器包含一个下箭头的图标。这个图标通过弹性盒子进行居中显示
  ■Select控件-是一个与整个下拉列表容器等高宽的透明控件,这样用户看到的是我们的文字区域和按钮区域,但实际点击时,点击的是系统Select控件。在select控件中我们通过zy_selectmenu接口截取用户选中的条目,修改文字区域内容
上述控件中,不管是最外面的容器还是子容器,我们都使用的是弹性盒子模型。

4.5 导航栏

在应用开发中,导航栏是组织内容的一种常见方式。它可以给用户更直观的选择和良好的交互体验。AppCan IDE UI2.0)框架对UI1.0中的导航栏控件进行了调整,使用新的弹性盒子模型重新构建了代码,更加便于开发者进行调整定制。我们通过选择IDE控件栏中标红的按钮,来构建一个导航栏。导航栏也可使用高级模式来设定背景色和渐变。我们在index.html中的footer部分构建一个导航栏。Demo013范例
效果:

代码:

<!--iPhone导航条开始-->
<div class="ub c-bla c-m1 tab t-wh">
<input class="uhide" type="radio" name="tabSwitch" checked="true">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-info"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-home"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-set"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-shop"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
<input class="uhide" type="radio" name="tabSwitch">
<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="ub-f1 ub-img5 tp-talk"></div><div class="uinn ulev-2 tx-c">
新闻
</div></div>
</div>

上述代码可以看到,整个导航栏是由一个弹性盒子容器包含5个条目组成的,如果用户需要事先大于5个或小于5个的导航栏,只需要拷贝复制或删除条目即可。每个条目又是由一个radiobox控件和一个纵排的弹性盒子子容器组成。在子容器中,包含图片和文字两个子元素。我们对这些组成部分进行一下分析。
  ■radiobox控件-此控件为隐藏控件,并不现实(uhide),他的作用是通过和其他具有同样name属性的radiobox控件组合使用,来实现条目的单项选择,配合后面子元素的CSS类属性实现选中和未选中效果。
  子容器-用于容纳每一个条目的子元素。同时负责显示选中和未选中状态(tab-act)。我们看一下ui-tab.csstab-act的定义。

input[type="radio"]:checked + div.tab-act
{
background-color:rgba(255,255,255,0.1) !important;
border-radius:0.3em;
border: 0px;
background-image: none;
}

  上面代码可以很清晰的看到当一个radiobox 被选中状态下,他相邻的那个div中的tab-act类表示一个透明度为0.1的圆角矩形。未选中状态下无效果。通过这个类配合之前的单选钮我们可以很简单的实现条目的选中未选中状态变化。
  图片元素-用于显示每一个条目得图片(tp-info)。由于每个条目的图片不同,需要为每个图片元素设定图片资源。目前我们在ui-tab.css中预置了六组图片资源类,用户可以根据需求替换相应的图片资源。每一组图片资源分选中状态和为选中状态,我们以tp-info为例进行分析。

input[type="radio"] + div>div.tp-info{
background: url(res-apple/info.png) 50% 50% no-repeat;
}

input[type="radio"]:checked + div>div.tp-info{
background: url(res-apple/info-act.png) 50% 50% no-repeat;
}

  上述代码中,可以看到当一个radio未选中时,与他相邻的div中的子div元素具有的tp-info属性对应背景图片为info.png。当选中时,与他相邻的div中的子div元素具有的tp-info属性对应背景图片为info-act.png。即配合radiobox我们可以简单的实现图片的变化。
导航栏并不一定都是这种显示效果,我们修改一下代码实现以下另一种效果。

这是上面是中文下方是英文的效果。附件是代码Demo014范例。我们调整了子容器的元素,从一个图片变为了两组文字框。

<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act"><div class="uinn3 tx-c">新闻</div><div class="uinn ulev-1 tx-c">news</div></div>

上面展示的良种效果会有些问题,我们可以看到每一个子容器都是通过ub-f1进行等分的,但在文章最开始我们介绍时提到过,如果自容器中的内容并不等长时,浏览器会动态的调整每个字元素的宽度即时齐都是相同的flex属性。如果确实出现了文字不等长的情况,我们该如何调整呢?我们调整一下Demo014范例的代码Demo015范例

<div ontouchstart="zy_touch('',zy_for)" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
早间新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>

相对于之前,修改后我们为文字外添加了一个容器,通过ub-con定义此文字区域的高宽与父元素相同。而之前每一个文字区域的高度都是被文字撑开的,所以此时为了保证文字区域的高度,我们分别为两个文字区域设定了umh2umh1的最小高度值。由于ub-con定义使用了position:absoluteheight:100%属性,则其高度是父容器的边框高+内边距高+内容高,因此我们不能为原来的文字区域再指定内边距,我们为条目容器指定了uinn3的内边距来代替原来为文字区域设定的uinn3,通过为上方的文字区域指定上下外边界来为两个文字区域进行分隔。通过这种写法,我们可以在各条目文字长度不同的情况下保持宽度的一致。同样,在页面设计中ub-con也可以用到其它有类似问题的地方。
导航条的目的是为了配合页面的切换。那么下面我们演示一下如何通过导航条快速实现页面切换。我们目前已经有了一个index.html和一个index_content.html,那么我们为index.html页面在建立一个内容页面。复制index_content.html,改名为msg_content.html。这个时候我们就有了两个内容页面。我们在script区域添加两个函数

function loadmsgcontent(){
zy_con("content", "msg_content.html", 0, $$("header").offsetHeight);
}
function loadindexcontent(){
zy_con("content", "index_content.html", 0, $$("header").offsetHeight);
}

第一个函数用于修改名字为content的浮动窗口加载的页面为msg_content.html,第二个函数用于修改content浮动窗口加载的页面为index_content.html。然后我们为导航栏中第一个元素和第二个元素分别加上onclick事件,

<div ontouchstart="zy_touch('',zy_for)" οnclick="loadindexcontent()" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
早间新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>
<div ontouchstart="zy_touch('',zy_for)" οnclick="loadmsgcontent()" class="ub-f1 ub ub-ver tab-act uinn3">
<div class="tx-c umh2 umar-b umar-t">
<div class="ub-con ulev-1 ut-s">
新闻
</div>
</div>
<div class="ulev-1 tx-c umh1">
<div class="ub-con">news</div>
</div>
</div>

此时我们可以看到,当我们点击第一个条目和第二个条目时,中间区域的网页内容发生了改变。范例工程参阅附件Demo016范例

4.6 单选框和复选框

单选和复选框是应用中常见的组件,他们一般都会按组的方式实现。我们通过IDE中标红的两个按钮来生成复选和单选控件。我们打带复选框向导

构建一个单个复选框按钮,并对其代码进行分析

代码:

<!--复选框开始-->
<input type="checkbox" name="che1" class="uhide" checked="checked" value=""> 
<div οnclick="zy_for(event)" ontouchstart="zy_touch('btn-act')" class="ub uc-a1 uba c-gra c-m2 b-gra t-bla uinn5 ">
<div class="ub-f1 ut-s tx-l" >item</div>
<div class="che-icon ub-img umw1"></div> 
</div>
<!--
复选框结束-->

述代码可以看到一个复选框由一个隐藏(uhide)checkbox和一个复选框容器组成。复选框容器包含一个文字区域和一个选中状态图标。当用户点击这个复选框容器时触发onclick函数,会调用zy_for函数,此函数会对这个DIV元素之前的Input标签的checked属性做取反操作,即如果checkedtrue则变为false,为false则变为true。与之前select和导航栏控件机制一样,我们通过input和后面元素的CLASS类组合通过input的状态变化达到更换选中状态图标的效果。我们可以看一下che-icon这个类的定义。

input[type=checkbox]+div>div.che-icon {
background-color: transparent;
background-image: url(images/icons-18-white_39.png);
}
input[type=checkbox]:checked+div>div.che-icon {
background-color: transparent;
background-image: url(images/icons-18-white_37.png);
}

上述代码种,当input被选中时,其相邻的div中的子Div元素的che-icon属性会设定图片为icons-18-white_37.png。如果未选中则设定为icons-18-white_39.png。通过这里我们可以看到,我们在控件中广泛采用了input和类进行组合的方式非常简单的实现各种效果。
复选框还有一种变形,我们看看如下范例Demo017范例,通过向导选择

index_contet.html中添加一个水平分组复选框。效果如下

代码:

<!--复选框开始-->
<div class="ub uc-a1 t-bla c-gra c-m2 uba b-gra tx-c"> 
<input type="checkbox" name="che1" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 ubr b-gra uc-l1 ub-f1 che">item</div> 
<input type="checkbox" name="che2" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 ubr b-gra ub-f1 che">item</div> 
<input type="checkbox" name="che3" class="uhide" value=""> 
<div οnclick="zy_for(event)" class="uinn5 uc-r1 ub-f1 che">item</div>
</div>
<!--
复选框结束-->

水平复选框分组其实就是一个容器包含了三个子元素,每个子元素配合一个input标签来控制其效果(che)。我们看一下che类的代码

input[type=checkbox]:checked+div.che {
box-shadow:inset 0 1px 2px rgba(0,0,0,0.6);
}

上述代码表示当input被选中时,为元素添加一个内阴影。
对于纵向排列的复选框分组就不作介绍了,大家可以自己通过模板建立一个,研究一下代码。它其实就是一个容器里放了多个单条复选框而已。
单选框和复选框基本代码和设计都是一致的只是单选框的隐藏input标签类型为radio而已。大家可以研究一下ui-input.css中的类定义

4.7 列表控件

有人说80%的应用界面都是列表形式的,没统计过但是从大概的感觉上可以认为没有什么偏差。AppCan IDE UI(2.0)中,提供了新构建的列表模板。我们通过IDE中的列表向导进行构建Demo018范例

这次我们构建一个带图标的列表。
效果:

代码:

<!--列表开始-->
<div class="uba b-gra c-wh us uc-a ">
<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
<div ontouchstart="zy_touch('btn-act')" class=" ub ubb b-gra c-m2 t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
<div ontouchstart="zy_touch('btn-act')" class="uc-b c-m2 ub t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>
</div>
<!--
列表结束-->

这是一个三个条目的列表,很明显,这个列表与其他控件基本组成元素都是一致的,也是一个容器、子容器加一些元素构造而成。我们主要对一个条目进行讲解。

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<div class="tx-r t-blu ulev-1">Old Phone</div>
<div class="res8 lis-sw ub-img"></div>
</div>

这是列表的第一个条目,我们一行一行进行解析。

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">

这是一个容器,由于是第一行,所以他的圆角要和外面容器的圆角保持匹配,因此我们为其设定圆角(uc-t),这个容器和下一行需要一条分割线,我们设定这个子容器右下边界(ubb),边界色彩为(b-gra),这个条目有一点简便效果,我们采用的是(c-m2)由于其位于容器内,这个遮盖层会和父容器背景色进行组合。这个子容器包含多个元素,这些元素也是以弹性盒子模型进行排版(ub),文字色彩定义为黑色(t-bla),由于容器中的子元素高低不定,因此我们要求其子元素中线对其(ub-ac)。最后是设定列表条目的默认效果(lis 建立了内边距)

<div class="lis-icon ub-img im"></div>

这是容器中的第一个元素,它是一个小图片,我们设定了这个图片的高宽(lis-icon),同时设定了这个图片是(im),图片的展示参数通过(ub-img)来设定。 备注:
默认工程中的ui-img.css定义了我们范例中的范例资源图片,而ui-res.css是我们控件需要的资源图片。

<div class="ub-f1 ut-s">设置</div>

这一行设定了一个弹性区域,他会撑满真个容器的空闲区域(ub-f1),当文字长度超过可容纳区域后,进行缩略(ut-s)

<div class="tx-r t-blu ulev-1">Old Phone</div>

这一行定义了一个文字去,这个文字区的大小会根据文字长度进行调整。我们通过ulev-1对此地的文字进行缩小显示。并通过t-blu设定其颜色为兰色。

<div class="res8 lis-sw ub-img"></div>

最后这个元素是一个小箭头图标。lis-sw定义了他的大小,res8指定了所用的资源,ub-img定义了图片的展示方式。
通过这部分解析我们看到一个列表其实也是由最基本的容器和元素组合而成。通过弹性盒子模型,真个列表的排布会非常简洁明了。

4.8 开关按钮

UI2.0框架中,我们对开关按钮进行了重新实现,配合上一个范例,我们在第一个条目中插入开关按钮来体验一下他的效果。Demo019范例

代码:

<div ontouchstart="zy_touch('btn-act')" class="uc-t ubb c-m2 ub b-gra t-bla ub-ac lis">
<div class="lis-icon ub-img im"></div>
<div class="ub-f1 ut-s">
设置
</div>
<!--
开关按钮开始
-->
<input class="uhide" type="checkbox" checked="true" >
<div class="uba b-gra swi swi-bg uc-a1" οnclick="zy_for(event)"></div>
<!--
开关按钮结束
-->
</div>

上面代码中,我们把前一个范例的第一个条目后面的两个元素删除,替换了一个开关按钮。开关按钮的动画变换也是依赖于input的变化进行控制。其中swi定义了这个控件的变形动画效果,swi-bg定义了这个开关按钮的背景swiinput进行配合定义了不同状态下的效果。

input[type=checkbox]:checked + div.swi{
background-position:-0.1em;
}
input[type=checkbox] + div.swi
{
background-position:-4.01em
}

input标签被选中时,swi的背景位置是-0.3em。当未被选中时,背景位置为-4.01em。通过背景图片位置的变化完成选中状态的变化。
通过上面的讲解,我们展示了UI2.0的框架设计思想。并通过对我们预置组件代码的分析,使大家对如何使用UI2.0框架调整界面有了一个基本的认识。我们总结一下我们公司开发人员的UI设计规则
1.
制作前先考虑好如何组织页面,需要如何布局,在什么地方需要几个容器来进行排版。然后构建架子,使用默认效果类进行排版定位和美化
2.
如果需要使用颜色,请在ui-color.css中根据文本、背景、遮盖、边框等分别扩展自己的类定义
3.
如果需要调整圆角、边距等附加属性请在ui-base.css中进行添加。
4.
如果需要资源,请在ui-res.css中进行扩展
5.
如果需要布局,请在ui-box.css中进行调整
6.
所有调整要遵循默认的命名规则。
遵守这些规则可以使你的代码更容易被其他人阅读,代码复用和调整将会更加简单

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值