UILabel上添加gif动态图

swift-ios富文本(图文混排):支持图片文字GIF表情 ios 富文本(图文混排):支持图片,文字,GIF表情 立即下载

遇到一个新需求,需要在富文本上添加gif或者其他动态图,原来的使用的富文本不支持动态图,就研究下了国外大牛的demo,其实还是很简单的,主要原理就是把动态图切成一帧帧图片,然后利用NSTimer和动态图的周期循环在UILabel上画图片。。。但是亲测了一下不会引起cpu和内存方面的担忧,所以我们可以在第三方的富文本源码上进行修改或者重新封装一下,废话不多少,直接上代码。


1.拿gif为例,首先处理gif成图片数字和得到动画周期

 //测试 处理消息区 gif  得到 图片数组和动画周期 _images _duration

-(void)getImagesAndDuration{

       NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"gif"];

        NSData *data = [NSData dataWithContentsOfFile:path];

        CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);

        size_t count = CGImageSourceGetCount(source);

        _images = [NSMutableArray array];

        _duration = 0.0f;

        for (size_t i = 0; i < count; i++) {

            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);

            _duration += [self sd_frameDurationAtIndex:i source:source];

            [_images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];

            CGImageRelease(image);

        }

}


-(float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {

    float frameDuration = 0.1f;

    CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);

    NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;

    NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];

    

    NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];

    if (delayTimeUnclampedProp) {

        frameDuration = [delayTimeUnclampedProp floatValue];

    }

    else {

        

        NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];

        if (delayTimeProp) {

            frameDuration = [delayTimeProp floatValue];

        }

    }

    

    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.

    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify

    // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>

    // for more information.

    

    if (frameDuration < 0.011f) {

        frameDuration = 0.100f;

    }

    CFRelease(cfFrameProperties);

    return frameDuration;

}


2.绘制gif 我们的项目用的是TTTAttributedLabel,绘制图片代码基本都差不多,根据自己项目的需要,传入相应的数据,在绘制图片处进行修改

- (void)drawStrike:(CTFrameRef)frame

            inRect:(CGRect)rect

           context:(CGContextRef)c

