Laying out the Wheel(设计轮子)

 

现在我们已经建立了一个基本的控制类,我们可以开始形象化的设计轮子的原理,这样他才能显示在一个圈中。

设计转轮的原理,你需要借助CALayers。它不仅能实现非常酷的效果,也能进行像旋转等的几何操作。如果你对CALayers还不熟,查看CALayers的讲解教程。

要使用layers,你需要导入QuartzCore framework。选择左侧边栏的project然后选择Target,在右侧面板的Build Phases 栏,点击“+”符号,找到QuartzCore并添加。

做完这一步,这个framwork就应该出现在你工程树的某个地方,就像下面这张图片

现在来做设计的初始实现。首先,每一个扇区都是一个UILabel的实例。一会儿,你将会把UIImageView替换为定制的图片。

现在,你用一个简单的红色的背景,这样label的边界就会显示出来,然后你就可以为label填充一个数字。你想要实现的效果类似于在一个圆中舒展开一张卡片,在这种情况下,你希望可骗能完美的填充整个圆圈,所以你需要一个能计算每个label角度的算法。

这是已有的解决方法:

根据anchorPoint属性,每一个CALayer会有一个rotation,这个anchorPoint属性是CGPoint的一个实例,取值范围是(0,0)到(1,1)。anchorPoint是一个layer的中心坐标点,下面的这张图标识了anchorPoint的一些值:

默认情况下,anchorPoint设置为(0.5,0.5),这是layer画面的中心,但是你可以随意改变它。

在这篇教程中,我们希望可以绕圆圈的中心旋转每一个label。要实现这个效果,我们只需为每隔label做以下操作:

1.         设置每个anchorPoint为右边框中点(1.0,0.5

2.         编辑labelposition,以让右边框的中点与圆圈的中心点重合

3.         label应用一个转换让它旋转到合适的位置

现在让我们绘出轮子吧!但是首先,你必须在SMRotaryWheel.m文件的最上边导入QuartzCore

#import <QuartzCore/QuartzCore.h>

然后,用下面的代码替换空的drawWheel方法:

- (void) drawWheel {
    // 1
    container = [[UIView alloc] initWithFrame:self.frame];
    // 2
    CGFloat angleSize = 2*M_PI/numberOfSections;
    // 3
    for (int i = 0; i < numberOfSections; i++) {
        // 4
        UILabel *im = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
        im.backgroundColor = [UIColor redColor];
        im.text = [NSString stringWithFormat:@"%i", i];
        im.layer.anchorPoint = CGPointMake(1.0f, 0.5f);
        // 5
        im.layer.position = CGPointMake(container.bounds.size.width/2.0, 
                                        container.bounds.size.height/2.0); 
        im.transform = CGAffineTransformMakeRotation(angleSize * i);
        im.tag = i;
        // 6
        [container addSubview:im];
    }
    // 7
    container.userInteractionEnabled = NO;
    [self addSubview:container];
}

让我们一步步来看它的工作原理。

1.         这里我们创建了一个把所有东西都放进去的view

2.         这是一个弧度为2*PI的圆(一会儿会有更详细的解释),我们根据我们希望显示的扇区的数目来分割弧度。还给出了我们在扇区之间旋转的account,我们一会会用到。

3.         就像刚才解释的那样,我们为每个扇区创建了一个label并设置它的anchorPoint为右边框的中点。

4.         设置anchorPoint为右边框的中点,现在我们要设置anchorPoint要移动到的点的坐标。所以我们设置labelposition为容器视图的中心。为了旋转label,我们需要设置label的转换为旋转转换。不要担心,你没有必要知道实现它的函数,你可以用CGAffineTransformMakeRotation方法!我们仅仅用扇区的数目乘以每个扇区的弧度。

5.         label添加到我们刚才创建的container view

6.         把这个container添加到主控件(main control

为了保证这个应用能显示一些界面,我们需要在SMViewController中加入wheel类的实例。在SMViewController.m的最上边加入下面语句:

#import "SMRotaryWheel.h"

下一步,用下面的代码替换掉viewDidLoad方法:

- (void)viewDidLoad {
    // 1 - Call super method
    [super viewDidLoad];
    // 2 - Set up rotary wheel
    SMRotaryWheel *wheel = [[SMRotaryWheel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)  
                andDelegate:self 
                withSections:8];
    // 3 - Add wheel to view
    [self.view addSubview:wheel];
}

如果你现在运行程序,你会在每一个图片的上层看到红色的圆花饰。你知道你正在进行正确的追踪!

现在是时间来学习下圆圈、角度、PI、度和弧度。知道了这些知识,你才能正确的根据用户的触碰(或拖拽)组件时决定的movements来旋转扇区容器。