AppleWatch___学习笔记(二)UI搭建和逻辑处理

1.UI搭建

  直接开发,你会发现Apple Watch并不支持AutoLayoutWatchKit里有个类叫做WKInterfaceGroup,乍一看像是UIView,但是这货其实是用来布局的。从 Storyboard中拉一个WKInterfaceGroup出来,在属性检查器(Attributes Inspector)中有个Layout属性,通过设置成Horizontal或Vertical,就可以让这个group下所有的子视图水平排列或竖直排列。再结合AutoLayout的知识,就可以轻松满足要求啦。

  首先,watch的屏幕不大,目前只有38mm和42mm两个尺寸,我们不可能在 这个有限的空间里做非常复杂的界面效果,因此,在界面开发中,应该遵循便于使用和一目了然的原则。watch上的布局方式采用的是一种平面堆放的方式,不再有frame,也不再有约束,控件的布局方式只是一个挨着一个的平面堆放,也不可重叠。但在watch中,提供了group这样一种布局方式,可以让我 们在布局中体现自由与个性的方面。具体如何使用呢?

  (1)首先简单布局介绍

就是我们在不使用group的时候,watch的布局采用的是最基础的堆放方式,从上到下依次排开,例如,我们添加四个label,效果如下:

通过改变label的添加顺序,可以改变其上下位置:

这种方式的布局高度并没有限制,我们可以一直往下排列,在watch上,会出现滑动的效果:

    

  (2)使用Group进行复杂的界面布局

通过上面的布局方式,我们只能进行纵向的排列布局,这并不能达到我们的需求,WatchKit中提供那一套布局的模型:Group。

可以这样理解,group就是将屏幕分成了几各分区,我们可以设置各个分区的排列方式,例如水平或者垂直,通过这样的思路,完成复杂的watch界面布局,例如下面的效果:

这样效果的一个界面,就是将在屏幕中添加了三个Group,最上面的Gorup设置为水平排列模式,在其中添加了两个按钮和一个分割线,中间一个Group是垂直排列模式,放入了一个选择器和一个按钮,最下面一个Group也是水平排列模式,放入了一个按钮和一个时间栏。    Group在界面布局上,不仅可以起到分区屏幕的作用,其还可以设置一些属性来使布局更加漂亮。在storyBoard右侧的设置菜单中,我们可以对这些属性进行操作:

Layout:设置布局模式,分为水平布局和垂直布局两种

insert:可以设置内容区域偏移量,通过这个属性,我们可以使其中填充的控件四周留白

Spacing:其中填充的控件的间距

BackGround:设置Group的背景图案

Mode:设置背景图案的填充方式

Animate:出现时带动画

color:设置Group的背景颜色

Radius:设置Group的圆角度

(3)布局中控件的位置和尺寸设置

在iphone中,我们使用frame或者约束来控制控件的位置和尺寸,在watch中则简单很多,尺寸和位置都是固定的模式,我们只需要做一些设置即可。

   1、控件尺寸的控制

对于控件的尺寸,有三种模式,控件的width和Height都是通过这三个模式设置的:

Relative to Container:自身的尺寸是按照容器的尺寸比例设置的。例如设置为0.5的话,当前控件的尺寸就是容纳其Group的一半。

Size To Fit Content:自身的尺寸与自身内容相关,例如,label中字数的多少决定了label的尺寸。

Fixed:手动设置一个固定的值。

   2、控件位置的控制

因为watch的界面十分简洁,对于控件的位置设置,是通过水平和垂直两个维度来设置的,通过设置每个维度的属性来控制其在容纳它的Group中的位置:

Horizontal:left(左),center(中心),right(右)

Vertical:top(上),center(中心),bottom(下)

注意:

关于图片素材,你可以发现,在Extension和App文件夹中各有一个Assets.xcasssets组,只有将素材放入APP文件夹下的这个组watch才能使用。

 2.UI控件的使用

  (1)Table

   WatchKit中的 WKInterfaceTable不同于UITableView,没有dataSource和delegate,只能通过主动方式填充并展现数据。对应每 一种不同类型的cell,都需要为它构造一个rowController(继承自NSObject),这个rowController负责往这种类型的 row中填充需要展现的内容。

方法如下:

  1. -(id)rowControllerAtIndex:(NSInteger)index;

通过调用这个方法得到指定行的rowController,再调用这个rowController的自定义方法来进行渲染。例如:

  1. - (void)configureRowWithDataModel:(id)dataModel;

