UILabel+Category.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //
  2. // UILabel+Category.m
  3. // 乐销
  4. //
  5. // Created by 刘惠萍 on 2017/4/29.
  6. // Copyright © 2017年 ping. All rights reserved.
  7. //
  8. #import "UILabel+Category.h"
  9. #import <objc/runtime.h>
  10. #import "NSObject+Catrgory.h"
  11. //YYKit
  12. #import <YYKit/NSAttributedString+YYText.h>
  13. //model
  14. #import "ModelLabel.h"
  15. static const char lineSpaceKey = '\0';
  16. static const char numLimitKey = '\0';
  17. @implementation UILabel (Category)
  18. #pragma mark 运行时 获取line space
  19. - (void)setLineSpace:(CGFloat)lineSpace{
  20. objc_setAssociatedObject(self, &lineSpaceKey, [NSNumber numberWithFloat:lineSpace], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  21. }
  22. - (CGFloat)lineSpace{
  23. NSNumber * lineSpace = objc_getAssociatedObject(self, &lineSpaceKey);
  24. return lineSpace?[lineSpace floatValue]:0;
  25. }
  26. - (void)setNumLimit:(int)numLimit{
  27. objc_setAssociatedObject(self, &numLimitKey, [NSNumber numberWithInt:numLimit], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  28. }
  29. - (int)numLimit{
  30. NSNumber * lineSpace = objc_getAssociatedObject(self, &numLimitKey);
  31. return lineSpace?[lineSpace intValue]:0;
  32. }
  33. //替换方法
  34. + (void)load{
  35. static dispatch_once_t onceDispatch;
  36. dispatch_once(&onceDispatch, ^{
  37. method_exchangeImplementations(class_getInstanceMethod(self,@selector(setText:)), class_getInstanceMethod(self,@selector(lhpSetText:)));
  38. });
  39. }
  40. #pragma mark set
  41. - (void)setFontNum:(CGFloat)fontNum{
  42. self.font = [UIFont systemFontOfSize:fontNum];
  43. }
  44. - (CGFloat)fontNum{
  45. return self.font.pointSize;
  46. }
  47. -(void)lhpSetText:(NSString *)str{
  48. if (str&&[str isKindOfClass:[NSString class]]&& self.numLimit) {
  49. [self lhpSetText:str.length>=self.numLimit?[str substringToIndex:self.numLimit]:str];
  50. }else{
  51. [self lhpSetText:str];
  52. }
  53. }
  54. /**
  55. 固定宽度
  56. @param width 宽度
  57. */
  58. - (void)fitFixed:(CGFloat)width{
  59. [self fitWidth:width isFixed:true];
  60. }
  61. /**
  62. 固定宽度
  63. @param title 内容
  64. @param width 宽度
  65. */
  66. - (void)fitTitle:(NSString *)title fixed:(CGFloat)width{
  67. self.text = title;
  68. [self fitFixed:width];
  69. }
  70. /**
  71. 可变宽度
  72. @param width 宽度
  73. */
  74. - (void)fitVariable:(CGFloat)width{
  75. [self fitWidth:width?:CGFLOAT_MAX isFixed:false];
  76. }
  77. /**
  78. 可变宽度
  79. @param title 内容
  80. @param width 宽度
  81. */
  82. - (void)fitTitle:(NSString *)title variable:(CGFloat)width{
  83. self.text = title;
  84. [self fitVariable:width];
  85. }
  86. /**
  87. 根据行数改变宽高
  88. @param width 宽度
  89. @param isFiexed 宽度是否固定
  90. */
  91. - (void)fitWidth:(CGFloat)width isFixed:(BOOL)isFiexed{
  92. NSString * string = self.text;
  93. if (!isStr(string) || !width) {
  94. self.widthHeight = XY(isFiexed?width:0, self.font.lineHeight);
  95. return;
  96. }
  97. //获取高度 会获取行高
  98. CGSize size = [self fetchRectWithString:string width:width];
  99. CGFloat num_height_return = size.height;
  100. //如果有行高 并且不是一行
  101. if (self.lineSpace && num_height_return > self.font.lineHeight) {
  102. NSMutableAttributedString * attributeString = [[NSMutableAttributedString alloc]initWithString:self.text];
  103. //段落格式
  104. NSMutableParagraphStyle * paragraphStyle = [NSMutableParagraphStyle new];
  105. paragraphStyle.alignment = self.textAlignment;
  106. paragraphStyle.lineSpacing = self.lineSpace;
  107. [attributeString setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:self.font} range:NSMakeRange(0, self.text.length)];
  108. self.attributedText = attributeString;
  109. }
  110. //限制行数 并且超过一行
  111. if (self.numberOfLines != 0 && num_height_return > self.font.lineHeight) {
  112. CGFloat heightLines = self.numberOfLines * self.font.lineHeight + (self.numberOfLines - 1)*self.lineSpace;
  113. num_height_return = num_height_return >heightLines ?heightLines :num_height_return;
  114. }
  115. self.widthHeight = XY(isFiexed?width:size.width, num_height_return);
  116. }
  117. /**
  118. attribute label 固定宽度
  119. @param width 宽度限制
  120. @param models ModelLabel
  121. */
  122. -(void)resetAttributeStrFixed:(CGFloat)width models:(NSArray *)models{
  123. [self resetAttributeStrWidth:width isFiexed:true models:models lineSpace:0];
  124. }
  125. /**
  126. attribute label 固定宽度
  127. @param width 宽度限制
  128. @param models ModelLabel
  129. */
  130. -(void)resetAttributeStrFixed:(CGFloat)width models:(NSArray *)models lineSpace:(CGFloat)lineSpace{
  131. [self resetAttributeStrWidth:width isFiexed:true models:models lineSpace:lineSpace];
  132. }
  133. /**
  134. attribute label 可变宽度
  135. @param width 宽度限制
  136. @param models ModelLabel
  137. */
  138. -(void)resetAttributeStrVariable:(CGFloat)width models:(NSArray *)models{
  139. [self resetAttributeStrWidth:width isFiexed:false models:models lineSpace:self.lineSpace];
  140. }
  141. /**
  142. attribute label 可变宽度
  143. @param width 宽度限制
  144. @param models ModelLabel
  145. */
  146. -(void)resetAttributeStrVariable:(CGFloat)width models:(NSArray *)models lineSpace:(CGFloat)lineSpace{
  147. [self resetAttributeStrWidth:width isFiexed:false models:models lineSpace:lineSpace];
  148. }
  149. /**
  150. 富文本文字显示
  151. @param width 宽度限制
  152. @param models ModelLabel
  153. @param lineSpace 行高
  154. */
  155. -(void)resetAttributeStrWidth:(CGFloat)width isFiexed:(BOOL)isFiex models:(NSArray *)models lineSpace:(CGFloat)lineSpace{
  156. NSString *labelText=@"";
  157. NSMutableArray *mutArr = [NSMutableArray arrayWithArray:models];
  158. for (int i=0; i<models.tmpAry.count; i++) {
  159. ModelLabel *model = models[i];
  160. model.range = NSMakeRange(labelText.length, model.text.length);
  161. [mutArr addObject:model];
  162. labelText = [labelText stringByAppendingString:UnPackStr(model.text)];
  163. }
  164. self.text = labelText;
  165. NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:self.text];
  166. NSMutableDictionary *attributes=[NSMutableDictionary dictionary];
  167. [mutArr enumerateObjectsUsingBlock:^(ModelLabel *model, NSUInteger idx, BOOL * _Nonnull stop) {
  168. NSRange sizeRange = model.range;
  169. if (sizeRange.length>0) {
  170. if (model.textColor) {
  171. [attributes setValue:model.textColor forKey:NSForegroundColorAttributeName];
  172. }
  173. if (model.fontAttribute) {
  174. [attributes setValue:[UIFont fontWithName:model.fontAttribute size:(CGFloat)(model.font>0? model.font:self.font.pointSize)] forKey:NSFontAttributeName];
  175. }else{
  176. [attributes setValue:[UIFont systemFontOfSize:(CGFloat)(model.font>0? model.font:self.font.pointSize)] forKey:NSFontAttributeName];
  177. }
  178. [str setAttributes:attributes range:sizeRange];
  179. }
  180. }];
  181. if (lineSpace) {
  182. str.lineSpacing = lineSpace;
  183. }
  184. self.attributedText = str;
  185. CGRect rect =[str boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil];
  186. CGFloat num_height_return = CGRectGetHeight(rect);
  187. //限制行数
  188. if (self.numberOfLines != 0) {
  189. CGFloat lineHeight = [self fetchRectWithString:@"A" width:CGFLOAT_MAX].height;
  190. num_height_return = num_height_return > (self.numberOfLines*lineHeight + (self.numberOfLines-1)*lineSpace)?self.numberOfLines*lineHeight:num_height_return;
  191. }
  192. self.widthHeight = XY(isFiex?width:CGRectGetWidth(rect), num_height_return);
  193. }
  194. //计算高度的方法
  195. - (CGSize)fetchRectWithString:(NSString *)string width:(CGFloat)width{
  196. //如果string 无效 返回
  197. if (!isStr(string)) {
  198. return CGSizeMake(0, 0);
  199. }
  200. CGRect frame = [string boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:self.lineSpace?@{NSParagraphStyleAttributeName:[NSMutableParagraphStyle initWithLineSpace:self.lineSpace],NSFontAttributeName:self.font}:@{NSFontAttributeName:self.font} context:nil];
  201. //如果只有一行
  202. if (self.lineSpace && CGRectGetHeight(frame) == self.font.lineHeight + self.lineSpace) {
  203. return CGSizeMake(CGRectGetWidth(frame), self.font.lineHeight);
  204. }
  205. return CGSizeMake(CGRectGetWidth(frame), CGRectGetHeight(frame));
  206. }
  207. - (CGRect)boundingRectForCharacterRange:(NSRange)range
  208. {
  209. NSMutableAttributedString * attributedText;
  210. if (self.lineSpace) {
  211. attributedText = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];
  212. }else{
  213. attributedText = [[NSMutableAttributedString alloc]initWithString:self.text];
  214. //段落格式
  215. NSMutableParagraphStyle * paragraphStyle = [NSMutableParagraphStyle new];
  216. paragraphStyle.alignment = self.textAlignment;
  217. [attributedText setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:self.font} range:NSMakeRange(0, self.text.length)];
  218. self.attributedText = attributedText;
  219. }
  220. NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedText];
  221. NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
  222. [textStorage addLayoutManager:layoutManager];
  223. NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
  224. textContainer.lineFragmentPadding = 0;
  225. textContainer.lineBreakMode = self.lineBreakMode;
  226. [layoutManager addTextContainer:textContainer];
  227. NSRange glyphRange = NSMakeRange(0, 0);
  228. // NSRange characterRange = NSMakeRange(0, 0);
  229. // Convert the range for glyphs.
  230. // [layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];
  231. CGRect rectReturn = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
  232. return rectReturn;
  233. }
  234. //limit width then subtract text; line break mode must be NSLineBreakByCharWrapping
  235. - (void)configStringWithLimitWidth{
  236. self.lineBreakMode = NSLineBreakByCharWrapping;
  237. NSMutableAttributedString * attributedText;
  238. if (self.lineSpace) {
  239. attributedText = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];
  240. }else{
  241. attributedText = [[NSMutableAttributedString alloc]initWithString:self.text];
  242. //段落格式
  243. NSMutableParagraphStyle * paragraphStyle = [NSMutableParagraphStyle new];
  244. paragraphStyle.alignment = self.textAlignment;
  245. paragraphStyle.lineBreakMode = self.lineBreakMode;
  246. [attributedText setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:self.font} range:NSMakeRange(0, self.text.length)];
  247. self.attributedText = attributedText;
  248. }
  249. NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedText];
  250. NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
  251. [textStorage addLayoutManager:layoutManager];
  252. NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
  253. textContainer.lineFragmentPadding = 0;
  254. textContainer.lineBreakMode = self.lineBreakMode;
  255. [layoutManager addTextContainer:textContainer];
  256. NSRange rangeText = [layoutManager glyphRangeForBoundingRect:self.bounds inTextContainer:textContainer];
  257. self.text = [self.text substringWithRange:rangeText];
  258. }
  259. //fetch height
  260. + (CGFloat)fetchHeightFontNum:(CGFloat)numFont string:(NSString *)title lineSpace:(CGFloat)lineSpace widthLimit:(CGFloat)widthLimit heightLimit:(CGFloat)heightLimit{
  261. static UILabel * label = nil;
  262. if (!label) {
  263. label = [UILabel new];
  264. }
  265. label.fontNum = numFont;
  266. label.lineSpace = lineSpace;
  267. CGSize size = [label fetchRectWithString:title width:widthLimit];
  268. return heightLimit?MIN(heightLimit, size.height):size.height;
  269. }
  270. //fetch widht
  271. + (CGFloat)fetchWidthFontNum:(CGFloat)num text:(NSString *)str{
  272. if (!isStr(str)) {
  273. return 0;
  274. }
  275. static UILabel * label = nil;
  276. if (!label) {
  277. label = [UILabel new];
  278. }
  279. label.fontNum = num;
  280. [label fitTitle:str variable:0];
  281. return label.width;
  282. }
  283. //设置label默认阴影
  284. -(void)setNormalShadow{
  285. [self setShadowColor:[UIColor blackColor] range:NSMakeRange(0, self.text.length) offsetsize:CGSizeMake(0, 1)];
  286. }
  287. //设置label阴影
  288. -(void)setShadowColor:(UIColor *)shadowColor range:(NSRange)range offsetsize:(CGSize)size{
  289. NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:self.text];
  290. NSShadow *shadow = [[NSShadow alloc]init];
  291. shadow.shadowBlurRadius = 1.0;
  292. shadow.shadowOffset = size;
  293. shadow.shadowColor = shadowColor;
  294. [str addAttribute:NSShadowAttributeName
  295. value:shadow
  296. range:range];
  297. self.attributedText = str;
  298. //label自身阴影属性不可设置range
  299. // self.shadowColor = shadowColor;
  300. // //阴影偏移 x,y为正表示向右下偏移
  301. // self.shadowOffset = size;
  302. }
  303. #pragma mark logical
  304. //价格与累积采购之间添加I
  305. -(void)setPriceLabelSpaceMark:(NSString*)attributeStr{
  306. NSRange range = [attributeStr rangeOfString:@"I"];
  307. NSValue * value = [NSValue valueWithRange:range];
  308. NSMutableArray * array = [[NSMutableArray alloc]initWithObjects:value, nil];
  309. [self setAttributedText:[ReturnAttributeStr returnDifferentTextColorWithText:attributeStr lineSpacing:0 alignment:0 rangArray:array color:[UIColor colorWithHexString:@"#E5E5E5"]]];
  310. }
  311. @end