【转】关于FLASH中图文混排聊天框的小结
图文混排也是FLASH里一个很古老的话题了,我们不像美国佬那样游戏里面聊天框就是聊天框,全是文字干干净净,也不像日本人发明了并且频繁地使用颜文字。不管是做论坛、做游戏,必定要实现的一点就是带表情对话框。
闲话扯多了,直接进入正题把。
1、TextField
首先,使用TextField的情况下
要想在使用TextField的前提下实现图文混排,一般比较流行的有2种实现方法:
第一种是使用HTML标签,textfield支持简单的HTML标签,比如<img>、<a>等等,在设置了href的a标签的TextField上可以注册一个侦听器侦听TextEvent.LINK事件,其广播的event具有一个text属性,就是href=”event:aaaa”中冒号后的字符串。通过标记和判断字符串可以知道发生了哪个点击事件。而IMG标签的实用性却太差,几乎无法控制图片的定位,也做不到图文同行。
另一种方法是使用双层结构,就是自己搞一个包含了2层的对话框,下面一层是普通的TextField,上面一层是图片层,当遇到需要展示图片的时候,在TextField里用一个占位符代替图片,然后在图片层的相应位置addChild一张图片。网上有关这种解决办法的自制组件有很多,这里有一个比较好的,叫做RichTextField,这个类可以比较完美地实现一般的聊天框对表情的需要:
RichTextField有如下特性:
●在文本末尾追加文本和显示元素。
●在文本任何位置替换(删除)文本和显示元素。
●支持HTML文本和显示元素的混排。
●可动态设置RichTextField的尺寸大小。
●可导入和导出XML格式的文本框内容。
但是这种2层结构有个缺陷,由于表情图片不是处在文本框中,那么当滚动滚动条时,图片只能选择显示or不显示,那么当滚动到某一行中间时,就会出现下图的情况:

(最后一行的图片根据判断已经不显示了,但是文字还在。或者与之相反的情况)
另外如果我们需要聊天框可以自己拉宽、拉长时,也会出现同样的问题。无法像一个真正的文本框那样,处于边缘的文字会被遮住一部分,图片也被遮住一部分。(如下图的最后一行文本所示),排版也经常出现错位现象。

