iOS_26彩票_幸运转盘

最终效果图:

各个view的关系图:

背景圆盘(需要扣图处理)LuckyBaseBackground.png

盖在背景圆盘上面的转盘 LuckyRotateWheel.png

代表一个星座或生肖的按钮背景图片

要创建12个,并以最下方中点为锚点进行旋转

对背景圆盘进行扣图,并在其上面盖上转盘图片的核心代码

在自定义的背景view中,画好了背景圆盘和背景转盘之后,

一次性添加12个代表星座或生肖的按钮,并设置旋转角度

一张集合了所有的代表星座的按钮的背景图片的大图片

一张集合了所有的代表星座的按钮的背景图片的大图片

需要根据不同的按钮的i值,

利用CGImageCreateWithImageInRect方法

从大图片中裁剪出一张小图片作为按钮的背景图片

供控制器调用,让圆转盘(circleBgView)慢悠悠地转

当用户点击圆转盘中心的【开始选号】按钮时,

让circleBgView所在图层,利用核心动画CA,

进行假的疯狂地快速旋转,并且动画完成时,

才让cirleBgView的transform真正地旋转负的一定角度,

让被点击的按钮指向正上方

控制器

//
//  LuckyNumController.h
//  25_彩票
//
//  Created by beyond on 14-8-27.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface LuckyNumController : UIViewController

@end
//
//  LuckyNumController.m
//  25_彩票
//
//  Created by beyond on 14-8-27.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "LuckyNumController.h"
// 两个封装的view
// 顶部的三个按钮作为一整体添加到控制器的view
#import "TopThreeBtnsAsOne.h"
// 中间的所有东东,作为一个整体添加到控制器的view
#import "CircleView.h"
#import "CircleViewDelegate.h"

@interface LuckyNumController ()<CircleViewDelegate>
{
    TopThreeBtnsAsOne *_threeButton;
    CircleView *_circle;
}
@end

@implementation LuckyNumController
#pragma mark - 生命周期方法
// 控制器的view消失的时候,可以暂停转盘
- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    [_circle pauseRotate];
}
// 控制器的view出现的时候,才需慢慢转动转盘
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [_circle startSlowlyRotate];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 1.根据4inch或3.5   添加一个全屏的背景
    [self setupFullScreenBg];

    // 2.添加顶部3个选择按钮作为一个整体
    [self setupTopThreeBtnsAsOne];

    // 3.添加圆转盘整体
    [self setupCircleView];
}
// 1.根据4inch或3.5   添加一个全屏的背景
- (void)setupFullScreenBg
{
    UIImageView *bg = [[UIImageView alloc] initWithFrame:self.view.bounds];
    bg.image = [UIImage imageNamed:[email protected]"[email protected]":@"[email protected]"];
    bg.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:bg];
}
// 2.添加顶部3个选择按钮作为一个整体
- (void)setupTopThreeBtnsAsOne
{
    TopThreeBtnsAsOne *tb = [TopThreeBtnsAsOne threeBtnsAsOne];
    CGFloat cx = self.view.frame.size.width * 0.5;
    CGFloat cy = tb.frame.size.height * 0.5 + 20;
    tb.center = CGPointMake(cx, cy);
    [self.view addSubview:tb];
    _threeButton = tb;
}
// 3.添加圆转盘整体
- (void)setupCircleView
{
    CircleView *circle = [CircleView circleView];
    // 设置代理,监听其内部的 12星座或生肖按钮的点击状态
    circle.delegate = self;
    // 设置转盘为星座类型 或生肖类型
    circle.circleType = CircleViewTypeAstrology;
    circle.circleType = CircleViewTypeAnimal;
    // 置于顶部的三个按钮的下方
    CGFloat cx = _threeButton.center.x;
    CGFloat cy = CGRectGetMaxY(_threeButton.frame) + circle.frame.size.height * 0.5;
    // 对3.5inch作一个调整
    if (!is4inch) {
        // 3.5inch屏幕,往上移动20个点
        cy -= 20;
    }
    circle.center = CGPointMake(cx, cy);
    [self.view addSubview:circle];
    _circle = circle;
}

#pragma mark - 转盘的代理方法 略
@end

