使用CoreGraphics创建简单的Apple Watch应用程序
本文将展示如何使用 CoreGraphics 创建一个绘制饼图的 Apple Watch 应用。
引言
本文的目的是展示创建一个使用 CoreGraphics 绘制饼图的 Watch 应用是多么容易。我当时正在编写一个应用,需要一系列简单的图像作为动画帧。我发现手动生成许多图像非常耗时,而且对图像进行微小的尺寸更改也很麻烦。因此,我做了一些研究,发现 CoreGraphics 是一个解决方案。
完整的源代码可以从 github 下载:https://github.com/yuetwong/PieChart。
示例应用如下所示:
入门
在 Xcode 中创建一个新项目
让我们从在 Xcode 中创建一个新项目开始。请注意,我正在使用 WatchOS 2.0 和 Xcode 7.0.1。要创建一个新项目,请导航到 File\New\Project.. 并选择 watchOS\Application\iOS App with WatchKit App 模板。
输入产品名称为 PieChart,并取消选中 Include Notification Scene,因为我们不会使用通知场景。
在下一个屏幕上,选择一个目录来存储新项目。
设计界面
新项目应具有以下结构:
打开 PieChart WatchKit App 文件夹下的 Interface.storyboard
。您应该会看到一个空的界面控制器。向空的界面控制器添加以下界面对象:2 个标签和一个选择器。
通过在 storyboard 中选择对象并单击“显示属性检查器” 图标来配置对象。
- Label
- 将标签文本更改为以下消息:
转动数字表冠以调整饼图
- 将文本颜色更改为黄色
- 将字体更改为 System,大小 12
- 将行数更改为 2 以允许文本跨越 3 行
- 将文本颜色更改为橙色
- 将文本对齐方式更改为“居中”
- 将标签对齐方式更改为“居中”
- 将标签文本更改为以下消息:
- 选择器
- 将选择器样式从 List 更改为 Sequence
- 将选择器的水平对齐方式设置为“居中”
- 一个显示饼图百分比的标签。
- 将文本更改为 0%
- 将文本对齐方式设置为“居中”
- 将标签的水平对齐方式设置为“居中”
编码
好了,我们有了界面,但它现在什么也做不了。我们需要编写一些代码来使其“活”起来。总而言之,我们需要:
- 创建一个绘制饼图图像的方法
- 使用图像设置选择器
- 显示选定的饼图图像
- 显示选定的饼图百分比
PieChart 类
由于我们将为选择器创建许多图像作为动画帧,因此我们将创建一个可以多次调用的方法来创建不同大小的饼图。
我们将创建一个 PieChart
类,其中包含一个绘制饼图的方法。我们将在 WatchKit 扩展中创建 PieChart
类,因为它将被 Watch 应用使用。要创建类,请转到 项目导航器,右键单击 PieChart WatchKit Extension,然后在弹出菜单中单击 New Files...。
选择 watchOS\Source\WatchKit Class 模板
通过继承 NSObject
创建一个 PieChart
类。
创建了 2 个文件:PieChart.h 和 PieChart.m。PieChart.h 是头文件,PieChart.m 是源文件。
PieChart
类需要使用 CoreGraphics
。为了使用 CoreGraphics
库函数,我们需要导入 UIKit.h 文件。在 PieChart.h 头文件中添加以下行以导入 UIKit.h 文件。
#import <UIKit/UIKit.h>
PieChart
类将有一个方法 PieChartImageBySize
,它将创建一个饼图图像。方法开头的 +
号表示该方法是一个类方法。您可以直接调用类方法而无需创建类的实例,这与实例方法不同。
PieChart.h 文件如下所示:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PieChart : NSObject
// class method for drawing a pie chart
+(UIImage * )PieChartImageBySize:(float)imageSize outlineWidth:(CGFloat)outlineWidth
pieColor:(UIColor *)pieColor startRatio:(CGFloat)startRatio
endRatio:(CGFloat)endRatio;
@end
现在,我们准备编写创建饼图图像的方法。打开 PieChart.m 文件,并在 @implementation
和 @end
行之间添加 PieChartImageBySize
的代码。
PieChartImageBySize
方法的逻辑可以分解如下:
- 圆的常量
fullCircle
= 2π,是圆的完整角度。initialAngle
用于调整作为输入参数传递给CGContextAddArc
函数的startAngle
和endAngle
,该函数以弧度测量从正 x 轴(位于 3 点钟位置)开始的角度。由于我们希望饼图从 12 点钟位置开始,因此我们将角度调整 3π/2。centerPoint
是饼图的中心。饼图的radius
由outlineWidth
调整,以避免边缘被切断。
- 获取图形上下文
context
是绘图区域。UIGraphicsBeginImageContextWithOptions
以指定大小创建上下文。将scale
参数设置为 0.0 将根据设备主屏幕的缩放因子缩放图像。这将确保图像在不同尺寸的不同设备上看起来清晰。
- 绘制饼图
- 在绘制饼图之前,我们通过调用函数
CGContextSetFillColorWithColor
设置颜色。然后,我们调用函数CGContextAddArc
绘制饼图的弧线。CGContextAddLineToPoint
函数从弧线的末端绘制一条线到饼图的中心。CGContextClosePath
函数通过从中心点到起点绘制一条线来闭合路径。最后一个函数CGContextFillPath
用先前设置的颜色填充饼图。
- 在绘制饼图之前,我们通过调用函数
- 绘制饼图轮廓
- 绘制轮廓与绘制饼图类似。我们调用
CGContextSetStrokeColorWithColor
来设置轮廓的颜色,而不是调用 CGContextSetFillColorWithColor。我们调用CGContextStrokePath
来绘制轮廓,而不是调用CGContextFillPath
。
- 绘制轮廓与绘制饼图类似。我们调用
- 返回图像
- 最后一步是调用函数
UIGraphicsGetImageFromCurrentImageContext
来获取图像并返回给调用者。我们还使用函数UIGraphicsEndImageContext
关闭上下文。
- 最后一步是调用函数
+(UIImage * )PieChartImageBySize:(float)imageSize outlineWidth:(CGFloat)outlineWidth
pieColor:(UIColor *)pieColor startRatio:(CGFloat)startRatio endRatio:(CGFloat)endRatio
{
// 1. Constants for circle
CGFloat fullCircle = 2.0 * M_PI;
CGFloat initialAngle = 3.0 * M_PI_2;
CGFloat startAngle = startRatio * fullCircle + initialAngle;
CGFloat endAngle = endRatio * fullCircle + initialAngle;
CGPoint centerPoint = CGPointMake(imageSize/2, imageSize/2);
CGFloat radius = (imageSize/2) - outlineWidth;
// 2. Get graphics context
CGSize contextSize = CGSizeMake(imageSize, imageSize);
bool opaque = YES;
CGFloat scale = 0.0;
UIGraphicsBeginImageContextWithOptions(contextSize, opaque, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
// 3. draw the pie chart
CGContextSetFillColorWithColor(context, pieColor.CGColor);
CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, startAngle, endAngle, 0);
CGContextAddLineToPoint(context, centerPoint.x, centerPoint.y);
CGContextClosePath(context);
CGContextFillPath(context);
// 4. draw the outline
CGContextSetLineWidth(context, outlineWidth);
CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, 0, fullCircle, 0);
CGContextStrokePath(context);
// 5. return the image
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
现在我们有了一个可以创建饼图图像的函数,我们可以编写下一个函数,它将创建 101 个饼图图像。打开 PieChart WatchKit Extension 文件夹中的 InterfaceController.m 文件,并添加以下行以导入 PieChart.h 头文件。
#import "PieChart.h"
然后,添加 loadImage
函数。该函数通过调用 PieChartImageBySize
函数生成 101 个饼图图像。start
比率为 0.0,这意味着饼图从 12 点钟位置开始。end
比率通过当前图像索引除以图像总数来计算。该函数将所有饼图图像打包成一个动画图像并返回给调用者。
-(UIImage *)loadImage {
UIImage * image;
float start = 0.0;
float end = 0.0;
int totalImages = 100;
float imageSize = 100;
float outlineWidth = 5.0;
UIColor * color = [UIColor cyanColor];
NSMutableArray * animationFrames = [NSMutableArray array];
// generate pie chart images for the values of 0 to 100
for( int i = 0; i <= totalImages; i++)
{
end = (float)i/(float)totalImages;
image = [PieChart PieChartImageBySize:imageSize outlineWidth:outlineWidth
pieColor:color startRatio:start endRatio:end];
[animationFrames addObject:image];
}
// set the animation duration to be very short as the digital crown can dial very fast
float animationDuration = 0.0;
return [UIImage animatedImageWithImages:animationFrames duration:animationDuration];
}
接下来,我们将配置 PieChartPicker
和 PercentageLabel
。
- 打开 PieChart WatchKit App 文件夹中的 interface.storyboard 文件。
- 单击顶部菜单中的“显示辅助编辑器”
图标,并选择 InterfaceController.m 文件。
- 将选择器和标签从 storyboard 按住 CTRL 拖动到 InterfaceController.m 文件中的
@interface
部分。我们将选择器命名为PieChartPicker
,将标签命名为PercentageLabel
。
将选择器按住 CTRL 拖动到 @implementation
部分,以添加一个函数来更改 PercentageLabel
显示的百分比值。
在 pickerValueChanged
函数中添加以下行,以便在数字表冠滚动时标签将显示新的百分比值。
// update the label to display the new percentage
self.PercentageLabel.text = [NSString stringWithFormat:@"%d%%", value];
最后,将以下代码添加到 awakeWithContext
以在 Watch 应用启动时初始化选择器。
- 通过调用
loadImage
函数生成动画图像。 - 加载选择器
- ?
for
循环填充pickerItems
数组,并将饼图图像存储在选择器项的contentImage
字段中。 - 通过调用
setItems:pickerItems
用饼图图像初始化PieChartPicker
- ?
- 将初始饼图设置为 30%。
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
// 1. generate the animated images
UIImage *image = [self loadImage];
// 2. load the picker with images
NSMutableArray * pickerItems = [NSMutableArray array];
for( int i=0; i< image.images.count; i++)
{
WKPickerItem * item = [[WKPickerItem alloc]init];
item.contentImage = [WKImage imageWithImage:[image.images objectAtIndex:i]];
[pickerItems addObject:item];
}
[self.PieChartPicker setItems:pickerItems];
// 3. set the initial pie chart to 30%
[self.PieChartPicker setSelectedItemIndex:30];
}
构建并运行!
您应该能够通过选择“iPhone X + Apple Watch”方案并单击“播放”按钮?来在模拟器上构建和运行应用。
第一次加载应用可能需要一点时间。如果模拟器崩溃并显示错误消息:无法找到应用程序 ID,只需重新运行即可。如果 storyboard 上的任何界面对象未正确映射,模拟器也可能会崩溃。右键单击 storyboard 上的界面控制器并更正任何不正确的映射。
结束
希望您喜欢这篇文章并对您有所帮助。编码愉快...