零基础iOS开发学习日记—控件篇—UIImageView与UILabel

1,070 阅读5分钟

开头

UIImageView

实际用处

  • 显示不需要任何功能的图片
  • 图片来源为网络获取、或者沙盒目录

基础用法

//设置内容
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dv_model1"]];
//设置大小
imageView.frame = CGRectMake(100, 100, 100, 100);
//添加到住视图
[self.view addSubview:imageView];

contentMode

  • 在实际开发中,图片大小不能很好得进行预估,而默认情况下,UIImageView的内容显示模式会导致,图片效果为拉伸填充,就需要设置属性contentMode
  • 常用的三个设置
  • 假定图片远大于设置的UIImageView的大小
UIViewContentModeScaleToFill //默认,拉伸填充
UIViewContentModeScaleAspectFit //按图片比例,适应UIImageView的大小,图片的宽 = UIImageView的宽,高度自适应
UIViewContentModeScaleAspectFill  //按图片比例,填充UIImageView,图片的高 =  UIImageView的高,宽度自适应
  • 这就会导致两个问题
  1. 当使用UIViewContentModeScaleAspectFit,会导致UIImageView的实际高度,大于图片高度
  2. 当使用UIViewContentModeScaleAspectFill,会导致图片宽度大于UIImageView的宽度
  • 第一个问题,在实际应用中,需要先获取图片大小,对UIImageView进行比例缩放,前提是要提前设置好UIImageView的宽度
CGFloat imageViewHeight = self.image.size.height / self.image.size.width * (self.bounds.size.width - 40);
  • 第二个问题,在实际应用中,常见于头像设置,让头像完全显示,在配合imageView.clipsToBounds = YES;,对多出来的部分进行裁剪
  • contentMode的其他属性,实现效果是显示图片的原来比例,但是用对应的位置对UIImageView进行填充

sizeToFit

  • UIImageView对象调用sizeToFit,会改变UIImageView的大小变成实际上图片的大小,并且contentMode的设置无法影响到UIImageView的大小,所以sizeToFit的调整并不适合实际图片的大小比需要图片的大小要大多的修改,而适用于适应纯文字的控件自适应,下面的控件都是一样的道理

UILabel

实际用处

  • 固定的文本控件
  • 显示标题、解释等

基础用法

UILabel *label = [UILabel new];
label.backgroundColor = [UIColor redColor];
//内容
label.text = str;
//字体
label.font = [UIFont systemFontOfSize:20];
//文本框大小
label.frame = CGRectMake(0, 0, 300, 300);
//自动换行
label.numberOfLines = 0;
//对其方式 默认 NSTextAlignmentLeft
label.textAlignment = NSTextAlignmentNatural;
[self.view addSubview:label];

UILabel自适应

  • 在实际开发中,会需要两种适应方式
  1. 文字大小适应文本框大小
  2. 文本框大小适应文字大小
  • 文字大小适应文本框大小,解决起来比较简单,设置下面这个属性即可
label.adjustsFontSizeToFitWidth = YES;

sizeToFit

  • 在测试过程中,发现自己是找了一个麻烦的方法,UILabel适应文本内容,完全可以通过sizeToFit去实现,只需要固定宽度即可,但是下面的方法更加精确
  • 以下是比较找事做的方法
  • 文本框大小适应文字大小,思路与处理UIImageView自适应一致,获取文字内容和文字样式,调用NSString的类函数即可
// size 预设的大小,使用过程中设置了固定宽度,否则没有效果
// options 文本大小的计算方式,如果没有设置字间距,设置为 NSStringDrawingUsesLineFragmentOrigin
// attributes 文字的样式字典,另外说明
// context 文本的其他信息,如缩放、间距等,在此功能下设置为nil即可
// 返回值 rect 取出size即可使用
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attributes context:(nullable NSStringDrawingContext *)context
  • 具体使用,扩展为NSString的类方法
/// label大小适应文字大小
/// @param labelFont label‘s font
/// @param width 固定宽度,保证换行
- (CGSize)labelSizeWithFont:(UIFont *)labelFont andWidth:(CGFloat)width {
    return [self boundingRectWithSize:CGSizeMake(width, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : labelFont} context:nil].size;
}

富文本的概念

  • 富文本实质上就是自定义字符串,通过设置attributes属性字典,进行自定义字符串
  • NSAttributedStringKey相当之多,下面举例的设置方法,思路是找到要设置的样式,找到对应key,然后根据key的类型进行设置即可
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
style.lineSpacing = 1; //行间距
style.paragraphSpacing = 30; //段间距
style.firstLineHeadIndent = 30; //首行缩近
NSDictionary *attrDic = @{
    NSFontAttributeName : [UIFont systemFontOfSize:10], //字体和大小
    NSParagraphStyleAttributeName : style, //文本格式
    NSKernAttributeName : @0, //字间距
    NSObliquenessAttributeName : @0, //倾斜
    NSExpansionAttributeName : @1, //加粗
    NSForegroundColorAttributeName : [UIColor blueColor], //文字颜色
    NSBackgroundColorAttributeName : [UIColor whiteColor] //背景颜色
};
NSAttributedString *attr = [[NSAttributedString alloc] initWithString:str attributes:attrDic];
label.attributedText = attr;

富文本编辑与图文混排

  • 在实际开发中,会出现图文混排的需求,即需要用到NSMutableAttributedStringNSAttributedString,根据需求分析,主要处理以下几个事情
  1. 设置图片附件
  2. 找到字符串中需要替换的位置
  3. 替换字符串中需要替换的内容
  • 针对第一步,用到了NSTextAttachment这个类,将图片转换为NSAttributedString,再添加到可变的NSMutableAttributedString,字符串中,下面为封装NSMutableAttributedString扩展的类函数,根据实际font的大小,返回对应的图片文本
+ (NSAttributedString *)imageToAttributedStringWithImage:(UIImage *)image andFont:(UIFont *)font {
    CGFloat lineHeight = font.lineHeight;
    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    attachment.image = image;
    CGFloat width = image.size.width / image.size.height * lineHeight;
    attachment.bounds = CGRectMake(0, -2, width, lineHeight);
    return [NSAttributedString attributedStringWithAttachment:attachment];
}
  • 针对第二步,利用NSString的对象函数,根据设置好的字符串找到对应的位置
- (NSRange)rangeOfString:(NSString *)searchString;
  • 针对第三步,则利用NSMutableAttributedString的对象函数进行替换
- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attrString;
  • 值得注意的是,在实际开发中,会需要替换某个字符串的多个位置的字符,就需要提前约定好对应的协议,用符号标记出字符,且在替换过程中,要倒序替换,否则会导致替换位置出错,因为查找位置的字符串,在每一次替换后都会改变。下面是封装好的NSMutableAttributedString的类函数,将图片数组和需要替换的字符串数组,传递进来,再倒序替换,图片处理则用到了上面的函数
+ (NSMutableAttributedString *)attributedStringWithString:(NSString *)string andFont:(UIFont *)font andImages:(NSArray *)imageArray andLabels:(NSArray *)labelArray {
    NSMutableAttributedString *strM = [[NSMutableAttributedString alloc] initWithString:string];
    int count = (int)imageArray.count;
    for (int i = count - 1; i > -1; i--) {
        [strM replaceCharactersInRange:[string rangeOfString:labelArray[i]] withAttributedString:[self imageToAttributedStringWithImage:imageArray[i] andFont:font]];
    }
    return strM;
}