幸运选号顶部的
三个按钮,可作为一整体添加到LuckyNumController控制器中

//
//  TopThreeBtnsAsOne.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运选号顶部的 三个按钮,可作为一整体添加到LuckyNumController控制器中

#import <UIKit/UIKit.h>

@interface TopThreeBtnsAsOne : UIView

//  类方法返回 从xib创建的对象
+ (instancetype)threeBtnsAsOne;
@end
//
//  TopThreeBtnsAsOne.m
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运选号顶部的 三个按钮,可作为一整体添加到LuckyNumController控制器中

#import "TopThreeBtnsAsOne.h"

@interface TopThreeBtnsAsOne()

@end

@implementation TopThreeBtnsAsOne

//  类方法返回 从xib创建的对象
+ (instancetype)threeBtnsAsOne
{
    return [[NSBundle mainBundle] loadNibNamed:@"TopThreeBtnsAsOne" owner:nil options:nil][0];
}

@end

幸运转盘CircleView,是中部最大的view,

它包括由两个部组成,

分别是一个开始按钮、一个背景层CircleBgView,

其中背景层CircleBgView
又包括三层,

分别是图片1圆盘(要扣图),图片2转盘,12个按钮

//
//  CircleView.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运转盘CircleView,是中部最大的view,它包括由两个部组成,分别是一个开始按钮、一个背景层CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮

#import <UIKit/UIKit.h>
@protocol CircleViewDelegate;

// 让控制器可以选择幸运转盘的类型,选择星座 还是生肖,从而其内部会从不同的图片中裁剪一个个小按钮的背景图
typedef enum {
    CircleViewTypeAstrology, // 星座
    CircleViewTypeAnimal // 生肖
} CircleViewType;

@interface CircleView : UIView

// 类方法,返回实例对象
+ (instancetype)circleView;
// 让控制器可以选择幸运转盘的类型,选择星座 还是生肖,从而其内部会从不同的图片中裁剪一个个小按钮的背景图
@property (nonatomic, assign) CircleViewType circleType;
// 成员:代理,告诉控制器,内部点击的按钮的切换
@property (nonatomic, weak) id<CircleViewDelegate> delegate;

// 开始慢悠悠地转动圆盘
- (void)startSlowlyRotate;
// 暂停计时器
- (void)pauseRotate;
// 停止圆盘的转动,并且清空计时器
- (void)stopRotate;
@end
//
//  CircleView.m
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运转盘CircleView,是中部最大的view,它包括由两个部组成,分别是一个开始按钮、一个背景层CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮

#import "CircleView.h"
// 背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮
#import "CircleBgView.h"
// 代表一个个星座按钮
#import "CircleItem.h"
#import "CircleViewDelegate.h"

// 速度 : 1秒种转多少度
#define ILCircleRotateSpeedPerSecond (M_PI_4/2)
// 从transform用公式 算出角度
#define ILTransform2Angle(transform) atan2(transform.b, transform.a)

@interface CircleView ()
{
    // 背景层CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮
    CircleBgView *_circleBgView;
    CADisplayLink *_timer;
}
@end

@implementation CircleView
#pragma mark - 生命周期方法
+ (instancetype)circleView
{
    return [[self alloc] init];
}
// 供外部调用,设置【Circle背景View 】上的12个按钮是星座图,还是生肖
- (void)setCircleType:(CircleViewType)circleType
{
    _circleType = circleType;

    // 更换【Circle背景View 】内部要使用的大图片
    if (circleType ==CircleViewTypeAstrology) {
        [_circleBgView set12BtnsBgWithBigImg:@"LuckyAstrology" selected:@"LuckyAstrologyPressed"];
    } else {
        [_circleBgView set12BtnsBgWithBigImg:@"LuckyAnimal" selected:@"LuckyAnimalPressed"];
    }
}
// 初始化内部的子控件:1.开始按钮,2.Circle背景View (圆盘,转盘,12个星座或生肖按钮)
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //        self.backgroundColor = [UIColor yellowColor];
        // 1.添加背景层CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮
        [self setupCircleBgView];

        // 2.添加浮在圆转盘上面的 开始按钮
        [self setupStartBtn];
    }
    return self;
}
// 1.添加背景层CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1圆盘(要扣图),图片2转盘,12个按钮
- (void)setupCircleBgView
{
    // 内部固定了宽高
    CircleBgView *bgView = [CircleBgView circleBgView];
    [self addSubview:bgView];
    _circleBgView = bgView;
}
// 2.添加浮在圆转盘上面的 开始按钮
- (void)setupStartBtn
{
    UIButton *startBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    // 开始按钮,位于圆转盘的中心
    startBtn.bounds = CGRectMake(0, 0, 81, 81);
    startBtn.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
    // 设置按钮图片
    [startBtn setBtnBgImgForNormal:@"LuckyCenterButton" highlightedName:@"LuckyCenterButtonPressed"];
    // 添加监听事件,开始转动转盘
    [startBtn addTarget:self action:@selector(startBtnClicked) forControlEvents:UIControlEventTouchUpInside];

    [self addSubview:startBtn];
}