{

    [super drawStrike:frame inRect:rect context:c];

    //PS:这个是在TTT里drawFramesetter....方法最后做了修改的基础上。

    CGFloat emojiWith = self.font.lineHeight*kEmojiWidthRatioWithLineHeight;

    CGFloat emojiOriginYOffset = self.font.lineHeight*kEmojiOriginYOffsetRatioWithLineHeight;

    

    //修正绘制offset,根据当前设置的textAlignment

    CGFloat flushFactor = TTTFlushFactorForTextAlignment(self.textAlignment);

    

    CFArrayRef lines = CTFrameGetLines(frame);

    NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);

    CGPoint lineOrigins[numberOfLines];

    CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);

    

    BOOL truncateLastLine = (self.lineBreakMode == NSLineBreakByTruncatingHead || self.lineBreakMode == NSLineBreakByTruncatingMiddle || self.lineBreakMode == NSLineBreakByTruncatingTail);

    CFRange textRange = CFRangeMake(0, (CFIndex)[self.attributedText length]);

    

    for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {

        CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);

        

        //这里其实是能获取到当前行的真实origin.x,根据textAlignment,而lineBounds.origin.x其实是默认一直为0的(不会受textAlignment影响)

        CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(line, flushFactor, rect.size.width);

        

        CFIndex truncationAttributePosition = -1;

        //检测如果是最后一行,是否有替换...

        if (lineIndex == numberOfLines - 1 && truncateLastLine) {

            // Check if the range of text in the last line reaches the end of the full attributed string

            CFRange lastLineRange = CTLineGetStringRange(line);

            

            if (!(lastLineRange.length == 0 && lastLineRange.location == 0) && lastLineRange.location + lastLineRange.length < textRange.location + textRange.length) {

                // Get correct truncationType and attribute position

                truncationAttributePosition = lastLineRange.location;

                NSLineBreakMode lineBreakMode = self.lineBreakMode;

                

                // Multiple lines, only use UILineBreakModeTailTruncation

                if (numberOfLines != 1) {

                    lineBreakMode = NSLineBreakByTruncatingTail;

                }

                

                switch (lineBreakMode) {

                    case NSLineBreakByTruncatingHead:

                        break;

                    case NSLineBreakByTruncatingMiddle:

                        truncationAttributePosition += (lastLineRange.length / 2);

                        break;

                    case NSLineBreakByTruncatingTail:

                    default:

                        truncationAttributePosition += (lastLineRange.length - 1);

                        break;

                }

                

                //如果要在truncationAttributePosition这个位置画表情需要忽略

            }

        }

        

        //找到当前行的每一个要素,姑且这么叫吧。可以理解为有单独的attr属性的各个range。

        for (id glyphRun in (__bridge NSArray *)CTLineGetGlyphRuns(line)) {

            //找到此要素所对应的属性

            NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((__bridge CTRunRef) glyphRun);

            //判断是否有图像,如果有就绘制上去

            NSString *imageName = attributes[kCustomGlyphAttributeImageName];

            if (imageName) {

                CFRange glyphRange = CTRunGetStringRange((__bridge CTRunRef)glyphRun);

                if (glyphRange.location == truncationAttributePosition) {

                    //这里因为glyphRange的length肯定为1,所以只做这一个判断足够

                    continue;

                }

                

                CGRect runBounds = CGRectZero;

                CGFloat runAscent = 0.0f;

                CGFloat runDescent = 0.0f;

                

                runBounds.size.width = (CGFloat)CTRunGetTypographicBounds((__bridge CTRunRef)glyphRun, CFRangeMake(0, 0), &runAscent, &runDescent, NULL);

                

                if (runBounds.size.width!=emojiWith) {

                    //这一句是为了在某些情况下,例如单行省略号模式下,默认行为会将个别表情的runDelegate改变,也就改变了其大小。这时候会引起界面上错乱,这里做下检测(浮点数做等于判断似乎有点操蛋啊。。)

                    continue;

                }

                

                runBounds.size.height = runAscent + runDescent;

                

                CGFloat xOffset = 0.0f;

                switch (CTRunGetStatus((__bridge CTRunRef)glyphRun)) {

                    case kCTRunStatusRightToLeft:

                        xOffset = CTLineGetOffsetForStringIndex(line, glyphRange.location + glyphRange.length, NULL);

                        break;

                    default:

                        xOffset = CTLineGetOffsetForStringIndex(line, glyphRange.location, NULL);

                        break;

                }

                runBounds.origin.x = penOffset + xOffset;

                runBounds.origin.y = lineOrigins[lineIndex].y;

                runBounds.origin.y -= runDescent;



//上面代码千篇一律 重点在这里 self.rankGifImageArray self.duration 是图片数组和动画周期

      NSUserDefaults * nextImage = [NSUserDefaults standardUserDefaults];

                    int imgIndex = [[nextImage objectForKey:@"location"] intValue];

                    

                    UIImage *image;

                    if (imgIndex < [self.rankGifImageArray count]-1) {

                        imgIndex++;

                    }else{

                        imgIndex= 0;

                    }

                    image = [self.rankGifImageArray objectAtIndex: imgIndex];


                    [nextImage setObject:[NSString stringWithFormat:@"%d",imgIndex] forKey: @"location"];


                    

                    runBounds.origin.y += 3; //稍微矫正下。

                    runBounds.size.width = 28;

                    runBounds.size.height = 13;

                    CGContextDrawImage(c, runBounds, image.CGImage);

                    

                    [self startGif:self.duration/self.rankGifImageArray.count];

}


- (void)startGif:(NSTimeInterval)time

{

    if (!gifTimer) {

         gifTimer = [NSTimer timerWithTimeInterval:time target:self selector:@selector(gifAnimate:) userInfo:nil repeats:YES];

        [[NSRunLoop mainRunLoop] addTimer:gifTimer forMode:NSRunLoopCommonModes];

    }

   

}


- (void)gifAnimate:(NSTimer *)timer

{

    [super setNeedsDisplay];

}


总结:我们要做的就是在富文本处理图片的基础上进行修改,达到实现动态图效果。





DWAnimatedLabel:UILabel子类,可让您为不同类型的文本设置动画 DWAnimatedLabel 一个UILabel子类,使您可以根据设置不同类型的文本动画。 特征 UILabel子类,易于使用 使用CADisplayLink执行平滑的动画 四种不同的动画 纯雨燕 安装 您想要将pod 'DWAnimatedLabel', '~> 1.1'或类似的内容添加到Podfile: target 'MyApp' do pod 'DWAnimatedLabel' , '~> 1.1' end 然后在终端内部或从CocoaPods.app运行pod install 。 另外,要进行测试运行,请运行以下命令: pod try DWAnimatedLabel 用法 首先,导入模块: import DWAnimatedLabel 然后,您可以像使用UILabel一样创建标签。 let label = DWAnimatedLabel ( frame : 立即下载

相关推荐

ios-富文本(支持图文混排、图片可网络可本地,gif请导入yykit).zip

图文混排

AWRichText —— 强大的iOS富文本排版库

AWRichText —— 强大的iOS富文本排版库 AWRichText 是一个基于CoreText和Objective-C语言的开源项目,旨在为iOS开发者提供一个面向对象、极简、易用且高效的富文本排版解决方案。 核心功能 该项目的主要功能包括: 支持图文混排,不仅仅是简单的图文组合,还能实现UIView与文字的混合排版。 支持GIF动图显示,丰富内容的呈现形式。 支持精确点击,使得用户可以...

gitblog_00149的博客 410

PMEdit一个富文本框可以编辑文本、图片并可以显示GIF动画

二、PMEdit是一个在windows下的富文本框,它能显示文字、编辑文字、显示图片、改变图片显示大小,具有行号、行图标、改变字体属性等特性。 PMEdit完成从底层开发,没有用任何windows控件,代码直接基于最基本GUI、windows消息,很容易移植到OpenGL或其他平台下。 说明:http://www.natframe.com/forum.php?mod=viewthread&tid=446&page=1&extra=#pid3354

iOS 文本与图片表情混排的实现

 2015-09-04 by 木易哥哥 智者精选,每天获取励志认知能量 www.5izhjx.com要实现文图混排效果需要用到的有:富文本NSMutableAttributedString,字符替换substringWithRange,以及支持动画gif的ImageIO.h。写了几个对象TQRichTextView,TQRichTextRunEmoji,SvGifView,废话不多说,列出实现该效...

木易哥哥的专栏 3805

gif表情键盘、图文混排富文本

一款gif表情键盘,聊天内容富文本展示用的是第三方YYText,支持显示网络图片。

StarRocks慢查询排查实战:从Query Plan到Profile的保姆级调优指南

本文提供StarRocks慢查询排查的实战指南,从Query Plan解析到Profile诊断,详细讲解如何识别执行计划中的危险信号和优化关键指标。通过物化视图优化、分布式执行调整和资源管控方案,帮助DBA快速定位并解决查询性能问题,提升数据库效率。

weixin_42568801的博客 379

ios 旋转加载gif_IOS-加载动态图(gif)

1 //2 //BowenView.h3 //IOS_0302_下拉刷新4 //5 //Created by ma c on 16/3/2.6 //Copyright © 2016年 博文科技. All rights reserved.7 //89 #import 1011 @interfaceBowenView : UIView1213 //要把loading界面加载到那个界面14 + (voi...

weixin_39956182的博客 445

LoFTR训练避坑指南:从零到一复现论文训练流程

本文是一份详细的LoFTR模型训练避坑指南,旨在帮助开发者从零开始复现论文训练流程。文章系统性地讲解了环境配置、数据准备、代码调试与显存优化等关键步骤,并针对常见的训练错误提供了解决方案,确保训练过程顺利进行。

weixin_29091837的博客 204

常用控件textlabel显示图片和动态图

常用控件,使用textLabel显示图片和动态图。 #include "widget.h" #include "ui_widget.h" #include <QMovie> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); //设置默认选中 ui->stackedWidget->setCurrentIn

u010955460的博客 1334

Microchip Studio 7.0 从零开始:下载、安装到首个AVR工程实战

本文为AVR单片机开发新手提供了Microchip Studio 7.0的完整入门指南。从官方下载、避坑安装,到创建首个GCC C工程、编写LED闪烁代码,再到项目配置、仿真调试与程序烧录,手把手带你完成从零到一的实战过程,是掌握AVR开发环境的必备教程。

weixin_29200741的博客 520

hcaptcha无感验证码逆向实战:从接口分析到环境补全

本文详细解析了hcaptcha无感验证码的逆向实战过程。通过分析核心接口与加密逻辑,重点介绍了采用环境补全策略来模拟真实浏览器环境,从而绕过验证码检测。文章提供了从接口抓包、剖析hsw.js加密核心到使用Node.js搭建模拟环境的完整步骤,为自动化操作提供了一种稳健的解决方案。

weixin_29324401的博客 1151

iOS个人整理02-UILabel/UIIamgeView

昨天学习了工程的建立和UIView视图的简单使用,今天总结一些最基本的控件 一、UILabel 标签,很简单,显示文字的 //初始化设置大小,有自己的初始化方法就用自己的,没有就用父类的 UILabel *myLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 10,250, 150)]; //设置Label的行数

舍本逐末 916

GIS小白也能看懂的实战:5步教你将ArcGIS里的等高线和水系完美导入CAD做规划图

本文详细介绍了如何将ArcGIS中的等高线和水系数据高效导入CAD,制作专业规划底图的5个关键步骤。从数据准备、ArcGIS处理到CAD优化,涵盖坐标系设置、数据裁剪、格式转换等实用技巧,特别适合设计规划领域的新手快速掌握GIS与CAD协同工作流程。

weixin_27966471的博客 426

在GIF图片上添加水印

最近项目中需要对图片(包括静态图和动图GIF)进行一些自定义的操作,比如添加文本,图片,或是其他页面元素。就此把所学分享出来。 Quartz2D Quartz2D是苹果公司提供的二维绘图引擎,可以实现绘图,绘制文字,绘制图片,截图,裁剪图片等功能。 静态图:即把当前View上的所有东西保存成一个新的图片 func screenCapture(view: UIView)-> UIImage...

weixin_30662849的博客 218

Mybatis面试题(基础篇)

(1)mybatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。(2)mybatis避免了几乎所有的JDBC代码(说明了mybatis底层用的就是JDBC,只不过是封装了)和手动设置参数以及获取结果集。(3)mybatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的pojo映射成数据库中的记录。

qq_38196449的博客 1687

手把手教你 Ubuntu 24.04 离线安装 Ollama

本文介绍 Ubuntu 下离线安装 Ollama 并使用 Ollama 部署 llama3.1-70b 大模型

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 1018

IOS-加载动态图(gif)

1 // 2 // BowenView.h 3 // IOS_0302_下拉刷新 4 // 5 // Created by ma c on 16/3/2. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h&g...

weixin_30824479的博客 85

超声波传感器(CHx01) 学习笔记 Ⅲ-API介绍

超声波传感器(CHx01) API介绍

nicole088的专栏 1386

YYLabel完全指南:告别UILabel性能瓶颈,打造丝滑富文本体验

YYText是iOS平台上一款功能强大的富文本框架,专为解决原生UILabel在复杂文本展示时的性能问题而设计。无论是图文混排、动态文本效果还是高性能编辑,YYText都能提供流畅的用户体验,是iOS开发者构建富文本界面的理想选择。 ## YYText架构解析:为何比UILabel更高效? YYText采用了分层设计架构,直接基于CoreText构建,相比系统TextKit框架减少了中间层开销

gitblog_00020的博客 409

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

UI基础视图----UIImageView总结

  UIImageView和UILabel一样,也是UIKit框架中非常常用的视图类。继承关系和UILabel完全一致(都是继承于UIView),功能也相似(用户交互都默认为关,主要用于展示),只不过UIImageView用于展示图片,UILabel用于展示文字。   UIImageView主要用于展示两种图片,一种是静态图片,也是最基础的用法,另一种是动态图片(一组图片产生的动画效果)。所以U...

weixin_30602505的博客 125

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

iOS UI-UIPickerView(拾取器)、UIWebView(网页视图)和传值方式

1 // 2 // ViewController.m 3 // IOS_0107_finalToolClass 4 // 5 // Created by ma c on 16/1/7. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import "View...

weixin_30485379的博客 123

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

iOS逆向过程思考(1)

通过隐藏iOS系统自带APP-Mail底部的编辑按钮对逆向过程的思考对于APP来说,我们感兴趣的往往体现在UI上,UI展示了函数的执行过程和结果.函数和UI之间的关联非常紧密,如果能够拿到感兴趣的UI对象,就可以找到它对应的函数,我们称该函数为UI函数.在这个过程中,一般是利用Cycript,结合UIView中的神奇私有函数recursiveDescription和UIResponder中的next

Esirnus 1518

动画富文本编辑器 `AnimRichEditor`:为内容创作注入生动活力

动画富文本编辑器 AnimRichEditor:为内容创作注入生动活力 去发现同类优质开源项目:https://gitcode.com/ 在数字时代,内容创作的需求日益增长,而一个强大且直观的编辑工具是提升创作效率的关键。今天,我们将向您推荐一款名为 的创新富文本编辑器,它不仅提供基本的文本编辑功能,更引入了动画元素,让您的文字更具表现力和吸引力。 项目简介 AnimRichEditor 是一个...

gitblog_00038的博客 409

让UILabel提示文字动起来

当用一个UILabel或者其他作为提示输入错误信息的时候,为了使错误信息引起用户注意,可以采取增加一个动画效果,例如:   [objc] view plain copy print? [UIView animateWithDuration:.1 animations:^{      self.errorLabel.alpha = 0.0;        } comp

MOKA 538
上一篇: iOS随手整一个无限轮播图
下一篇: iOS11和iPhone X适配
KingOfTheCoders
博客等级 码龄12年 1粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值