使用该组件还有一个需要注意的地方就是如果你需要改变输入文字的颜色,如果当前输入框中有表情,将会造成表情和光标的错位:
比如我侦听一个点击调色板发出的事件,使用如下侦听器函数
1
2
3
4
5
6
7
8
9
|
private function changeInputColor(e:InfoEvent): void { i_txtFormat.color = e.info as uint ; input.textfield.setTextFormat(i_txtFormat); //var xml:XML = input.exportXML(); //input.clear(); //input.importXML(xml); stage.focus = input.textfield; } |
前两行代码用于改变输入框的format,如果将345行注释掉,就会出现表情重叠、光标错位的情况,所以需要每次都把输入框中的内容导出,然后clear掉,在重新导入进去。由于AS对XML的处理速度较慢,所以这也在一定程度上降低了效率。
总之,如果需求简单,那么RichTextField类是一个很好的选择。功能简便也对得起他轻量级的体积.
其次,使用FTE(Flash text engine)和TLF(TextLayout Framework)来实现。
Flash.text.engine包是fp10中新加入的内置包,也就是说如果你的flash使用了该文本引擎,10以下版本的flashplayer是找不到该类的。
2、flash.text.engine
其次,使用FTE(Flash text engine)和TLF(TextLayout Framework)来实现。
Flash.text.engine包是fp10中新加入的内置包,也就是说如果你的flash使用了该文本引擎,10以下版本的flashplayer是找不到该类的。
使用FTE在舞台上创建一段文本的基本流程如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//首先创建一个字符串 var txt: String = '我是一条字符串' ; //创建一个格式,并将字符串与格式传给文本元素(TextElement)的构造方法 var format:ElementFormat = new ElementFormat( new FontDescription( 'Verdana' , 12 )); var textEle:TextElement = new TextElement(txt,format); //创建一个文本块,文本块负责储存文本元素,并创建文本行(TextLine)用于显示文本元素 var inputBlock:TextBlock = new TextBlock(textEle); //使用文本块创建文本行,并将其显示在舞台或父容器中 var textline1:TextLine = inputBlock.createTextLine( null , 100 ); //第一个参数null表示该文本行没有上一行,是第一行 textline1.x = 100 ; textline1.y = 100 ; addChild(textline1); |
TextElement类就是一条带颜色、字体、大小的字符串。与它同等级别的类还有GraphicElement(一个图片元素)和GroupElement(一些文字元素和一些图片元素组成的元素),他们都是ContentElement的子类,ContentElement本身无法实例化。
TextBlock类是一个文本块,他是TextLine类的工厂,他创建这些line,并添加他们到舞台上,textBlock.content属性就是这个文本块中包含的内容元素,我们可以将上面提到的3种ContentElement的子类赋给文本块的content属性。由文本块生产的TextLine是继承自DisplayObjectContainer的,这就意味着我们可以把一句话分成不同的行,并且添加到舞台的任何地方,还可以进行事件侦听。
我们可以在flash.text.engine包中看到Adobe对FTE的介绍:
“FTE 提供对文本度量、格式和双向文本的复杂控制的低级别支持。尽管可以使用 FTE 创建和管理简单的文本元素,但设计 FTE 的主要目的在于为开发人员创建文本处理组件提供基础。”
如果我们需要显示一些简单的文本/图文,那么使用FTE是很好的选择,他甚至比传统的Textfield更加低级,更加节省内存。
为了方便使用,而ADOBE又使用FTE的API开发了一套框架,叫做TextLayoutFramework,它位于flashx.textlayout包中,它和其他API不同,是AS3写的一套类库而不是FLASH本地的原生API,因此存在运行效率和带来的文件体积增加的问题。例如TLF通过EditManager类将文本变成可编辑文本,是通过注册KeyboardEvent事件侦听的方式来获取用户按下的字符,然后添加到文本流中的方式实现的。事件侦听势必会带来效率的下降。 TLF整个类库的体积在200K不到,但是ADOBE提供了SWZ文件,这些文件会在第一次下载的时候储存到用户机器里免去二次下载,所以进行RSL的话也不会带来太大体积压力。
3、flashx.textlayout
使用TLF创建一个简单的文本流程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
一行字: span:SpanElement --> span.text = “Hello world”; 一张图: g:InlineGraphicElement --> g.source = 路径/位图/内嵌图片等 一个段落:p: ParagraphElement --> p.fontSize = 16 ; p.addChild(span); p.addChild(g); 一个文本流:textFlow:TextFlow --> textFlow.addChild(p); 创建控制器: displayObject = new Sprite(); displayObject.x = _x; displayObject.y = _y myController = new ContainerController(displayObject,_width,_height); 为文本流添加控制器,并更新所有控制器 textFlow.flowComposer.addController(myController); textFlow.flowComposer.updateAllControllers(); |
上面代码中的_x,_y,_width,_height就是你可以控制的文本框位置的和大小。TLF中的updateAllControllers()方法非常重要,在你对文本流做出任何更改后都需要调用这个方法来让改动显示在屏幕上,包括你在可编辑文本中输入文字之后也需要调用这个方法,当然这里Adobe已经帮你在KeyboardEvent的侦听器中实现了。所以我们需要在改变文字颜色、插入表情、清空文本等等之后都调用这个方法来更新文本流的显示。
但是没有必要频繁地调用这个函数,为了提升效率我们只需要在flashplayer每次更新屏幕之前调用就可以了。所以我们可以在文本流发生改变后调用stage.invalidate()函数,这个函数起到一个标记的作用,让flashplayer在下一次屏幕更新的时候自动发送一个Event.RENDER事件,我们只需要侦听这个事件,统一对文本流的显示进行更新就可以了。
1
2
3
4
5
6
7
8
9
10
11
|
stage.addEventListener(Event.RENDER,updateControllers); private function updateControllers(e:Event): void { outputFlow.flowComposer.updateAllControllers(); inputFlow.flowComposer.updateAllControllers(); } |
你当然可以直接使用TLF类库来工作,但是ADOBE又分别在FLEX和FLASH PRO中制作了基于TLF的文本框,这才是真正组件级别的使用,他们更加实用,但是会给你的文件带来更大的体积…我们现在是做游戏的聊天框,FLEX组件暂时不讨论,FLASH PRO中的组件位于fl.text.TLFTextField,如果使用FLASH PRO进行编程那么你可以直接看到这个类,如果使用flashBuilder或者fd,你可以在找到在如下路径找到包含了TLFTextField组件的swc文件
“你的Flash Professional安装目录\Adobe Flash CS5.5\ Common\ Configuration\ ActionScript 3.0\ libs\ tlfruntime.swc”
并把这个文件包含到工程库路径中。
该类有一个textFlow属性,我们可以把自己创建的一个TLF文本流赋给一个TLFTextField实例。然后添加这个实例到舞台上。
1
2
3
4
5
|
outputFlow :TextFlow; textField = new TLFTextField(); textField.textFlow = outputFlow; |
除此之外,这个类的使用方法非常类似与普通TextField。
下面是使用TLFTextfield组件制作的聊天框:
总结与拓展
我们可以根据上面的讨论,根据不同的需求选择不同的文本结构:
1.简单的用于显示一段不可编辑的文本:使用FTE的TextLine类来完成
2.一个不可以被拉伸缩放的带表情聊天框:使用RichTextField或你自己实现的两层结构
3.支持拉伸缩放功以及更多功能(比如每一行字体都不同、类似古文的竖行排版、输入框撤销/重做等)的带表情聊天框:使用TLF框架。
4.

这里有两张图,上面是使用2层结构实现的,下面是使用TLF实现的。由于TLF是直接将我们输入的表情实例输出出来,每个表情的实例化都在点击插入表情按钮的时刻,所以这些表情都不是同步的,而上面一张的所有表情都是在我们按下回车发送之后同时实例化的,所以表现为同步。
实际使用中如果不在乎表情是否同步,我想应该可以进行一些优化,首先使用逐帧改变bitmapData的位图对象代替MovieClip,然后将同一种表情的所有bitmapData 指向同一个BitmapData实例。
【转】关于FLASH中图文混排聊天框的小结的更多相关文章
- Android TextView中图文混排设置行间距导致高度不一致问题解决
最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常easy,突然有一天发现文字跟表情混排的时候,TextView中图文高度不一致,excuse...什么鬼,之前明明测试过图文混排,不存在这个 ...
- iOS中 图文混排/自定义图文混排 作者:韩俊强
指示根视图:(准备几张图片,把label加载在window上) CustomLable *label = [[CustomLable alloc]initWithFrame:CGRectMake(0, ...
- CSS - 关于li中图文混排不能垂直居中的问题
图片和文字一起放在li标签下不能同时垂直居中 解决办法: 1.设置图片的position:absolute; 2.把文字加上span标签: span{ height:30px;line-heigh ...
- AS3聊天单行输入框图文混排完美实现
几年前刚毕业.第一个游戏模块做的就是聊天.到如今.几个游戏写过几次聊天模块. 之前在4399做的<幻龙骑士>(又名<神骑士>),还有上周六刚上线的<疯狂的子弹>, ...
- photo中的图文混排
photoshop中无法象word中自动图文混排,但可以通过手工绘制路径完成图文混排. 如下图,先摆放图像,然后绘制路径,然后在路径中输入或粘贴文字即可.
- Android中Textview显示Html,图文混排,支持图片点击放大
本文首发于网易云社区 对于呈现Html文本来说,Android提供的Webview控件可以得到很好的效果,但使用Webview控件的弊端是效率相对比较低,对于呈现简单的html文本的话,杀鸡不必使用牛 ...
- 仿QQ聊天图文混排流程图【适用于XMPP】
图文混排流程图.graffle4.8 KB 下面附上图片素材: 表情.zip692.5 KB 下面是字符串与图片的详细对应关系: "[呲牙]& ...
- Unity UGUI实现图文混排
目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英文来说,并没有什么影响.然后对于中文来说就是一个相当麻烦的事了,毕竟图文混排多用于游戏 ...
- [UGUI]图文混排(一):标签制定和解析
参考链接: https://github.com/SylarLi/RichText/tree/master/Assets/Scripts 正则表达式: https://blog.csdn.net/ly ...
随机推荐
- centos6安装php5.4以上版本
1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包,先删除他们 yum remove php.x86_64 php-cli.x86_64 p ...
- cron 任务
相关文件 /etc/crontab /etc/cron.deny 设置哪个用户有权限运行 cron 任务 /var/spool/cron/root /var/spool/cron/user /var/ ...
- php阳历转农历的类 谷歌到的
<?phpclass Lunar { var $MIN_YEAR = 1891; var $MAX_YEAR = 2100; var $lunarInfo = array( ...
- js 实时监听input中值变化
注意:用到了jquery需要引入jquery.min.js. 需求: 1.每个地方需要分别打分,总分为100; 2.第一个打分总分为40; 3.第二个打分总分为60. 注意:需要判断null.&quo ...
- git整理
git图形客户端:SourceTree bash: 先初始化: git init 添加远程仓库: git remote add sae https://git.sinacloud.com/newapp
- bootstrap-table分页第二篇 延续上一篇的
这个是service/** * 返回记录数 * @return */ public Integer getPageTotal(Integer userid); //service的实现类 public ...
- $stateProvider
在你的应用中大多数状态都有与其相关联的 url,路由控制不是设计完成 state 之后的事后想法,而是开始开发时就应该考虑的问题. 这里是如何设置一个基本url. 12345 $stateProvid ...
- win7系统网卡驱动正常,网线连接设备正常,但电脑右下角网络图片显示一直在转圈或者显示一个黄色感叹号的解决办法
今天遇到一个问题是电脑的win7系统一直都可以连接有线,但今天突然连接不了.在我的电脑右键-->管理--->设备管理器-->网络适配器,里面查看了网络适配器安装正常.但是电脑右下角的 ...
- Js实现string.format
经常需要动态拼接html字符串,想到用类似于.net的string.format函数比较好,于是找了下,stackoverflow的代码: if (!String.prototype.format) ...
- 微信小程序开发—快速掌握组件及API的方法---转载
微信小程序框架为开发者提供了一系列的组件和API接口. 组件主要完成小程序的视图部分,例如文字.图片显示.API主要完成逻辑功能,例如网络请求.数据存储.音视频播放控制,以及微信开放的微信登录.微信支 ...