#pragma mark - 父类方法
// setFrame:和setBounds:能保证尺寸永远是286x286
- (void)setFrame:(CGRect)frame
{
    frame.size = CGSizeMake(ILCircleWH, ILCircleWH);
    [super setFrame:frame];
}

- (void)setBounds:(CGRect)bounds
{
    bounds.size = CGSizeMake(ILCircleWH, ILCircleWH);
    [super setBounds:bounds];
}

#pragma mark - 私有方法
// 监听【开始按钮】的点击事件,利用CA核心动画,进行假的快速旋转
- (void)startBtnClicked
{
    // 0.先清空计时器
    [self stopRotate];

    // 1.停止交互
    self.userInteractionEnabled = NO;

    // 2.利用CA核心动画,进行假的 快速狂转
    [self crazyRotate];

    // 通知代理
    if ([_delegate respondsToSelector:@selector(circleView:willRoateToIndex:)]) {
        [_delegate circleView:self willRoateToIndex:_circleBgView.selectedBtn.tag];
    }
}
// 2.利用CA核心动画进行假的 狂转
- (void)crazyRotate
{
    // 固定写法
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    // 从transform用公式 算出角度
    // #define ILTransform2Angle(transform) atan2(transform.b, transform.a)
    // 算出被点击的按钮的初始角度
    CGFloat btnInitialAngle = ILTransform2Angle(_circleBgView.selectedBtn.transform);
    // 动画持续 时间为2秒
    anim.duration = 2.0;
    // 旋转的目标值是  转10圈 - btnInitialAngle
    anim.toValue = @(M_PI * 20 - btnInitialAngle);
    // 动画效果  淡进 淡出
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    // 代理,动画完成后,会通知代理
    anim.delegate = self;
    // 让其所在的图层开始假的 快速旋转动画
    [_circleBgView.layer addAnimation:anim forKey:nil];
}
#pragma mark - 动画代理方法,动画执行完毕后自动调用
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    // 1.允许交互了
    self.userInteractionEnabled = YES;
    // 从transform用公式 算出角度
    // #define ILTransform2Angle(transform) atan2(transform.b, transform.a)
    // 2. 算出被点击的按钮的初始角度
    CGFloat btnInitialAngle = ILTransform2Angle(_circleBgView.selectedBtn.transform);
    // 3. 让被点击的按钮 指向正上方,即让图层 真正地转 负btnInitialAngle度
    _circleBgView.transform = CGAffineTransformMakeRotation(-btnInitialAngle);

    // 通知代理(控制器) 被点击的按钮的tag
    if ([_delegate respondsToSelector:@selector(circleView:didRoateToIndex:)]) {
        [_delegate circleView:self didRoateToIndex:_circleBgView.selectedBtn.tag];
    }
    // 4.继续慢悠悠地转
    [self performSelector:@selector(startSlowlyRotate) withObject:nil afterDelay:1];
}

