当前位置: 首页 > 编程日记 > 正文

iOS_25彩票_幸运转盘

终于效果图:




各个view的关系图:



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



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


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

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



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



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

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



一张集合了全部的代表星座的button的背景图片的大图片



一张集合了全部的代表星座的button的背景图片的大图片



须要依据不同的button的i值,

利用CGImageCreateWithImageInRect方法

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



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




当用户点击圆转盘中心的【開始选号】button时,

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

进行假的疯狂地高速旋转,而且动画完毕时,

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

让被点击的button指向正上方



控制器

//
//  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
// 顶部的三个button作为一总体加入到控制器的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个选择button作为一个总体[self setupTopThreeBtnsAsOne];// 3.加入圆转盘总体[self setupCircleView];
}
// 1.依据4inch或3.5   加入一个全屏的背景
- (void)setupFullScreenBg
{UIImageView *bg = [[UIImageView alloc] initWithFrame:self.view.bounds];bg.image = [UIImage imageNamed:is4inch?@"LuckyBackground-568h@2x.jpg":@"LuckyBackground@2x.jpg"];bg.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;[self.view addSubview:bg];
}
// 2.加入顶部3个选择button作为一个总体
- (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星座或生肖button的点击状态circle.delegate = self;// 设置转盘为星座类型 或生肖类型circle.circleType = CircleViewTypeAstrology;circle.circleType = CircleViewTypeAnimal;// 置于顶部的三个button的下方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


幸运选号顶部的三个button,可作为一总体加入到LuckyNumController控制器中

//
//  TopThreeBtnsAsOne.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运选号顶部的 三个button,可作为一总体加入到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.
//  幸运选号顶部的 三个button,可作为一总体加入到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,

它包含由两个部组成,

各自是一个開始button、一个背景层CircleBgView,

当中背景层CircleBgView又包含三层,

各自是图片1圆盘(要扣图),图片2转盘,12个button

//
//  CircleView.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  幸运转盘CircleView,是中部最大的view,它包含由两个部组成,各自是一个開始button、一个背景层CircleBgView,当中背景层CircleBgView 又包含三层,各自是图片1圆盘(要扣图),图片2转盘,12个button#import <UIKit/UIKit.h>
@protocol CircleViewDelegate;// 让控制器能够选择幸运转盘的类型,选择星座 还是生肖,从而其内部会从不同的图片中裁剪一个个小button的背景图
typedef enum {CircleViewTypeAstrology, // 星座CircleViewTypeAnimal // 生肖
} CircleViewType;@interface CircleView : UIView// 类方法,返回实例对象
+ (instancetype)circleView;
// 让控制器能够选择幸运转盘的类型,选择星座 还是生肖,从而其内部会从不同的图片中裁剪一个个小button的背景图
@property (nonatomic, assign) CircleViewType circleType;
// 成员:代理,告诉控制器,内部点击的button的切换
@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,它包含由两个部组成,各自是一个開始button、一个背景层CircleBgView,当中背景层CircleBgView 又包含三层,各自是图片1圆盘(要扣图),图片2转盘,12个button#import "CircleView.h"
// 背景层CircleBgView 又包含三层,各自是图片1圆盘(要扣图),图片2转盘,12个button
#import "CircleBgView.h"
// 代表一个个星座button
#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个buttonCircleBgView *_circleBgView;CADisplayLink *_timer;
}
@end@implementation CircleView
#pragma mark - 生命周期方法
+ (instancetype)circleView
{return [[self alloc] init];
}
// 供外部调用,设置【Circle背景View 】上的12个button是星座图,还是生肖
- (void)setCircleType:(CircleViewType)circleType
{_circleType = circleType;// 更换【Circle背景View 】内部要使用的大图片if (circleType ==CircleViewTypeAstrology) {[_circleBgView set12BtnsBgWithBigImg:@"LuckyAstrology" selected:@"LuckyAstrologyPressed"];} else {[_circleBgView set12BtnsBgWithBigImg:@"LuckyAnimal" selected:@"LuckyAnimalPressed"];}
}
// 初始化内部的子控件:1.開始button,2.Circle背景View (圆盘,转盘,12个星座或生肖button)
- (id)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {//        self.backgroundColor = [UIColor yellowColor];// 1.加入背景层CircleBgView,当中背景层CircleBgView 又包含三层,各自是图片1圆盘(要扣图),图片2转盘,12个button[self setupCircleBgView];// 2.加入浮在圆转盘上面的 開始button[self setupStartBtn];}return self;
}
// 1.加入背景层CircleBgView,当中背景层CircleBgView 又包含三层,各自是图片1圆盘(要扣图),图片2转盘,12个button
- (void)setupCircleBgView
{// 内部固定了宽高CircleBgView *bgView = [CircleBgView circleBgView];[self addSubview:bgView];_circleBgView = bgView;
}
// 2.加入浮在圆转盘上面的 開始button
- (void)setupStartBtn
{UIButton *startBtn = [UIButton buttonWithType:UIButtonTypeCustom];// 開始button,位于圆转盘的中心startBtn.bounds = CGRectMake(0, 0, 81, 81);startBtn.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);// 设置button图片[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 - 私有方法
// 监听【開始button】的点击事件,利用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)// 算出被点击的button的初始角度CGFloat btnInitialAngle = ILTransform2Angle(_circleBgView.selectedBtn.transform);// 动画持续 时间为2秒anim.duration = 2.0;// 旋转的目标值是  转10圈 - btnInitialAngleanim.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. 算出被点击的button的初始角度CGFloat btnInitialAngle = ILTransform2Angle(_circleBgView.selectedBtn.transform);// 3. 让被点击的button 指向正上方,即让图层 真正地转 负btnInitialAngle度_circleBgView.transform = CGAffineTransformMakeRotation(-btnInitialAngle);// 通知代理(控制器) 被点击的button的tagif ([_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个星座button(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个星座button(CircleItem)
//  背景层(3层:最底部圆盘图片、中间转盘图片、顶部的星座小图片)#import <UIKit/UIKit.h>@class CircleItem;// 在.h文件里声明 变量的存在
extern const int ILCircleWH;@interface CircleBgView : UIView// 类方法,返回一个实例对象
+ (instancetype)circleBgView;// 须要依据不同的button的i值,利用CGImageCreateWithImageInRect方法,从大图片中裁剪出一张小图片作为button的背景图片
- (void)set12BtnsBgWithBigImg:(NSString *)normal selected:(NSString *)selected;// 供外界訪问,其内部的当前被点击中的 星座button
@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个星座button(CircleItem)
//  背景层(3层:最底部圆盘图片、中间转盘图片、顶部的星座小图片)#import "CircleBgView.h"// 一个自己定义的星座button
#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个的代表星座或生肖的button[self add12Btns];}return self;
}
// 1.加入12个的代表星座或生肖的button
- (void)add12Btns
{for (int i = 0; i < 12; i++) {// button内部会 设置自己的锚点 btn.layer.anchorPoint = CGPointMake(0.5, 1);// 设置button所在图层的锚点(底部中点),坐标系以左上角为 0 0,x向右为正,y向下为正// 目的是让全部的button在加入的时候,能够环绕锚点,即大圆图片的中心点进行rotateCircleItem *btn = [CircleItem buttonWithType:UIButtonTypeCustom];// 绑定tag,目的是要告诉代理,点击了哪一个buttonbtn.tag = i;// 设置每个代表生肖的button的位置和角度// 锚点的x在圆盘的中心,锚点的y也在圆盘的中心,只变化的是代表星座的button的角度CGFloat posX = ILCircleWH * 0.5;CGFloat posY = posX;btn.layer.position = CGPointMake(posX, posY);// 只依据i,设置每个代表星座的button的旋转角度btn.transform = CGAffineTransformMakeRotation(M_PI / 6 * i);// 监听button点击[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];[self addSubview:btn];// 第0个默认选中if (i == 0) {[self btnClick:btn];}}
}
// 须要依据不同的button的i值,利用CGImageCreateWithImageInRect方法,从大图片中裁剪出一张小图片作为button的背景图片
- (void)set12BtnsBgWithBigImg:(NSString *)normal selected:(NSString *)selected
{// 遍历12个button,依据其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值不同,裁剪不同的rectCGRect miniRect = CGRectMake(i * miniW, 0, miniW, miniH);// 创建出小图片CGImageRef miniNormalCG = CGImageCreateWithImageInRect(normalBig.CGImage, miniRect);// 设置裁剪出来的小图片为button的背景[btn setImage:[UIImage imageWithCGImage:miniNormalCG] forState:UIControlStateNormal];// 选中时的背景图片,也是一样的裁剪后,设置到button的选中状态下背景图片UIImage *selectedBig = [UIImage imageNamed:selected];CGImageRef miniSelectedCG = CGImageCreateWithImageInRect(selectedBig.CGImage, miniRect);[btn setImage:[UIImage imageWithCGImage:miniSelectedCG] forState:UIControlStateSelected];}
}
// 三步曲,控制button点击时的切换
- (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继承自button,

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

//
//  CircleItem.h
//  25_彩票
//
//  Created by beyond on 14-8-30.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  CircleItem 继承自button,一个本类实例,就代表着一个可被点击的星座 或 生肖#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.
//  继承自button,一个本类实例,就代表着一个可被点击的星座 或 生肖#import "CircleItem.h"// 生肖 或 星座button的宽和高,须与提供的图片一致
const int kCircleItemWidth = 68;
const int kCircleItemHeight = 143;@implementation CircleItem
#pragma mark - 生命周期方法
- (id)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {// 设置button选中时的背景[self setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected.png"] forState:UIControlStateSelected];// 设置button所在图层的锚点(底部中点),坐标系以左上角为 0 0,x向右为正,y向下为正// 目的是让全部的button在加入的时候,能够环绕锚点,即大圆图片的中心点进行rotateself.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 {}
// 调整button的图片的位置
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{// 获得当前屏幕点的比例,假设是2.0代表retina视网膜屏幕,一个点代表2个像素CGFloat scale = [UIScreen mainScreen].scale;// 获得图片本身的大小,从而进行 缩小 为正常的点坐标CGSize size = [self imageForState:UIControlStateNormal].size;// 除以比例因子,得到点坐标下的正常的sizeCGFloat 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;// 返回调整好的图片的framereturn  CGRectMake(x, y, w, h);
}#pragma mark - 触摸事件二慷慨法
// 点击button的时候必然会调用
// 询问鼠标点击的point是否在button身上
// 假设返回YES,代表point在button身上,系统就会让button处理点击事件
// 假设返回NO。代表point部在button身上。系统就不会让button处理点击事件
- (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











相关文章:

Python 自动化办公之 Excel 对比工具

作者 | 周萝卜来源丨萝卜大杂烩今天我们继续分享真实的自动化办公案例&#xff0c;希望各位 Python 爱好者能够从中得到些许启发&#xff0c;在自己的工作生活中更多的应用 Python&#xff0c;使得工作事半功倍&#xff01;需求由于工作当中经常需要对比前后两个 Excel 文件&am…

jQuery简单实现iframe的高度根据页面内容自适应的方法(转)

本文实例讲述了jQuery简单实现iframe的高度根据页面内容自适应的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;方式1&#xff1a;//注意&#xff1a;下面的代码是放在和iframe同一个页面中调用 $("#iframeId").load(function () {var mainheight $(t…

linux wc 命令简介

此wc命令不是让大家没有食欲的地方。而是linux下一个简单的小命令。NAMEwc — word, line, character, and byte countSYNOPSISwc [-clmw] [file ...]下面让我们来简单的看一下其支持的参数及其代表的含义。 参数及含义 参数含义-c显示文件的Bytes数(字节数)-l将每个文件的行数…

这个插件竟打通了Python和Excel,还能自动生成代码!

作者 | 云朵君来源丨数据STUDIO加载一个Jupyter插件后&#xff0c;无需写代码就能做数据分析&#xff0c;还帮你生成相应代码&#xff1f;没错&#xff0c;只需要加载这个名为Mito的小工具包&#xff0c;用Python做数据分析&#xff0c;变得和用Excel一样简单&#xff1a;介绍以…

集合list set Map问题

2019独角兽企业重金招聘Python工程师标准>>> ####集合list set Map的个人理解 首先集合说的对一类数据的存储容器&#xff0c;对象都是引用类型并不是基本数据类型 collection 接口 list和set都需实现它 collections 抽象了一些集合的基本功能&#xff0c;reverse s…

python学习第四课

#!/user/bin/env python#-*-coding:utf-8-*-# 一、字符串魔法# &#xff08;1&#xff09;.isalpha()是否是字母或汉字。# 例&#xff1a;# a"张san22"# b"张三lisi"# va.isalpha()# v1b.isalpha()# print(v)# print(v1)# 因为a里含有数字&#xff0c;结果…

PHP 截取字符串专题

1. 截取GB2312中文字符串<?php< ?php//截取中文字符串functionmysubstr($str, $start, $len){$tmpstr ""; $strlen $start $len; for($i 0; $i< $strlen; $i){if(ord(substr($str, $i, 1))> 0xa0){$tmpstr. substr($str, $i, 2); $i; }else$tm…

​GPT-3好“搭档”:这种方法缓解模型退化,让输出更自然

作者 | LZM来源丨数据实战派文本生成对于许多自然语言处理应用来说都是非常重要的。但神经语言模型的基于最大化的解码方法&#xff08;如 beam search&#xff09;往往导致退化解&#xff0c;即生成的文本是不自然的&#xff0c;并且常常包含不必要的重复。现有的方法通过采样…

(Question)CSS中position的绝对定位问题

RT,绝对定位相对于定位的元素存在是哪里&#xff1f; https://yunpan.cn/crjSMTiak2srZ 访问密码 1570转载于:https://www.cnblogs.com/LiuChunfu/p/5139958.html

BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)

题目描述 Bob有一棵 nn 个点的有根树&#xff0c;其中1号点是根节点。Bob在每个点上涂了颜色&#xff0c;并且每个点上的颜色不同。 定义一条路径的权值是&#xff1a;这条路径上的点&#xff08;包括起点和终点&#xff09;共有多少种不同的颜色。 Bob可能会进行这几种操作&am…

ls -l |wc -l命令多统计一行

#ls -l |wc -l注意&#xff1a;总用量也占用1行&#xff0c;所以统计出来的是14而不是13其他网友提醒 #ls -l |wc -l 就统计实际的行&#xff0c;放大就看出效果1和l不同

驱动数字经济加速,摩尔线程发布全新元计算架构MUSA和GPU产品

2022年3月30日&#xff0c;北京——摩尔线程今天举行主题为“元动力 创无限”的春季发布会。摩尔线程创始人兼CEO张建中解读了“元计算”这一产业趋势&#xff0c;并发布全新架构及系列重磅新品&#xff0c;包括&#xff1a;MUSA&#xff08;Moore Threads Unified System Arch…

HDU 4869 Turn the pokers(思维+组合公式+高速幂)

Turn the pokers 大意&#xff1a;给出n次操作&#xff0c;给出m个扑克。然后给出n个操作的个数a[i]&#xff0c;每一个a[i]代表能够翻的扑克的个数&#xff0c;求最后可能出现的扑克的组合情况。Hint Sample Input&#xff1a; 3 3 3 2 3 For the this example: 0 express fac…

马云打响本地生活消费攻坚战,饿了么获手淘一级入口,美团危险了

8月2日&#xff0c;细心的网友可以发现&#xff0c;手机淘宝App首页已上线“饿了么外卖”&#xff0c;饿了么成为手机淘宝首页的10个默认入口之一。这也就意味着以后手机淘宝用户可以通过淘宝首页新入口进入外卖服务&#xff0c;在应用内直接完成由饿了么提供的订餐外卖服务。 …

Linux文件,文件描述符以及dup()和dup2()

一.Linux中文件 可以分为4种&#xff1a;普通文件、目录文件、链接文件和设备文件。1、普通文件是用户日常使用最多的文件&#xff0c;包括文本文件、shell脚本、二进制的可执行和各种类型的数据。ls -lh 来查看某个文件的属性&#xff0c;可以看到有类似 -rw-r--r-- &#xff…

摩尔线程推出首款数据中心级全栈功能GPU:MTT S2000

2022年3月30日&#xff0c;北京——摩尔线程正式推出首款基于其先进架构MUSA统一系统架构&#xff08;Moore Threads Unified System Architecture&#xff09;打造的数据中心级多功能GPU产品MTT S2000。摩尔线程MTT S2000基于其第一代MUSA架构GPU芯片苏堤研发制成&#xff0c;…

jquery 获取 outerHtml 包含当前节点本身的代码

在开发过程中&#xff0c;jQuery.html() 是获取当前节点下的html代码&#xff0c;并不包含当前节点本身的代码&#xff0c;然后我们有时候确需要&#xff0c;找遍jQuery api文档也没有任何方法可以拿到。 看到有的人通过parent().html()&#xff0c;如果当前元素没有兄弟元素还…

修改CentOS yum源

解决在CentOS yum源下载慢的办法最近在虚拟机下面安装了个CentOS 5.5&#xff0c;使用yum更新时发现下载速度异常慢。可以修改yum的配置文件&#xff0c;把其镜像指向国内的服务器即可。 方案一&#xff1a; # cd /etc/yum.repos.d/ # mv CentOS-Base.repo CentOS-Base.repo.b…

带monkey的测流量!

为什么80%的码农都做不了架构师&#xff1f;>>> //public static void flow(){ //String command1 "adb shell monkey -p com.netease.newsreader.activity -s 500 -v 2000"; //String command2 "adb shell ps"; //String str"com.nete…

实现AI技术自立自强,国产深度学习框架面临三大难题

作为推动AI应用大规模落地的关键力量&#xff0c;深度学习框架的重要性日益凸显。它不仅关系国计民生的行业和领域广泛的应用&#xff0c;同样也对信息系统的科技安全有着决定性的意义。 “深度学习框架在人工智能技术体系中&#xff0c;处于贯通上下的腰部位置&#xff0c;它下…

关于Android H5混合开发遇到的问题

2019独角兽企业重金招聘Python工程师标准>>> 添加WebChromeClient&#xff0c;复写onJsAlert、onJsConfirm、onJsPrompt方法后&#xff0c;弹框异常退出问题 项目经理说&#xff0c;Android没有处理弹框&#xff0c;点击按钮没有反应&#xff0c;iOS就可以。于是就复…

手动配置lnmp环境

做php开发的&#xff0c;想要进一步提升自己&#xff0c;手动搭建开发环境&#xff0c;我想是必须经历的一个坎。虽然说有很多第三方集成环境可供使用&#xff0c;但我想说的是在你没有自己搭建过一次环境的时候&#xff0c;你没有太多的资本去“偷懒”。虽然我自己也是个菜鸟&…

负载均衡,会话保持,session同步

一&#xff0c;什么负载均衡一个新网站是不要做负载均衡的&#xff0c;因为访问量不大&#xff0c;流量也不大&#xff0c;所以没有必要搞这些东西。但是随着网站访问量和流量的快速增长&#xff0c;单台服务器受自身硬件条件的限制&#xff0c;很难承受这么大的访问量。在这种…

终于“打造”出了一个可以随时随地编程的工具

作者 | 老表来源丨简说Python分享概要 系统&#xff1a;阿里云ECS共享型n4服务器 1核2g 存储50g&#xff08;双十一便宜买的&#xff0c;180元/3年&#xff09;环境&#xff1a;自带python3.6.8 方便演示&#xff0c;直接使用它开始动手动脑 首先我们需要连接上服务器&#xff…

JVM堆 栈 方法区详解

一、栈 每当启用一个线程时&#xff0c;JVM就为他分配一个JAVA栈&#xff0c;栈是以帧为单位保存当前线程的运行状态 栈是由栈帧组成&#xff0c;每当线程调用一个java方法时&#xff0c;JVM就会在该线程对应的栈中压入一个帧 只有在调用一个方法时&#xff0c;才为当前栈分配一…

ECSHOP学习笔记

帮助 http://help.ecshop.com/index.phpECSHOP各文件夹功能说明 1、根目录&#xff1a;前台程序文件2、admin&#xff1a;后台程序文件夹 --根目录&#xff1a;后台程序文件 *.php文件 --help\zh_cn&#xff1a;各功能的帮助文件 *.xml文件 --images&#xff1a;后台页面…

Redis主从复制配置

环境描述Redis Master&#xff1a;192.168.1.100 6379(Ubuntu系统)Redis Slave1&#xff1a;192.168.1.101 6380(Ubuntu系统)Redis Slave2&#xff1a;192.168.1.102 6381(Ubuntu系统) 安装redis分别在192.168.1.100、192.168.1.101、192.168.1.102三台机器上安装redis&#xf…

利用 Python 打造一个语音合成系统

作者 | thedaydreamer来源丨CSDN博客背景一直对语音合成系统比较感兴趣&#xff0c;总想能给自己合成一点内容&#xff0c;比如说合成小说&#xff0c;把我下载的电子书播报给我听等等。语音合成系统其实就是一个基于语音合成的工具&#xff0c;但是这个东西由于很多厂家都提供…

干货:排名前 16 的 Java 工具类!

2019独角兽企业重金招聘Python工程师标准>>> 干货&#xff1a;排名前 16 的 Java 工具类&#xff01; 在Java中&#xff0c;工具类定义了一组公共方法&#xff0c;这篇文章将介绍Java中使用最频繁及最通用的Java工具类。以下工具类、方法按使用流行度排名&#xf…

使用ecshop电子商务系统的100个小问题

总结100条关于操作ecshop电子商务系统的小问题。1:如何修改网站"欢迎光临本店"回答:languages\zh_cn\common.php文件中&#xff0c; $_LANG[welcome] 欢迎光临本店;将他修改成你需要的字样。2:如何修改首页"热门搜索关键字"回答:后台->系统设置->网…