使用Mac OS控件,封装加载视图ProgressView



针对系统原生的菊花视图(NSProgressIndicator类实例),封装一个较为完善的加载视图!

为工程创建一个新的视图——GYHLoadProgress类!

使用Mac OS控件,封装加载视图ProgressView_第1张图片
右键选择"New File"
使用Mac OS控件,封装加载视图ProgressView_第2张图片
选择"Cocoa Class"(Mac的App又叫'Cocoa App')

使用Mac OS控件,封装加载视图ProgressView_第3张图片
继承自`NSView`的`GYHLoadProgress`


对应的“.h”文件:

 #import 

 NS_ASSUME_NONNULL_BEGIN

@interface GYHLoadProgress : NSView

@property (nonatomic, strong) NSView * totalProgressV;//整个‘加载中’视图
@property (nonatomic, strong) NSProgressIndicator * progIndicator;//’加载中‘视图(菊花)
@property (nonatomic, strong) NSTextField * showNoticeLabel;

//属性——backGroundColor(背景色)、textFont(字体大小)、    //可根据自己需求来进行添加,比如:textColor(字体色)、等
@property (nonatomic, strong) NSColor * backGroundColor;
@property (nonatomic, assign) CGFloat textFont;

//方法——显示、隐藏
-(void)startTheProgressWithStr:(NSString *)str; //显示——开启 旋转
-(void)stopTheProgressAnimation; //隐藏——停止 旋转

@end

 NS_ASSUME_NONNULL_END

对应的“.m”文件:

#import "GYHLoadProgress.h"
    
@implementation GYHLoadProgress

-(instancetype)initWithFrame:(NSRect)frameRect {
    if (self = [super initWithFrame:frameRect]) {
        CGFloat progressV_W = frameRect.size.width;
        _totalProgressV = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, progressV_W, progressV_W)];//整个‘加载中’视图
        [self addSubview:_totalProgressV];
        //为_totalProgressV添加约束
        _totalProgressV.translatesAutoresizingMaskIntoConstraints = NO;
        NSLayoutConstraint * total_progressV_CenterX = [_totalProgressV.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:0.f];
        NSLayoutConstraint * total_progressV_CenterY = [_totalProgressV.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:0.f];
        NSLayoutConstraint * total_progressV_Width = [_totalProgressV.widthAnchor constraintEqualToConstant:progressV_W];
        NSLayoutConstraint * total_progressV_Height = [_totalProgressV.heightAnchor constraintEqualToConstant:progressV_W];
        [self addConstraints:@[total_progressV_CenterX,total_progressV_CenterY,total_progressV_Width,total_progressV_Height]];
        _totalProgressV.wantsLayer = YES;
        _totalProgressV.layer.backgroundColor = [NSColor whiteColor].CGColor;//背景色:白色
        _totalProgressV.layer.masksToBounds = YES;
        _totalProgressV.layer.cornerRadius = 5.f;//切圆角
        _totalProgressV.hidden = YES;//(默认)隐藏
        
        CGFloat totalProgressV_W = (1.f/2.f)*progressV_W;
        CGFloat progress_Offset_Y = -8.0f;
        _progIndicator = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0, 0, totalProgressV_W, totalProgressV_W)];  //’加载中‘视图(菊花)
        [_totalProgressV addSubview:_progIndicator];
        //为_progIndicator添加约束
        _progIndicator.translatesAutoresizingMaskIntoConstraints = NO;
        NSLayoutConstraint * progressV_CenterX = [_progIndicator.centerXAnchor constraintEqualToAnchor:_totalProgressV.centerXAnchor constant:0.f];
        NSLayoutConstraint * progressV_CenterY = [_progIndicator.centerYAnchor constraintEqualToAnchor:_totalProgressV.centerYAnchor constant:progress_Offset_Y];
        NSLayoutConstraint * progressV_Width = [_progIndicator.widthAnchor constraintEqualToConstant:totalProgressV_W];
        NSLayoutConstraint * progressV_Height = [_progIndicator.heightAnchor constraintEqualToConstant:totalProgressV_W];
        [self addConstraints:@[progressV_CenterX,progressV_CenterY,progressV_Width,progressV_Height]];
        _progIndicator.style = NSProgressIndicatorStyleSpinning; //条形样式,菊花样式
        _progIndicator.controlSize = NSControlSizeRegular; //大小,可选 regular small  mini
        [_progIndicator sizeToFit];    //size适配菊花大小,多余的舍弃
        _progIndicator.minValue = 0;
        _progIndicator.maxValue = 100;   //最大值默认为100, 不是1,和progress不同
        //[_progIndicator setIndeterminate:NO];   // YES:不显示当前进度  NO:精准显示当前进度
                    
        CGFloat showLB_W = progressV_W;     CGFloat showLB_H = (1.f/5.f)*progressV_W;
        CGFloat showLB_X = 0.f;             CGFloat showLB_Y = 0.f;
        _showNoticeLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(showLB_X, showLB_Y, showLB_W, showLB_H)];//文字提示Label
        [_totalProgressV addSubview:_showNoticeLabel];
        _showNoticeLabel.bordered = NO;
        _showNoticeLabel.editable = NO; _showNoticeLabel.enabled = NO;//不可操作,当作Label!
        _showNoticeLabel.alignment = NSTextAlignmentCenter; //字体 居中
        _showNoticeLabel.lineBreakMode = NSLineBreakByCharWrapping;//换行模式:字符边界
        _showNoticeLabel.backgroundColor = [NSColor clearColor];
        _showNoticeLabel.textColor = [NSColor blackColor];      //textColor(字体色)
        self.textFont = 10.0;                                   //textFont(字体大小)
        _showNoticeLabel.font = [NSFont labelFontOfSize:self.textFont];
    }
    return  self;
}
//属性——backGroundColor(背景色)、textFont(字体大小)、
-(void)setBackGroundColor:(NSColor *)backGroundColor {
    _backGroundColor = backGroundColor;
    
    _totalProgressV.layer.backgroundColor = backGroundColor.CGColor;
}
-(void)setTextFont:(CGFloat)textFont {
    _textFont = textFont;

    self.showNoticeLabel.font = [NSFont systemFontOfSize:textFont];
}
//方法——显示、隐藏
-(void)startTheProgressWithStr:(NSString *)str {
    dispatch_async(dispatch_get_main_queue(), ^{
        self.totalProgressV.hidden = NO; //整个‘加载中’视图
        
        [self.progIndicator startAnimation:nil];  //开始动画
        self.showNoticeLabel.stringValue = str;
    });
}
-(void)stopTheProgressAnimation {
    dispatch_async(dispatch_get_main_queue(), ^{
        self.totalProgressV.hidden = YES;
        
        [self.progIndicator stopAnimation:nil];   //结束动画
        self.showNoticeLabel.stringValue = @"";
    });
}



- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Drawing code here.
}

@end


使用:在ViewController中

CGFloat progressV_W = 100.f;
GYHLoadProgress * gyhProgress = [[GYHLoadProgress alloc] initWithFrame:NSMakeRect(0, 0, progressV_W, progressV_W)];//整个‘加载中’视图
[self.view addSubview:gyhProgress];
//添加约束,始终居于viewController对应视图的中央!
gyhProgress.translatesAutoresizingMaskIntoConstraints = NO;//必须书写
NSLayoutConstraint * total_progressV_CenterX = [gyhProgress.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0.f];
NSLayoutConstraint * total_progressV_CenterY = [gyhProgress.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor constant:0.f];
NSLayoutConstraint * total_progressV_Width = [gyhProgress.widthAnchor constraintEqualToConstant:progressV_W];
NSLayoutConstraint * total_progressV_Height = [gyhProgress.heightAnchor constraintEqualToConstant:progressV_W];
[self.view addConstraints:@[total_progressV_CenterX,total_progressV_CenterY,total_progressV_Width,total_progressV_Height]];
//开始动画  显示——开启 旋转
[gyhProgress startTheProgressWithStr:@"加载中..."];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//延时3s
    [gyhProgress setBackGroundColor:[NSColor redColor]];//改为红色
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//延时5s
    //停止动画  隐藏——停止 旋转
    [gyhProgress stopTheProgressAnimation];
});


效果:
a.由于对GYHLoadProgress实例添加了约束,所以会一直居中!
b.延时3.0s时改变颜色为红色,延时5.0s时隐藏!

使用Mac OS控件,封装加载视图ProgressView_第4张图片


 Tips:对于NSTextField字体过长的处理!

修改代码[gyhProgress startTheProgressWithStr:@"加载中..."];[gyhProgress startTheProgressWithStr:@"Loading...加载中。。。"];后,NSTextField会显示不全!

使用Mac OS控件,封装加载视图ProgressView_第5张图片
改为[gyhProgress startTheProgressWithStr:@"Loading...加载中。。。"];后,NSTextField会显示不全!

思路:目前思路有 1.增加行数、2.计算该使用的准确字体大小(font)!

采取的解决方案:2.计算该使用的准确字体大小(font)——Label宽度固定,行数为1
《iOS\Mac OS 根据字体大小、控件宽度,计算字符串展示时尺寸!》中的“- (NSSize)sizeForLblContent:(NSString *)strContent fixMaxWidth:(CGFloat)w andFondSize:(int)fontSize;”方法!


-(void)startTheProgressWithStr:(NSString *)str方法中:使用递归方法“-(void)adjustTheLabelFontWithStr:(NSString *)str”来设置字体大小!

-(void)startTheProgressWithStr:(NSString *)str {
  dispatch_async(dispatch_get_main_queue(), ^{ //主线程
   self.totalProgressV.hidden = NO; //整个‘加载中’视图
   
   [self.progIndicator startAnimation:nil];  //开始动画
   self.showNoticeLabel.stringValue = str;
   
   [self adjustTheLabelFontWithStr:str];
  });
}

递归方法:-(void)adjustTheLabelFontWithStr:(NSString *)str

-(void)adjustTheLabelFontWithStr:(NSString *)str {//使用递归方法,设置好对应字体大小(NSFont)
   CGFloat maxWidth = (self.showNoticeLabel.frame.size.width - 5);
   NSSize size = [self sizeForLblContent:str fixMaxWidth:maxWidth andFondSize:self.textFont];
   NSLog(@"%lf  %lf",size.height,self.showNoticeLabel.frame.size.height);
   if (size.height < self.showNoticeLabel.frame.size.height) {
       //计算得到的高度在控件范围
   } else { //计算得到的高度超过控件范围,重新设置NSTextField的font属性!
       CGFloat newFontNum = self.textFont - 1.0;
       NSLog(@"newFontNum:%lf",newFontNum);
       self.textFont = newFontNum;
       self.showNoticeLabel.font = [NSFont systemFontOfSize:newFontNum];
       [self adjustTheLabelFontWithStr:str];
   }
}

效果:文字展示完整!

使用Mac OS控件,封装加载视图ProgressView_第6张图片

XCode打印:字体变为8号!

使用Mac OS控件,封装加载视图ProgressView_第7张图片
字体变为8号








goyohol's essay

你可能感兴趣的:(使用Mac OS控件,封装加载视图ProgressView)