#pragma mark 供控制器调用,让圆转盘,开始慢悠悠地转
- (void)startSlowlyRotate
{
    // NSTimer        只适合做频率比较低的事情
    // CADisplayLink  适合做频率比较高的事情
    if (_timer.isPaused) {
        // 如果CADisplayLink仅仅是暂停状态,那么取消暂停
        _timer.paused = NO;
    } else {
        // 先停止旧的 CADisplayLink
        [_timer invalidate];
        // 再创建新的 CADisplayLink,每1/60秒,调用一次self的rotating:方法
        _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(slowlyRotating:)];
        [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    }
}
// 重点~~~ 慢悠悠地旋转
// 1秒调用60次,1/60.0秒调用一次
- (void)slowlyRotating:(CADisplayLink *)timer
{
    // 速度 : 1秒种转多少度
    // #define ILCircleRotateSpeedPerSecond (M_PI_4/2)

    // 时间 * 速度 == 角度
    CGFloat angle = timer.duration * ILCircleRotateSpeedPerSecond;

    // 旋转一定的角度
    _circleBgView.transform = CGAffineTransformRotate(_circleBgView.transform, angle);

}
// 计时器暂停,便可以暂停圆盘的旋转
- (void)pauseRotate
{
    // 暂停计时器 CADisplayLink
    _timer.paused = YES;
}
// 停止圆盘的转动,并且清空计时器
- (void)stopRotate
{
    [_timer invalidate];
    _timer = nil;
}

@end
//
//  CircleViewDelegate.h
//  25_彩票
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  CircleView

#import <Foundation/Foundation.h>
@class CircleView;
@protocol CircleViewDelegate <NSObject>

@optional
- (void)circleView:(CircleView *)circleView willRoateToIndex:(NSUInteger)index;
- (void)circleView:(CircleView *)circleView didRoateToIndex:(NSUInteger)index;

@end

幸运转盘CircleView的背景层是:CircleBgView,

其中背景层CircleBgView
又包括三层,

分别是图片1(背景圆盘, 要扣图),图片2(带棱角的转盘),12个星座按钮(CircleItem)

//
//  CircleBgView.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运转盘CircleView的背景层是:CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1(背景圆盘, 要扣图),图片2(带棱角的转盘),12个星座按钮(CircleItem)
//  背景层(3层:最底部圆盘图片、中间转盘图片、顶部的星座小图片)

#import <UIKit/UIKit.h>

@class CircleItem;

// 在.h文件中声明 变量的存在
extern const int ILCircleWH;

@interface CircleBgView : UIView

// 类方法,返回一个实例对象
+ (instancetype)circleBgView;

// 需要根据不同的按钮的i值,利用CGImageCreateWithImageInRect方法,从大图片中裁剪出一张小图片作为按钮的背景图片
- (void)set12BtnsBgWithBigImg:(NSString *)normal selected:(NSString *)selected;

// 供外界访问,其内部的当前被点击中的 星座按钮
@property (nonatomic, readonly) CircleItem *selectedBtn;

@end
//
//  CircleBgView.m
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运转盘CircleView的背景层是:CircleBgView,其中背景层CircleBgView 又包括三层,分别是图片1(背景圆盘, 要扣图),图片2(带棱角的转盘),12个星座按钮(CircleItem)
//  背景层(3层:最底部圆盘图片、中间转盘图片、顶部的星座小图片)

#import "CircleBgView.h"

// 一个自定义的星座按钮
#import "CircleItem.h"
// 在.m中定义变量
const int ILCircleWH = 286;

@implementation CircleBgView

#pragma mark - 生命周期方法
// 类方法,返回一个实例对象
+ (instancetype)circleBgView
{
    return [[self alloc] init];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        // 1.添加12个的代表星座或生肖的按钮
        [self add12Btns];
    }
    return self;
}
// 1.添加12个的代表星座或生肖的按钮
- (void)add12Btns
{
    for (int i = 0; i < 12; i++) {
        // 按钮内部会 设置自己的锚点 btn.layer.anchorPoint = CGPointMake(0.5, 1);
        // 设置按钮所在图层的锚点(底部中点),坐标系以左上角为 0 0,x向右为正,y向下为正
        // 目的是让所有的按钮在添加的时候,可以围绕锚点,即大圆图片的中心点进行rotate

        CircleItem *btn = [CircleItem buttonWithType:UIButtonTypeCustom];
        // 绑定tag,目的是要告诉代理,点击了哪一个按钮
        btn.tag = i;

        // 设置每个代表生肖的按钮的位置和角度
        // 锚点的x在圆盘的中心,锚点的y也在圆盘的中心,仅仅变化的是代表星座的按钮的角度
        CGFloat posX = ILCircleWH * 0.5;
        CGFloat posY = posX;
        btn.layer.position = CGPointMake(posX, posY);
        // 仅仅根据i,设置每一个代表星座的按钮的旋转角度
        btn.transform = CGAffineTransformMakeRotation(M_PI / 6 * i);
        // 监听按钮点击
        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
        [self addSubview:btn];
        // 第0个默认选中
        if (i == 0) {
            [self btnClick:btn];
        }
    }
}
// 需要根据不同的按钮的i值,利用CGImageCreateWithImageInRect方法,从大图片中裁剪出一张小图片作为按钮的背景图片
- (void)set12BtnsBgWithBigImg:(NSString *)normal selected:(NSString *)selected
{
    // 遍历12个按钮,根据其i值,裁剪不同的位置的小图片,作为其背景图片
    for (int i = 0; i<12; i++) {
        CircleItem *btn = self.subviews[i];
        // 加载大图片
        UIImage *normalBig = [UIImage imageNamed:normal];
        // 裁剪小图片 (像素坐标转成点坐标,在retina坐标下,比例因子为2,一个点代表2个像素)
        CGFloat miniW = normalBig.size.width / 12 * [UIScreen mainScreen].scale;
        CGFloat miniH = normalBig.size.height * [UIScreen mainScreen].scale;
        // 根据i值不同,裁剪不同的rect
        CGRect miniRect = CGRectMake(i * miniW, 0, miniW, miniH);
        // 创建出小图片
        CGImageRef miniNormalCG = CGImageCreateWithImageInRect(normalBig.CGImage, miniRect);
        // 设置裁剪出来的小图片为按钮的背景
        [btn setImage:[UIImage imageWithCGImage:miniNormalCG] forState:UIControlStateNormal];

        // 选中时的背景图片,也是一样的裁剪后,设置到按钮的选中状态下背景图片
        UIImage *selectedBig = [UIImage imageNamed:selected];
        CGImageRef miniSelectedCG = CGImageCreateWithImageInRect(selectedBig.CGImage, miniRect);
        [btn setImage:[UIImage imageWithCGImage:miniSelectedCG] forState:UIControlStateSelected];
    }
}
// 三步曲,控制按钮点击时的切换
- (void)btnClick:(CircleItem *)btn
{
    _selectedBtn.selected = NO;
    btn.selected = YES;
    _selectedBtn = btn;
}

#pragma mark - 父类的方法
// setFrame:和setBounds:能保证尺寸永远是286x286
- (void)setFrame:(CGRect)frame
{
    frame.size = CGSizeMake(ILCircleWH, ILCircleWH);
    [super setFrame:frame];
}

- (void)setBounds:(CGRect)bounds
{
    bounds.size = CGSizeMake(ILCircleWH, ILCircleWH);
    [super setBounds:bounds];
}

#pragma mark - 重点,绘图
// 背景圆盘(需要扣图处理)LuckyBaseBackground.png
- (void)drawRect:(CGRect)rect
{
    // 1.画最底部的背景圆盘
    // 取得当前view的上下文,不须再重新创建上下文对象
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // copy一个ctx对象到栈中,保存现场,并且会复制出一个新的上下文.
    // 在还原现场之前的所有操作,都将在这个新的上下文中执行
    CGContextSaveGState(ctx);

    // 2.在上下文中画一个小点的圆,并裁剪掉上下文,最后将背景圆盘绘制到稍小的圆形上下文中
    // 2.1.画一个稍小些的圆
    CGFloat innerCircleXY = 9;
    CGFloat innerCircleWH = ILCircleWH - innerCircleXY * 2;
    CGRect innerCircleRect = CGRectMake(innerCircleXY, innerCircleXY, innerCircleWH, innerCircleWH);
    // 在上下文中的指定坐标处画一个指定大小的圆
    CGContextAddEllipseInRect(ctx, innerCircleRect);

    // 2.2.裁剪(CGContextClip会把之前所画的剪下来)
    // 意思是 将上下文中 不属于刚才 画的圆的东东,全部清空(清空小圆以外的东东)
    // 上下文中现在只剩下一个稍小的圆形了
    CGContextClip(ctx);
    // 2.3.将稍大的背景圆盘图片 画到刚才裁剪后的上下文中,即为小圆形的上下文中
    // (因为小圆形以外的上下文区域 已经被清空了)
    [[UIImage imageNamed:@"LuckyBaseBackground"] drawInRect:rect];

    // 3.为了画下一张转盘图,因为不须要裁剪,所以恢复现场,还原为以前的正常的rect的上下文(没被裁剪的rect)
    CGContextRestoreGState(ctx);

    // 4.画中间的完整的转盘图 到上下文中
    [[UIImage imageNamed:@"LuckyRotateWheel"] drawInRect:rect];
}

