美文网首页
iOS不到100行代码实现时钟功能

iOS不到100行代码实现时钟功能

作者: QuakOrigin | 来源:发表于2018-06-29 14:28 被阅读0次

利用 UIViewtransform 函数 CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)
该方法需要传入一个角度值的参数,所以需要实时获取当前时间的时分秒数值,这里参考用 NSCalendar 日历类来获取相关数值,然后还需要一个 UIView 的实例变量,当然如果想要秒针动起来,NSTimer 也是必不可少的。
当然,首先需要几张图片。时钟指针图片来自 阿里巴巴矢量图库, 表盘来自百度。

clock_bg.png
pt_hour.png
pt_minute.png
pt_second.png

直接上代码,首先需要背景表盘与三根时钟指针

@interface LayerClockViewController ()

@property (nonatomic, strong) UIImageView *imgClock;
@property (nonatomic, strong) UIImageView *hourHand;
@property (nonatomic, strong) UIImageView *minuteHand;
@property (nonatomic, strong) UIImageView *secondHand;

@end

这里偷懒了,imgClock 做了懒加载,指针一起处理了。

- (UIImageView *)imgClock
{
    if(!_imgClock) {
        
        CGPoint point = self.view.center;
        
        _imgClock = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 250, 250)];
        _imgClock.center = point;
        [self.view addSubview:_imgClock];
        
        _secondHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        _secondHand.center = point;
        _secondHand.layer.anchorPoint = CGPointMake(0.5, 0.9);
        [self.view addSubview:_secondHand];
        
        _minuteHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        _minuteHand.center = point;
        _minuteHand.layer.anchorPoint = CGPointMake(0.5, 0.9);
        [self.view addSubview:_minuteHand];
        
        _hourHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        _hourHand.center = point;
        _hourHand.layer.anchorPoint = CGPointMake(0.5, 0.8);
        [self.view addSubview:_hourHand];
    }
    return _imgClock;
}

注意属性 anchorPoint 的作用,为视图添加锚点,不加这行代码的话,转起来会比较酸爽。
然后是钟表视图添加图片

- (void)drawClock
{
    CALayer *layerClock = [[CALayer alloc] init];
    layerClock.frame = CGRectMake(0, 0, self.imgClock.frame.size.width, self.imgClock.frame.size.height);
    layerClock.contents = (__bridge id)[UIImage imageNamed:@"clock_bg"].CGImage;
    [self.imgClock.layer addSublayer:layerClock];
    
    CALayer *layerHour = [[CALayer alloc] init];
    layerHour.frame = CGRectMake(0, 0, 100, 100);
    layerHour.contents = (__bridge id)[UIImage imageNamed:@"pt_hour"].CGImage;
    [self.hourHand.layer addSublayer:layerHour];

    CALayer *layerMinute = [[CALayer alloc] init];
    layerMinute.frame = CGRectMake(0, 0, 100, 100);
    layerMinute.contents = (__bridge id)[UIImage imageNamed:@"pt_mimute"].CGImage;
    [self.minuteHand.layer addSublayer:layerMinute];

    CALayer *layerSecond = [[CALayer alloc] init];
    layerSecond.frame = CGRectMake(0, 0, 100, 100);
    layerSecond.contents = (__bridge id)[UIImage imageNamed:@"pt_second"].CGImage;
    [self.secondHand.layer addSublayer:layerSecond];
}

最后就是角度的获取了

- (void)timeFire
{
    NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese];
    NSCalendarUnit unit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *components = [calendar components:unit fromDate:[NSDate new]];
    
    CGFloat hourAngal = ((CGFloat)labs(components.hour-12)/12)*2*M_PI; //先转成12小时制
    CGFloat minuteAngal = ((CGFloat)components.minute/60)*2*M_PI;
    CGFloat secondAngal = ((CGFloat)components.second/60)*2*M_PI;
    
    self.hourHand.transform = CGAffineTransformMakeRotation(hourAngal);
    self.minuteHand.transform = CGAffineTransformMakeRotation(minuteAngal);
    self.secondHand.transform = CGAffineTransformMakeRotation(secondAngal);
}

这里用 components.hour 获取当前小时,是24小时制的,看了下 NSDateComponents 类,没有找到设置时间格式为12小时的属性,暂时只能这么处理下。(若有好的方法请不吝赐教)

最后愉快的调用就好了

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self drawClock];
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeFire) userInfo:nil repeats:YES];
    [self timeFire]; //手动调用一次的主要目的是首次显示当前的时钟,不然会先显示12点,1秒后转到正确时间。
}

为了保证界面的流畅性,需要先手动调用一下 timeFire

看看效果:


clock.gif

效果还行,仔细看时针指的位置是不对的,按理说应该在靠近6点的位置才对,核对下代码后发现

CGFloat hourAngal = ((CGFloat)labs(components.hour-12)/12)*2*M_PI;

时针的角度只是处理了小时,没有把分钟的算进去,同理分钟的指针也没有把秒计算在内。
把分钟加进去

CGFloat hourAngal = ((CGFloat)fabs((components.hour-12)+((CGFloat)components.minute/60))/12)*2*M_PI;

效果就比较理想了


clock_new.gif

感谢爱抽烟的芭比提供的 iPhoneSimulator的录屏代码

xcrun simctl io booted recordVideo filename.mov

以及KFAaron
提供的 .mov.gif 的方法,可惜自己在用 brew 安装 ffmpeg 的时候一直报错,texi2html 下载地址无法访问,开关 vpn 都不好使,只好作罢

==> Installing dependencies for ffmpeg: texi2html, yasm, x264, lame, xvid
==> Installing ffmpeg dependency: texi2html
==> Downloading http://download.savannah.gnu.org/releases/texi2html/texi2html-5.
==> Downloading from http://ftp.yzu.edu.tw/nongnu/texi2html/texi2html-5.0.tar.gz

curl: (7) Failed to connect to ftp.yzu.edu.tw port 80: Operation timed out
Error: Failed to download resource "texi2html"
Download failed: http://ftp.yzu.edu.tw/nongnu/texi2html/texi2html-5.0.tar.gz

最后只好放弃,用了 GIF Brewery 3 墙裂推荐,功能很强大,使用也很方便。

参考自 iOS Core Animation: Advanced Techniques

相关文章

网友评论

      本文标题:iOS不到100行代码实现时钟功能

      本文链接:https://www.haomeiwen.com/subject/aabgyftx.html