65.9K
CodeProject 正在变化。 阅读更多。
Home

使用CoreGraphics创建简单的Apple Watch应用程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2015年10月14日

CPOL

7分钟阅读

viewsIcon

32352

downloadIcon

101

本文将展示如何使用 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 中选择对象并单击“显示属性检查器” 图标来配置对象。

  1. Label
    • 将标签文本更改为以下消息:转动数字表冠以调整饼图
    • 将文本颜色更改为黄色
    • 将字体更改为 System,大小 12
    • 将行数更改为 2 以允许文本跨越 3 行
    • 将文本颜色更改为橙色
    • 将文本对齐方式更改为“居中”
    • 将标签对齐方式更改为“居中”
  2. 选择器
    • 将选择器样式从 List 更改为 Sequence
    • 将选择器的水平对齐方式设置为“居中”

  3. 一个显示饼图百分比的标签。
    • 将文本更改为 0%
    • 将文本对齐方式设置为“居中”
    • 将标签的水平对齐方式设置为“居中”

编码

好了,我们有了界面,但它现在什么也做不了。我们需要编写一些代码来使其“活”起来。总而言之,我们需要:

  • 创建一个绘制饼图图像的方法
  • 使用图像设置选择器
  • 显示选定的饼图图像
  • 显示选定的饼图百分比

PieChart 类

由于我们将为选择器创建许多图像作为动画帧,因此我们将创建一个可以多次调用的方法来创建不同大小的饼图。

我们将创建一个 PieChart 类,其中包含一个绘制饼图的方法。我们将在 WatchKit 扩展中创建 PieChart 类,因为它将被 Watch 应用使用。要创建类,请转到 项目导航器,右键单击 PieChart WatchKit Extension,然后在弹出菜单中单击 New Files...

选择 watchOS\Source\WatchKit Class 模板

通过继承 NSObject 创建一个 PieChart 类。

创建了 2 个文件:PieChart.hPieChart.mPieChart.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 方法的逻辑可以分解如下:

  1. 圆的常量
    • fullCircle = 2π,是圆的完整角度。initialAngle 用于调整作为输入参数传递给 CGContextAddArc 函数的 startAngleendAngle,该函数以弧度测量从正 x 轴(位于 3 点钟位置)开始的角度。由于我们希望饼图从 12 点钟位置开始,因此我们将角度调整 3π/2。centerPoint 是饼图的中心。饼图的 radiusoutlineWidth 调整,以避免边缘被切断。
  2. 获取图形上下文
    • context 是绘图区域。UIGraphicsBeginImageContextWithOptions 以指定大小创建上下文。将 scale 参数设置为 0.0 将根据设备主屏幕的缩放因子缩放图像。这将确保图像在不同尺寸的不同设备上看起来清晰。
  3. 绘制饼图
    • 在绘制饼图之前,我们通过调用函数 CGContextSetFillColorWithColor 设置颜色。然后,我们调用函数 CGContextAddArc 绘制饼图的弧线。CGContextAddLineToPoint 函数从弧线的末端绘制一条线到饼图的中心。CGContextClosePath 函数通过从中心点到起点绘制一条线来闭合路径。最后一个函数 CGContextFillPath 用先前设置的颜色填充饼图。
  4. 绘制饼图轮廓
    • 绘制轮廓与绘制饼图类似。我们调用 CGContextSetStrokeColorWithColor 来设置轮廓的颜色,而不是调用 CGContextSetFillColorWithColor。我们调用 CGContextStrokePath 来绘制轮廓,而不是调用 CGContextFillPath
  5. 返回图像
    • 最后一步是调用函数 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];
}

接下来,我们将配置 PieChartPickerPercentageLabel

  1. 打开 PieChart WatchKit App 文件夹中的 interface.storyboard 文件。
  2. 单击顶部菜单中的“显示辅助编辑器” 图标,并选择 InterfaceController.m 文件。
  3. 将选择器和标签从 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 应用启动时初始化选择器。

  1. 通过调用 loadImage 函数生成动画图像。
  2. 加载选择器
    • ?for 循环填充 pickerItems 数组,并将饼图图像存储在选择器项的 contentImage 字段中。
    • 通过调用 setItems:pickerItems 用饼图图像初始化 PieChartPicker
  3. 将初始饼图设置为 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 上的界面控制器并更正任何不正确的映射。

结束

希望您喜欢这篇文章并对您有所帮助。编码愉快...

© . All rights reserved.