最近在做一个有关圆形的控件,发现有关圆形控件里面的布局涉及一些简单的算法,我这个人记性不太好,所以总结一下,怕时间长了,到时候忘了,又要从头开始研究。
一、理解坐标系
1、左手坐标系与右手坐标系
在我们数学中的坐标系一般采用的是右手坐标系,在 iOS开发中,存在多种坐标系。首先我们看一张图,来理解一下左手坐标系和右手坐标系:
2、UIView坐标系
在iOS的UIView中,统一使用左手坐标系,也就是坐标原点在左上角.
3、Quartz坐标系
Quartz(Core Graphics)坐标系使用的右手坐标系,原点在左下角,所以所有使用Core Graphics画图的坐标系都是右手坐标系,当使用CG的相关函数画图到UIView上的时候,需要注意CTM的Flip变换,要不然会出现界面上图形倒过来的现象。由于UIKit的提供的高层方法会自动处理CTM(比如UIImage的drawInRect方法),所以无需自己在CG的上下文中做处理。
4、CALayer坐标系
这个有些变态了,其坐标系和平台有关,在Mac中CALayer使用的是右手坐标系,其原点在左下角;iOS中使用的左手坐标系,其原点在左上角。
二、iOS中UIView的坐标系
1、右手坐标系下圆的坐标系
我们在右手坐标系下,画一个圆,然后把对应的弧度和象限标出来,如下图:
这个貌似看着还比较顺眼,因为我么以前一直用的都是这种坐标系。那么在iOS中,遵循左手坐标系的UIView中,圆对应的坐标系是怎么样的呢?
2、左手坐标系下圆的坐标系
iOS中UIView采用的是左手坐标系,原点在左上角,如下图所示:
细心的朋友会发现,其实这个左手坐标系和右手坐标系关于X轴对称,那么左手系下对应的圆的坐标系是怎样的呢?我么一起来看看下图:
我们可以看出,这个圆对应弧度是按顺时针标注的,所对应的象限也发生了改变。
三、在指定的弧度上创建按钮
首先先写一段代码:
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#import "ViewController.h"
@interface ViewController ()
{
float radius; //半径
}
@property (retain, nonatomic) UIView *baseView;
@end
@implementation ViewController
@synthesize baseView;
- (void)viewDidLoad {
[super viewDidLoad];
baseView = [[UIView alloc] initWithFrame:CGRectMake(20, 100, SCREEN_WIDTH-40, SCREEN_WIDTH-40)];
baseView.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self.view addSubview:baseView];
//设置圆心
UIView *centerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
centerView.center = baseView.center;
centerView.backgroundColor = [UIColor redColor];
[self.view addSubview:centerView];
[self createCircleButtonWithAngle:0];
}
//创建圆上指定角度对应的按钮
- (void)createCircleButtonWithAngle:(CGFloat)angle
{
radius = baseView.frame.size.width/2; //半径
CGFloat x = radius*cos(angle);
CGFloat y = radius*sin(angle);
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
btn.center = CGPointMake(radius+x, radius+y);
btn.backgroundColor = [UIColor orangeColor];
btn.layer.cornerRadius = btn.frame.size.width/2;
[baseView addSubview:btn];
}
@end
我们来小试牛刀,首先来看看几个特殊角度。
1、在0 PI (0度)处创建按钮
把角度改成 0
//调用创建按钮的方法
[self createCircleButtonWithAngle:0];
0PI对应的位置如下:
2、在0.5 PI (90度)处创建按钮
把角度改成 0.5*M_PI
//调用创建按钮的方法
[self createCircleButtonWithAngle:0.5*M_PI];
0PI对应的位置如下:
3、在1.0 PI (180度)处创建按钮
把角度改成 M_PI
//调用创建按钮的方法
[self createCircleButtonWithAngle:M_PI];
M_PI 对应的位置如下:
4、在1.5 PI (270度)处创建按钮
把角度改成 1.5*M_PI
//调用创建按钮的方法
[self createCircleButtonWithAngle:1.5*M_PI];
1.5*M_PI 对应的位置如下:
5、创建一连串按钮
用下面这段代码替换 [self createCircleButtonWithAngle:angle*M_PI];
CGFloat angle=0;
while (angle <= 2.0) {
[self createCircleButtonWithAngle:angle*M_PI];
angle = angle + 0.1;
}
效果图: