iOS开发笔记-根据frame大小动态调整fontSize的自适应文本及圆形进度条控件的实现

最近同样是新App,设计稿里出现一种圆形进度条的设计,如下:

 

 

 

 

 

 

 

 

 

想了想,圆形进度条实现起来不难,但是其中显示百分比的文本确需要自适应,虽然可以使用时自己设定文本字体的大小,但是这样显得很麻烦,也很low。

 

查了一圈,目前实现的自适应UILabel,都是根据font大小动态调整frame的size,并不能满足我们的需求。

 

 那么问题来了

 

 如何实现一种能够根据frame大小自适应调整文本font size的圆形进度条呢?

 

我的实现思路很简单,首先计算出能够给予UILabel的frame最大尺寸,然后根据高度优先,宽度次之的原则,计算出最合适的字体大小,这样可以完美的适配各种尺寸。

 

效果如下:

 

 

实现代码:

 

CircleProgressBar继承于UIView,具有四个属性,分别如下:

 

复制代码
//
//  CircleProgressBar.h
//  demo
//
//  Created by ZhangChangwei on 15/4/1.
//  Copyright (c) 2015年 Changwei. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CircleProgressBar : UIView
//进度条百分比值 @property (nonatomic)
float percentValue;
//进度条宽度 @property (nonatomic)
float lineWidth;
//文本颜色 @property (nonatomic ) UIColor
*textColor;
//进度条颜色 @property (nonatomic ) UIColor
*barColor; @end
复制代码

 

实现方式主要采用CoreGraphics绘制图形,其中文字绘制采用自适应计算大小的方式实现,实现了根据控件frame大小动态改变字体的行为,非常灵活。

 

复制代码
//
//  CircleProgressBar.m
//  demo
//
//  Created by ZhangChangwei on 15/4/1.
//  Copyright (c) 2015年 Changwei. All rights reserved.
//

#import "CircleProgressBar.h"

@implementation CircleProgressBar


/**
 *  init and set up property
 *
 *  @param frame <#frame description#>
 *
 *  @return <#return value description#>
 */
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        
    }
    return self;
}

/**
 *  redraw
 *
 *  @param rect frame
 */
 - (void)drawRect:(CGRect)rect {
     if(_lineWidth==0.0f){
         _percentValue=0;
         NSLog(@"%@",@"请输入颜色,数值等参数");
     }
         //开始绘制图形
         CGContextRef ctx=UIGraphicsGetCurrentContext();
         CGContextSetLineWidth(ctx, _lineWidth);
         CGContextBeginPath(ctx);
         CGContextSetStrokeColorWithColor(ctx, _barColor==nil?[UIColor orangeColor].CGColor:_barColor.CGColor);
         CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.width/2, self.frame.size.width/2-_lineWidth, M_PI*1.5, M_PI*(1.5-2*_percentValue), 1);
         CGContextStrokePath(ctx);
         //绘制计算最佳文本大小
         CGSize maxSize=CGSizeMake(rect.size.width*0.75, rect.size.height/3);
         int currentFontSize=17;
         NSString *str=[NSString stringWithFormat:@"%.1f%%",_percentValue*100];
         CGSize requiredSize = [str boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize]} context:nil].size;
         if(requiredSize.height<=maxSize.height)
         {
             while (requiredSize.height<=maxSize.height&&requiredSize.width<maxSize.width) {
                 currentFontSize++;
                 requiredSize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize]} context:nil].size;
             }
         }else
         {
             while (requiredSize.height>maxSize.height||requiredSize.width>maxSize.width) {
                 currentFontSize--;
                 requiredSize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize]} context:nil].size;
             }
             requiredSize=[str boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize]} context:nil].size;
         }
         //绘制自适应文本
         [str drawAtPoint:CGPointMake(rect.size.width/2-requiredSize.width/2, rect.size.height/2-requiredSize.height/2)
           withAttributes:@{
                            NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize],
                            NSForegroundColorAttributeName:_textColor==nil?[UIColor blackColor]:_textColor
                            }];
             
     }


@end
复制代码

 

使用方法:

 

CircleProgressBar使用起来非常简单,只需要提供相应参数即可,如下:

 

复制代码
- (void)viewDidLoad {
    [super viewDidLoad];
    
   
    CircleProgressBar *bar1=[[CircleProgressBar alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2-10, SCREEN_HEIGHT*0.2, 20, 20)];
    bar1.barColor=[UIColor redColor];
    bar1.lineWidth=1.0f;
    bar1.percentValue=0.85;
    bar1.backgroundColor=[UIColor clearColor];
    [self.view addSubview:bar1];
    
    CircleProgressBar *bar2=[[CircleProgressBar alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2-25, SCREEN_HEIGHT*0.3, 50, 50)];
    bar2.barColor=[UIColor orangeColor];
    bar2.lineWidth=3;
    bar2.percentValue=0.45;
    bar2.backgroundColor=[UIColor clearColor];
    [self.view addSubview:bar2];
    CircleProgressBar *bar3=[[CircleProgressBar alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2-50, SCREEN_HEIGHT*0.5, 100, 100)];
    bar3.barColor=[UIColor greenColor];
    bar3.lineWidth=5;
    bar3.textColor=[UIColor blueColor];
    bar3.percentValue=0.75;
    bar3.backgroundColor=[UIColor clearColor];
    [self.view addSubview:bar3];
    CircleProgressBar *bar4=[[CircleProgressBar alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT*0.7, 200, 200)];
    bar4.barColor=[UIColor blueColor];
    bar4.textColor=[UIColor purpleColor];
    bar4.lineWidth=10;
    bar4.percentValue=0.55;
    bar4.backgroundColor=[UIColor clearColor];
    [self.view addSubview:bar4];
}
复制代码

 

完成了圆形进度条的实现后,想了想,其实可以加入动画,使得进度条动态展现,下次有时间再实现😁

posted @   msp的昌伟哥哥  阅读(2392)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示