另外,如果要插入行和删除行,则要在上述操作之前先调用:

  1. -(void)insertRowsAtIndexes:(NSIndexSet *)rows withRowType:(NSString *)rowType;
  2. -(void)deleteRowsAtIndexes:(NSIndexSet *)rows;

  注意:在iOS开发中如果要刷新UITableView,只要更新数据源后再调用reloadData方法就可以。但是就像之前说 的,WKInterfaceTable并没有主动刷新数据的方法,只能通过调用 [table setRowTypes:nil] 方法先清除所有数据,再用新数据源重新填充一遍。仅仅是这样就算了,假设你现在视图控制器A中,然后被push到了视图控制 器B,那么如果你在B中刷新A中的WKInterfaceTable是没有用的。但是不是完全没用,经过多次测试,我发现,数据源确实是被更新了,但是界 面上的内容并没有刷新。也就是说,数据源和界面没有保持一致。暂时的解决方法是,在需要刷新的时候记录一个标记位,然后在willActivate的时候根据这个标记位进行延时刷新。一个很明显的副作用就是刷新时会产生跳动,相信之后的版本Apple应该会修复这个问题。

WatchOS中的TableView和iOS中的TableView还是有很大的区别,在开发之前,首先我们应该明白WatchOS中的Table有哪些局限性和特点。下面几点是我总结WatchOS中Table的特殊之处:

  1、Table只有行的概念,没有分区的概念,没有头尾视图的概念。

  2、可以通过创建多个Table,来实现分区的效果。

  3、因为Watch上是通过Gruop进行布局适应的,所以没有行高等设置。

  4、Table没有代理,所有行的数据都是采用静态配置的方式。

  5、点击Table中的行触发的方法,是通过重写Interface中的方法来实现的。

  (2)创建一个Table

在storyBoard中拖入你的Table(想要纯代码就不行了),如下:

在Table上拉两个label:

每一个Table中包含一个TableRowController,实际上我们Table上的控件都是通过这个TableRowController进行管理的,因此如果我们需要在代码中控制TableRow上的内容,我们需要创建一个文件作为Table的TableRowController:

将storyBoard中TableRowController的类修改为我们创建的类并指定一个identifier:

                 

然后,我们将两个label关联到TableRowController中:


1

2

3

4

5

6

import WatchKit

class TableRowController: NSObject {

    @IBOutlet var numberLabel: WKInterfaceLabel!

    @IBOutlet var titleLabel: WKInterfaceLabel!

}

将Table关联到interfaceController中:


1

2

3

4

5

class InterfaceControllerMain: WKInterfaceController {

    

    @IBOutlet var Table: WKInterfaceTable!

}

下面,我们开始在interface中对Table做相关配置,首先我们可以先观察一下WKInterfaceTable中有哪些方法和属性:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class WKInterfaceTable : WKInterfaceObject {

    //设置行的类型,数组中对应存放行的类型,数组元素的个数,就是行数

    /*

    通过这个方法,我们可以创建每一行样式都不同的table,行的类型

    实际上就是我们刚才用到的TableRowController,我们可以进行自定义

    */

    public func setRowTypes(rowTypes: [String]) 

    //设置行数和类型 用于创建单一行类型的table

    public func setNumberOfRows(numberOfRows: Int, withRowType rowType: String) // repeating row name

    //这个get方法获取行数,用于我们遍历table中的行,进行内容设置

    public var numberOfRows: Int { get }

    //这个方法会返回某一行,我们可以获取到后进行内容设置

    public func rowControllerAtIndex(index: Int) -> AnyObject?

    //插入一行

    public func insertRowsAtIndexes(rows: NSIndexSet, withRowType rowType: String)

    //删除一行

    public func removeRowsAtIndexes(rows: NSIndexSet)

    //滑动到某一行

    public func scrollToRowAtIndex(index: Int)

}

了解了上面的方法,可以看出,WatchOS的Table配置非常简单易用,例如我们如下配置:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@IBOutlet var Table: WKInterfaceTable!

    override func awakeWithContext(context: AnyObject?) {

        super.awakeWithContext(context)

        let dic:Dictionary<String,String> = ["中国建设银行":"¥1000","中国农业银行":"¥5000","中国银行":"20000","招商银行":"¥401","中国邮政储蓄":"1100"]

        //设置行数与类型

        Table.setNumberOfRows(dic.count, withRowType: "TableRowController")

        //遍历进行设置

        let titleArray:Array<String> = Array(dic.keys)

        for var i=0 ; i < dic.count ; i++ {

            let row:TableRowController = Table.rowControllerAtIndex(i) as! TableRowController

            row.titleLabel.setText(titleArray[i])

            row.numberLabel.setText(dic[titleArray[i]])

            row.numberLabel.setTextColor(UIColor.grayColor())

        }

        // Configure interface objects here.

    }

这样一个展示银行卡余额的界面我们就创建完成了,效果如下:

  (3)关于Table的点击事件

上面我们提到,Table没有所谓代理方法,点击row的时候,我们也是通过两种方式进行逻辑跳转的,一种是在storyBoard中,我们通过拉线跳转,这时如需传值,我们需在interface中实现如下方法:


1

 public func contextForSegueWithIdentifier(segueIdentifier: String, inTable table: WKInterfaceTable, rowIndex: Int) -> AnyObject?

另一种方式,我们可以重写实现InterfaceController中的如下方法,来处理Table的点击事件:


1

public func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int)

