美文网首页小问题
textView加载带大量html标签的文本,并实现点击图片预览

textView加载带大量html标签的文本,并实现点击图片预览

作者: 小涛_78e8 | 来源:发表于2019-01-15 18:53 被阅读8次

    测试文本数据

    //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

    相关文章

      网友评论

        本文标题:textView加载带大量html标签的文本,并实现点击图片预览

        本文链接:https://www.haomeiwen.com/subject/tinydqtx.html