测试文本数据
//html标签图片自适应
NSString *detailTextString = [STNewsDetailManager htmlImageHeighAutoStr:string width:self.textView.width];
+(NSString*)htmlImageHeighAutoStr:(NSString*)htmlStr width:(CGFloat)width
{
NSString*detailTextString =@"";
// 根据图片大小自适应,图片宽度小于width,图片不变,宽度大于width,自适应到屏幕宽度
if(![WDUtilisNullOrEmpty:htmlStr]) {
detailTextString = [NSString stringWithFormat:@"img{max-width:%f !important;height:auto}%@",width,htmlStr];
}
returndetailTextString;
}
//转换成AttributedString提取图片URL
NSMutableAttributedString *firstPart = [[NSMutableAttributedString alloc] initWithString:detailText];
[self getImageurlFromHtml:firstPart];
//手动提取文本中的图片URL
- (NSArray*) getImageurlFromHtml:(NSMutableAttributedString*) webString
{
if(webString.length==0) {
returnnil;
}
NSString*webStr = [NSString stringWithFormat:@"%@",webString];
self.imageurlArray = [NSMutableArray arrayWithCapacity:1];
//标签匹配
NSString*parten =@"<img(.*?)>";
NSError* error =NULL;
NSRegularExpression *reg = [NSRegularExpression regularExpressionWithPattern:parten options:0 error:&error];
NSArray* match = [reg matchesInString:webStr options:0 range:NSMakeRange(0, [webString length] - 1)];
for(NSTextCheckingResult* resultinmatch) {
//过去数组中的标签
NSRangerange = [resultrange];
NSString* subString = [webStrsubstringWithRange:range];
//从图片中的标签中提取ImageURL
NSRegularExpression *subReg = [NSRegularExpression regularExpressionWithPattern:@"http://(.*?)\"" options:0 error:NULL];
NSArray* match = [subRegmatchesInString:subStringoptions:0range:NSMakeRange(0, [subStringlength] -1)];
if(match.count>0) {
NSTextCheckingResult* subRes = match[0];
NSRangesubRange = [subResrange];
subRange.length= subRange.length-1;
NSString* imagekUrl = [subStringsubstringWithRange:subRange];
}
else{
NSRegularExpression *subReg = [NSRegularExpression regularExpressionWithPattern:@"https://(.*?)\"" options:0 error:NULL];
NSArray* match = [subRegmatchesInString:subStringoptions:0range:NSMakeRange(0, [subStringlength] -1)];
if(match.count>0) {
NSTextCheckingResult* subRes = match[0];
NSRangesubRange = [subResrange];
subRange.length= subRange.length-1;
NSString* imagekUrl = [subStringsubstringWithRange:subRange];
}
}
}
return self.imageurlArray;
}
//给textView赋值
self.textView.asyncAttributStr = detailTextString;
//加载完成后的回调
__weak typeof (self) weakSelf = self;
self.textView.attributeBlock = ^{
//找到每个图片所在的位置
[weakSelf.textView.attributedText enumerateAttributesInRange:NSMakeRange(0,weakSelf.textView.attributedText.length) options:NSAttributedStringEnumerationReverse usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
if(attrs[@"NSAttachment"]) {
NSTextAttachment*attachment = attrs[@"NSAttachment"];
if([attachment.fileTypecontainsString:@"png"] ||
[attachment.fileTypecontainsString:@"jpg"] ||
[attachment.fileTypecontainsString:@"jpeg"]||
[attachment.fileTypecontainsString:@"bmp"]||
[attachment.fileTypecontainsString:@"gif"]) {
NSString*str = [NSStringstringWithFormat:@"%ld",(unsignedlong)range.location]
[weakSelf.rangeArrinsertObject:stratIndex:0];
}
}
}];
};
//点击图片出发的代理方法(ios11.1系统的手机触发需要点击事件稍长,此问题,没有找到解决办法,感觉是苹果系统系统问题)
- (BOOL)textView:(UITextView*)textView shouldInteractWithTextAttachment:(NSTextAttachment*)textAttachment inRange:(NSRange)characterRange{
NSLog(@"点击的第%lu个",(unsignedlong)characterRange.location);
NSLog(@"图片共%lu个",(unsignedlong)self.imageurlArray.count);
NSString*location = [NSStringstringWithFormat:@"%ld",(unsignedlong)characterRange.location];
if(self.rangeArr.count>0) {
for(NSIntegeri =0; i
NSString*str = [self.rangeArrobjectAtIndex:i];
if([strisEqualToString:location] &&self.imageurlArray.count>=i+1) {
if(self.imageBlock) {
//根据自己的情况,跳转到图片浏览页面
self.imageBlock(self,i,self.imageurlArray);
}
break;
}
}
}
return YES;
}
textView的初始化
- (STCustomTextView*)textView{
if(!_textView) {
STCustomTextView *textView = [[STCustomTextView alloc] init];
textView.myFont = [UIFont extFontOfSize:self.currentFontSize];
textView.isAdjustHeightByWidth = YES;
textView.lineRowSpacing=7;//行间距
textView.lineAfterParagraphSpacing = 15;//段后间距
textView.delegate=self;
textView.backgroundColor = [ThemeManager _setupDayColor:nil nightColor:ST_Night_BackGroundColor];
textView.myColor = [ThemeManager _setupDayColor:[WDUtil colorWithHexString:@"#181818"] nightColor:ST_Night_BigTitleColor];
textView.editable=NO; //必须禁止输入,否则点击将弹出输入键盘
textView.scrollEnabled=NO;
_textView= textView;
}
return _textView;
}
自定义STCustomTextView
原本使用的是label,由于要加上点击图片浏览功能,所以换成了TextView,里面有些不用的代码就给注释了
.m文件
#import "STCustomTextView.h"
@implementationSTCustomTextView
-(instancetype)initWithFrame:(CGRect)frame
{
self= [superinitWithFrame:frame];
if(self) {
// _myLineBreakMode = NSLineBreakByWordWrapping;
// _myAlignment = kMyTextAlignmentLeft;
_isAdjustHeightByWidth = NO;
_isAdjustWidthByHeight = NO;
_isDestroyAttributeBlockAfterUse = NO;
_lineRowSpacing = -1; //行间距
_lineAfterParagraphSpacing = -1; //段前间距
_lineBeforeParagraphSpacing = -1; //段后间距
}
return self;
}
#pragma mark - Set methods
#pragma mark 同步加载富文本 attributStr
-(void)setAttributStr:(NSString*)attributStr
{
// detailsModel.mainBody = @"测试";
_attributStr= attributStr;
self.attributedText= [selfaddMessageAttribute:attributStr];
[self reloadAttributeData];
}
#pragma mark 异步加载富文本 asyncAttributStr
-(void)setAsyncAttributStr:(NSString*)asyncAttributStr
{
_asyncAttributStr= asyncAttributStr;
self.text=@"";//先清除文字再加载
__weaktypeof(self) weakSelf =self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSMutableAttributedString*firstPart = [selfaddMessageAttribute:asyncAttributStr];
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.attributedText= firstPart;
[weakSelfreloadAttributeData];
[weakSelfinvocationAttributeBlock];
});
});
}
//编辑NSMutableAttributedString
-(NSMutableAttributedString*)addMessageAttribute:(NSString*)message
{
// message = [message stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%f.00pt",self.font.pointSize] withString:@"12.00pt"];
//设置文字大小
message = [NSString stringWithFormat:@"%@%@",self.font.pointSize,message,@""];
NSMutableAttributedString *firstPart = [[NSMutableAttributedString alloc] initWithString:@""];
@try{
//空字符串直接返回nil
if([selfisMessageNullOrEmpty:message]) {
returnfirstPart;
}
firstPart = [[NSMutableAttributedString alloc]
initWithData:[message dataUsingEncoding:NSUnicodeStringEncoding]
options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
documentAttributes:nil
error:nil];
// //文字大小
// [firstPart addAttribute:NSFontAttributeName
// value:self.font
// range:NSMakeRange(0, firstPart.length)];
[firstPartaddAttribute:NSKernAttributeName
value:@1.0f
range:NSMakeRange(0, firstPart.length)];
//没有color,设置默认颜色
// if (self.myColor && [self isNotHaveColorInString:message])
if ([ThemeManager sharedThemeManager].isNight) {
if(self.myColor){
[firstPartaddAttribute:NSForegroundColorAttributeName
value:self.myColor
range:NSMakeRange(0, firstPart.length)];
}
}else{
if(self.myColor&& [selfisNotHaveColorInString:message]){
[firstPartaddAttribute:NSForegroundColorAttributeName
value:self.myColor
range:NSMakeRange(0, firstPart.length)];
}
}
if(self.lineRowSpacing>=0
||self.lineAfterParagraphSpacing >= 0
||self.lineBeforeParagraphSpacing >= 0)
{
NSMutableParagraphStyle * paragraph = [[NSMutableParagraphStyle alloc] init];
if(self.lineRowSpacing>=0 ) {
paragraph.lineSpacing=self.lineRowSpacing;
}
if (self.lineAfterParagraphSpacing >= 0) {
paragraph.paragraphSpacing=self.lineAfterParagraphSpacing;
}
if (self.lineBeforeParagraphSpacing >= 0) {
paragraph.paragraphSpacingBefore=self.lineBeforeParagraphSpacing;
}
[firstPartaddAttribute:NSParagraphStyleAttributeName
value:paragraph
range:NSMakeRange(0, firstPart.length)];
}
returnfirstPart;
}
@catch(NSException *exception) {
returnfirstPart;
}
}
//更新界面
-(void)reloadAttributeData
{
// [self customAttributeAlignment:self.myAlignment];
// self.lineBreakMode = self.myLineBreakMode;
//重新布局
[self layoutAdaptiveLable];
}
#pragma mark 更新自适应大小
- (void)layoutAdaptiveLable
{
if (self.isAdjustWidthByHeight == NO && self.isAdjustHeightByWidth == NO) {
return;
}
// self.numberOfLines = 0;
CGRectnewFrame =self.frame;
if (self.isAdjustHeightByWidth == YES) { //高度自适应
CGFloat height = [self sizeThatFits:CGSizeMake(self.frame.size.width, MAXFLOAT)].height;
newFrame.size.height= height;
}else if (self.isAdjustWidthByHeight == YES){ //换掉自适应
CGFloat width = [self sizeThatFits:CGSizeMake(MAXFLOAT,self.frame.size.width)].width;
newFrame.size.width= width;
}
self.frame= newFrame;
}
-(void)invocationAttributeBlock
{
if (self.attributeBlock) {
self.attributeBlock();
if (self.isDestroyAttributeBlockAfterUse) {
self.attributeBlock=nil;
}
}
}
//string中是否有color标签,myColor为nil,不设置默认颜色
//NO:表示有Color,不设置默认颜色; YES,表示没有color,可以设置默认颜色
-(BOOL)isNotHaveColorInString:(NSString*)string
{
if (self.myColor) { //myColor为nil,不设置默认颜色
NSRangerange = [stringrangeOfString:@"color"];
if(range.location==NSNotFound) {
returnYES;
}
}
return NO;
}
#pragma mark myAttributedText
//重置富文本
-(void)setMyAttributedText:(NSAttributedString*)myAttributedText
{
_myAttributedText= myAttributedText;
self.attributedText= myAttributedText;
[self reloadAttributeData];
}
#pragma mark 居中方式
//-(void)setMyAlignment:(MyCustomStrAlignment)myAlignment
//{
// _myAlignment = myAlignment;
// [self customAttributeAlignment:myAlignment];
//}
#pragma mark 字体大小
-(void)setMyFont:(UIFont*)myFont
{
_myFont= myFont;
if(myFont) {
self.font= myFont;
}
//字体大小改变,界面布局也要变化
[self layoutAdaptiveLable];
}
#pragma mark 颜色
-(void)setMyColor:(UIColor*)myColor
{
_myColor= myColor;
self.textColor= myColor;
}
#pragma mark 文字格式
//-(void)setMyLineBreakMode:(NSLineBreakMode)myLineBreakMode
//{
// _myLineBreakMode = myLineBreakMode;
// self.lineBreakMode = myLineBreakMode;
//}
#pragma mark *行间距 段前间距 段后间距
/*行间距**/
-(void)setLineRowSpacing:(CGFloat)lineRowSpacing
{
_lineRowSpacing= lineRowSpacing;
}
/**段前间距**/
-(void)setLineBeforeParagraphSpacing:(CGFloat)lineBeforeParagraphSpacing
{
_lineBeforeParagraphSpacing= lineBeforeParagraphSpacing;
}
/**段后间距**/
-(void)setLineAfterParagraphSpacing:(CGFloat)lineAfterParagraphSpacing
{
_lineAfterParagraphSpacing= lineAfterParagraphSpacing;
}
#pragma mark 是否允许适配高度/宽度
/**固定宽度适配高度 默认 NO**/
-(void)setIsAdjustHeightByWidth:(BOOL)isAdaptiveHeightByWidth
{
_isAdjustHeightByWidth= isAdaptiveHeightByWidth;
if(isAdaptiveHeightByWidth) {
_isAdjustWidthByHeight = NO;
}
}
/**固定高度适配宽度 默认 NO**/
-(void)setIsAdjustWidthByHeight:(BOOL)isAdaptiveWidthByHeight
{
_isAdjustWidthByHeight= isAdaptiveWidthByHeight;
if(isAdaptiveWidthByHeight) {
_isAdjustHeightByWidth = NO;
}
}
#pragma mark - Public methods
//居中方式
//-(void)customAttributeAlignment:(MyCustomStrAlignment )myAlignment
//{
// switch (myAlignment) {
// case kMyTextAlignmentCenter:{
// self.textAlignment = NSTextAlignmentCenter;
// }
// break;
// case kMyTextAlignmentLeft:{
// self.textAlignment = NSTextAlignmentLeft;
// }
// break;
// case kMyTextAlignmentJustified:{
// self.textAlignment = NSTextAlignmentJustified;
// }
// break;
// case kMyTextAlignmentNatural:{
// self.textAlignment = NSTextAlignmentNatural;
// }
// break;
// case kMyTextAlignmentRight:
// {
// self.textAlignment = NSTextAlignmentRight;
// }
// break;
// default:
// break;
// }
//
//}
#pragma mark - Private methods
//将自定义MyCustomStrAlignment 换成 NSTextAlignment
//+(NSTextAlignment)changeCustomAlignment:(MyCustomStrAlignment)myAlignment
//{
// NSTextAlignment align ;
// switch (myAlignment) {
// case kMyTextAlignmentCenter:{
// align = NSTextAlignmentCenter;
// }
// break;
// case kMyTextAlignmentLeft:{
// align = NSTextAlignmentLeft;
// }
// break;
// case kMyTextAlignmentJustified:{
// align= NSTextAlignmentJustified;
// }
// break;
// case kMyTextAlignmentNatural:{
// align = NSTextAlignmentNatural;
// }
// break;
// case kMyTextAlignmentRight:
// {
// align = NSTextAlignmentRight;
// }
// break;
// default:{
// align = NSTextAlignmentLeft;
// }
// break;
// }
// return align;
//}
//
////将NSTextAlignment 换成 自定义MyCustomStrAlignment
//+(MyCustomStrAlignment)changeTextAlignment:(NSTextAlignment)myAlignment
//{
// MyCustomStrAlignment align ;
// switch (myAlignment) {
// case NSTextAlignmentCenter :{
// align = kMyTextAlignmentCenter;
// }
// break;
// case NSTextAlignmentLeft :{
// align = kMyTextAlignmentLeft;
// }
// break;
// case NSTextAlignmentJustified :{
// align= kMyTextAlignmentJustified;
// }
// break;
// case NSTextAlignmentNatural :{
// align = kMyTextAlignmentNatural;
// }
// break;
// case NSTextAlignmentRight :
// {
// align = kMyTextAlignmentRight;
// }
// break;
// default:{
// align = kMyTextAlignmentLeft;
// }
// break;
// }
// return align;
//}
#pragma mark 将异常字符串处理成“”
//处理成空字符串
- (NSString*)dealEmptyMessageString:(NSString*)str
{
str = [NSString stringWithFormat:@"%@",str];
if ([self isMessageNullOrEmpty:str]) {
return@"";
}else{
returnstr;
}
}
//字符串是否为空
- (BOOL)isMessageNullOrEmpty:(NSString*)string
{
if ([string isKindOfClass:[NSNull class]]) {
returnYES;
}
string = [NSStringstringWithFormat:@"%@",string];
returnstring ==nil|| string==(id)[NSNullnull] || [stringisEqualToString:@""] || string.length==0|| [stringisEqualToString:@"(null)"] || [stringisEqualToString:@"null"] || [stringisEqualToString:@"<null>"]|| [stringisEqualToString:@"0(NSNull)"];
}
@end
.h文件
#import <UIKit/UIKit.h>
//typedef enum {
// kMyTextAlignmentLeft = 0,
// kMyTextAlignmentCenter = 1,
// kMyTextAlignmentRight = 2,
// kMyTextAlignmentJustified = 3,
// kMyTextAlignmentNatural = 4
//}MyCustomStrAlignment;
typedefvoid(^KZTCustomAttributeLabelBlock)(void);
@interfaceSTCustomTextView :UITextView
/**(不建议使用) 同步加载带文本标签字符串 比较卡,解决富文本无法准确计算富文本视图高度问题
*attributStr :标签文本,可设置文本居中方式,自适应文本视图大小
* 缺点:*同步加载,比较卡,
* 服务端配字体大小标签不可使用,字体大小只能客户端写,不然显示有问题
* 建议:不建议再使用这个属性, 建议使用asyncAttributStr属性,异步)
**/
@property (nonatomic,copy)NSString * attributStr;
/**(建议使用)异步处理带文本标签* 解决富文本无法准确计算富文本视图高度问题
**优点: 异步加载标签文字,界面比较流畅
** 缺点:同一个视图多次赋值, 会出现文字重叠字体(颜色加重)的情况,(比如cell重用)
**服务端配字体大小标签不可使用,字体大小只能客户端写,不然显示有问题
** 赋值后,由于是异步不能直接使用该视图的frame布局,可在attributeBlock属性的block回调中处理
**建议:仅赋值一次或不会快速刷新多次的地方使用该属性,),强烈建议使用异步,
*/
@property(nonatomic,copy)NSString* asyncAttributStr;
/**
字体大小,
*/
@property (nonatomic, strong) UIFont *myFont;//
/**
对齐方式默认居左 kMyTextAlignmentLeft
*/
//@property (nonatomic, assign) MyCustomStrAlignment myAlignment;//
/**
设置字体颜色,如html标签中没有
返回的不是html语言的普通字符串设置颜色用的,设置过后原来的颜色就没有用了
*/
@property (nonatomic, strong) UIColor *myColor;
// default is NSLineBreakByTruncatingTail. used for single and multiple lines of text
@property(nonatomic) NSLineBreakMode myLineBreakMode;
/**行间距**/
@property (nonatomic,assign) CGFloat lineRowSpacing;
/**段后间距**/
@property(nonatomic,assign)CGFloatlineAfterParagraphSpacing;
/**段前间距**/
@property(nonatomic,assign)CGFloatlineBeforeParagraphSpacing;
/**NSAttributedString*
* myAttributedText
*/
@property(nonatomic,copy)NSAttributedString* myAttributedText;
/**
isAdaptiveWidthByHeight
isAdaptiveHeightByWidth
不同时YES,其中一个为YES时,另一个会被改为NO,
**/
/**固定高度适配宽度 默认 NO**/
@property (nonatomic,assign) BOOL isAdjustWidthByHeight;
/**固定宽度适配高度 默认 NO**/
@property (nonatomic,assign) BOOL isAdjustHeightByWidth;
/**异步展示加载asyncAttributStr后调用block*
*注 目前仅在asyncAttributStr属性后调用
*注 使用时要预防block的循环引用,必要时要手动打破循环引用
*/
@property (nonatomic,copy)KZTCustomAttributeLabelBlock attributeBlock;
/**
使用后是否将 KZTCustomAttributeLabelBlock 置nil,(手动打破循环),使用时需先事先设置
对asyncAttributStr属性有效,
默认 NO,block不置nil
**/
@property(nonatomic,assign)BOOLisDestroyAttributeBlockAfterUse;
//将自定义MyCustomStrAlignment 换成 NSTextAlignment
//+(NSTextAlignment)changeCustomAlignment:(MyCustomStrAlignment)myAlignment;
////将NSTextAlignment 换成 自定义MyCustomStrAlignment
//+(MyCustomStrAlignment)changeTextAlignment:(NSTextAlignment)myAlignment;
@end
网友评论