无论哪种方式,我们都可以通过参数table和rowIndex来确认点击的具体是那个table和哪一行,进行传值和处理我们的逻辑。

时间: 2024-10-13 02:19:05

AppleWatch___学习笔记(二)UI搭建和逻辑处理的相关文章

Android学习笔记二

17. 在ContentProvider中定义的getType()方法是定义URI的内容类型. 18. SQLiteDatabase类中的insert/delete/update/query方法其实也挺好用的,我在EquipmentProvider类中做了实现 19. Android专门有个单元测试项目(Android Test Project),在这个项目中,可以新建一个继承AndroidTestCase类的具体测试类来单元测试某个功能.我新建了一个AndroidTestProject项目,在

Spring Batch学习笔记二

此系列博客皆为学习Spring Batch时的一些笔记: Spring Batch的架构 一个Batch Job是指一系列有序的Step的集合,它们作为预定义流程的一部分而被执行: Step代表一个自定义的工作单元,它是Job的主要构件块:每一个Step由三部分组成:ItemReader.ItemProcessor.ItemWriter:这三个部分将执行在每一条被处理的记录上,ItemReader读取每一条记录,然后传递给ItemProcessor处理,最后交给ItemWriter做持久化:It

《SQL必知必会》学习笔记二)

<SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语句,但是实际应用中的业务逻辑往往会非常复杂,所以会用到一些比较复杂的查询,如子查询,联合查询. 1.子查询 当一个查询是另一个查询的条件时,称为子查询.但是说到子查询又不的不说它与嵌套查询两者的区别,下面一张图来说明 下面再用一条sql语句来说明他们的关系. 其中在查询中又分为嵌套子查询和相关子查询,他们之间

linux学习笔记二:硬盘信息查询

在linux管理中,硬盘管理是很重要的一部分.包括阵列,分区,逻辑卷等操作,在对硬盘操作前,需要充分的了解硬盘的信息.常用的硬盘查询有以下几种: 1.df  查看文件系统空间使用情况: linux-lszd-db:~ # dfFilesystem     1K-blocks     Used Available Use% Mounted on/dev/sda6      809262496 37615092 770825244   5% /udev             8076412    

马哥学习笔记二十八——nginx反向代理,负载均衡,缓存,URL重写及读写分离

Nginx反向代理 Nginx通过proxy模块实现反向代理功能.在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI.客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server).nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上.如下面的示例中,location的/uri将被替换为上游服务器上的/newuri. location /uri { proxy_pa

hadoop学习笔记(二)

hadoop学习笔记(二) 我的个人博客站点地址:孙星的个人博客主页 后续的学习笔记:hadoop学习笔记 hadoop单节点的搭建 下载hadoop: wget http://apache.fayea.com/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz tar -zxvf hadoop-2.7.1.tar.gz 解压配置免密码登陆: //生成秘钥 ssh-keygen -t rsa //一直回车,在当前目录中会出现2个文件,一个是公钥,一个是私

Java学习笔记二:数据类型

Java学习笔记二:数据类型 1. 整型:没有小数部分,允许为负数,Java整型分4种:int short long byte 1.1 Int最为常用,一个Int类型变量在内存中占用4个字节,取值范围从-2 147 483 6至2 147 483 647 超过20亿,如果用来存储大于20亿的值,最好使用long型. 1.2  int 与Integer: Java中的数据类型分为基本数据类型和复杂数据类型.Int为前者,integer为后者. Integer是int的封装类,提供了很多转换方法,当

laravel3学习笔记(二)

原作者博客:ieqi.net ==================================================================================================== 路由 对于web框架而言,路由系统无疑是其中最关键的部分,Laravel3为用户提供了丰富的路由机制,极大的提高了编码效率.laravel3中,路由可以像一般框架那样绑定到controller类上,也可以直接在路由注册函数中利用回调函数实现访问逻辑.路由注册和配置代码

Caliburn.Micro学习笔记(二)----Actions

Caliburn.Micro学习笔记(二)----Actions 上一篇已经简单说了一下引导类和简单的控件绑定 我的上一个例子里的button自动匹配到ViewModel事件你一定感觉很好玩吧 今天说一下它的Actions,看一下Caliburn.Micro给我们提供了多强大的支持 我们还是从做例子开始 demo的源码下载在文章的最后 例子1.无参数方法调用 点击button把textBox输入的文本弹出来 如果textbox里没有文本button不可点,看一下效果图 看一下前台代码 <Stac

2. 蛤蟆Python脚本学习笔记二基本命令畅玩

2. 蛤蟆Python脚本学习笔记二基本命令畅玩 本篇名言:"成功源于发现细节,没有细节就没有机遇,留心细节意味着创造机遇.一件司空见惯的小事或许就可能是打开机遇宝库的钥匙!" 下班回家,咱先来看下一些常用的基本命令. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/48092873 1.  数字和表达式 看下图1一就能说明很多问题: 加法,整除,浮点除,取模,幂乘方等.是不是很直接也很粗暴. 关于上限,蛤蟆不太清楚