@end

CircleItem
继承自按钮,

一个本类实例,就代表着一个可被点击的星座
或 生肖

//
//  CircleItem.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  CircleItem 继承自按钮,一个本类实例,就代表着一个可被点击的星座 或 生肖

#import <UIKit/UIKit.h>

@interface CircleItem : UIButton

@end
//
//  CircleItem.m
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  继承自按钮,一个本类实例,就代表着一个可被点击的星座 或 生肖

#import "CircleItem.h"

// 生肖 或 星座按钮的宽和高,须与提供的图片一致
const int kCircleItemWidth = 68;
const int kCircleItemHeight = 143;

@implementation CircleItem
#pragma mark - 生命周期方法
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // 设置按钮选中时的背景
        [self setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected.png"] forState:UIControlStateSelected];
        // 设置按钮所在图层的锚点(底部中点),坐标系以左上角为 0 0,x向右为正,y向下为正
        // 目的是让所有的按钮在添加的时候,可以围绕锚点,即大圆图片的中心点进行rotate
        self.layer.anchorPoint = CGPointMake(0.5, 1);
    }
    return self;
}

#pragma mark - 父类的方法
// 重写setFrame:和setBounds:能保证尺寸永远是68x143
- (void)setFrame:(CGRect)frame
{
    frame.size = CGSizeMake(kCircleItemWidth, kCircleItemHeight);
    [super setFrame:frame];
}
- (void)setBounds:(CGRect)bounds
{
    bounds.size = CGSizeMake(kCircleItemWidth, kCircleItemHeight);
    [super setBounds:bounds];
}
// 中须选中,不要高亮状态
- (void)setHighlighted:(BOOL)highlighted {}
// 调整按钮的图片的位置
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    // 获得当前屏幕点的比例,如果是2.0代表retina视网膜屏幕,一个点代表2个像素
    CGFloat scale = [UIScreen mainScreen].scale;
    // 获得图片本身的大小,从而进行 缩小 为正常的点坐标
    CGSize size = [self imageForState:UIControlStateNormal].size;

    // 除以比例因子,得到点坐标下的正常的size
    CGFloat w = size.width/scale;
    CGFloat h = size.height/scale;
    // 设置x y坐标
    CGFloat x = ( contentRect.size.width - w ) * 0.5;
    CGFloat y = ( contentRect.size.height - h ) * 0.5 - 20;
    // 返回调整好的图片的frame
    return  CGRectMake(x, y, w, h);
}

#pragma mark - 触摸事件二大方法
// 点击按钮的时候必定会调用
// 询问鼠标点击的point是否在按钮身上
// 如果返回YES,代表point在按钮身上,系统就会让按钮处理点击事件
// 如果返回NO,代表point部在按钮身上,系统就不会让按钮处理点击事件
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"----%@", NSStringFromCGPoint(point));
   return [super pointInside:point withEvent:event];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    return [super hitTest:point withEvent:event];
}
@end
时间: 2024-10-05 05:41:38

iOS_26彩票_幸运转盘的相关文章

iOS_26_彩票_控制器的view的适配

iOS 7的控制器默认都是全屏的 如图所示: 程序入口是一个导航控制器, 导航控制器的根控制器是一个TabBarController, 因此,状态栏+导航栏会盖住TabBarController控制器的上面64的高度 TabBarController的子控制器是一个TableViewController, 因此,TabBarController的TabBar会盖住TableViewController的下部分49的高度, 因此,TableViewController的数据不能像iOS6那样正常地

【转】iOS25彩票 幸运转盘

原文 : http://www.it165.net/pro/html/201409/21216.html 最终效果图: 各个view的关系图: 背景圆盘(需穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq/2828tKbA7SlMdWNreUJhc2VCYWNrZ3JvdW5kLnBuZzwvc3Ryb25nPjwvcD4KPHA+PGltZyBzcmM9&qu

试探算法_随机生成彩票号码

先给出一般的解决“随机生成7位1—29号数的彩票号码”问题的代码: 1 #include<stdio.h> 2 int main() 3 { 4 int j,i[7];//定义数组保存随机生成不同的7位数字 5 for(i[0]=1;i[0]<=29;i[0]++)//在1——29中随机生成不同的数字 6 for(i[1]=1;i[1]<=29;i[1]++) 7 { 8 if(i[1]==i[0]) continue; 9 for(i[2]=1;i[2]<=29;i[2]+

《世界杯彩票竞猜系统》设计报告

目录 1 文档介绍    4 1.1 文档目的    4 1.2 文档范围    4 1.3 读者对象    4 1.4 参考文献    5 1.5 术语与缩写解释    5 2 系统环境说明    6 3 需求分析    7 3.1 功能需求分析    7 3.2 非功能需求分析    7 4 数据库的命名规则    8 5 概念结构设计    9 6 逻辑结构设计    9 7 物理结构设计    11 7.1 表汇总    11 7.2 表VS    11 7.3 表team    12

[iOS UI进阶 - 2.4] 彩票Demo v1.4 转盘动画

A.需求 幸运广场界面中有一个幸运转盘,平时能够自动缓缓转动 能够选择星座 点击“开始选号”开速旋转转盘,旋转一定周数 转盘转动速度节奏:开始-慢-块-慢-结束 设置其余的背景和按钮 code source: 彩票Demo https://github.com/hellovoidworld/HelloLottery 转盘Demo https://github.com/hellovoidworld/LuckyWheelDemo B.实现 1.使用xib设计转盘 2.自定义类 (1)自定义一个继承U

atitit.恒朋无纸化彩票系统数据接入通信协议

深圳市恒朋科技开发有限公司 Shenzhen Helper Science & Technology Co., Ltd. 恒朋无纸化彩票系统数据接入通信协议 文档版本历史 内容目录 恒朋无纸化彩票系统数据接入通信协议............................................1 文档版本历史..................................................................2 内容目录..................

Html5 canvas 绘制彩票走势图

因需要 要实现一个类似彩票走势图的功能,初次学Html5 ,很多地方不明白,前段时间也发帖请教过这个问题,也是没给个明确说话,在网上搜了很多,也没有实现的例子,今天仔细研究了下,发现其实也不是很难,现将代码贴出来,共同学习! 先来一张效果图: 实现的代码: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <me

scala实现彩票算法

scala实现彩票算法 (1)具体实现代码如下: package hw1 import scala.util.control._ /** * @author BIGDATA */ object Cp { var input=new Array[Int](7) var cp=new Array[Int](7) var level=0 def main(args:Array[String]):Unit={ //var num=readInt buy() printUsr(); kaijiang();

利用Python实现爬去彩票网站数据&amp;mdash;&amp;mdash;小样

写这篇文章纯属自娱自乐. 主要是近期在自学如何利用Python解决IT运维的一些问题时,总是不得其门而入,为了增加学习兴趣,就想通过完成一个小小有趣的爬虫程序激励下自己,同时也把这次经历跟各位道友分享下. Technorati Tags: Python,爬网,彩票,数据,夏明亮 首先申明,本人不是专职coding的,所以,代码部分如果不符合专业审美,还请多多包涵:俺就是纯粹以实习那目标为基础的小白一枚:思路为先,抛砖引玉~ 步骤一:利用搜索引擎找到你需要的信息的网页资源 1. 打开百度搜索"彩票