在Flex中实现聊天表情图片支持-实战篇

本站原创文章,转载请注明: 转载自zrong's Blog,原文 在Flex中实现聊天表情图片支持-实战篇,欢迎使用文章源码进行转载。

本站转载文章会标明[转],转载请注明原始作者文章地址。



2011年6月17日更新:有网友说

SDK4.5下编译报错 1119: 访问可能未定义的属性 textFlow (通过 static 类型 spark.core:IEditableText 引用)。 TextChat.mxml /TextChat/src 第 94 行

问题的原因,在于SDK4.5将TextInput和TextArea的外观部件textDisplay的类型从原来的RichEditableText改为了IEditableText,因此无法得到textFlow属性。这是为了适应Mobile设备。在Spark主题下,它是 RichEditableText,而在Mobile主题下,它是StyleableTextField。

我解决的办法是强制将IEditableText转换成RichEditableText(见TextChat.mxml第95,100行)。这在Spark主题下当然是没问题的,但这并非是最好的办法。现在的源码是可以正常在SDK4和SDK4.5下编译的,请重新下载。

另外,经常有网友问到下载的压缩包中是一个FXP文件,这个该如何处理。其实这个问题Google一下自然有答案,做Flex,居然不知道FXP是什么,而且随手Google也不愿意做,我就只能鄙视你一下了。为了避免大家的麻烦,新提供的源码中增加了编译好的swf方便大家看效果,同时也放弃了FXP格式。我现在采用的是ANT+SDK编译,所以不要问我怎么把项目导入Flash Builder。

2010年10月7日更新:很多网友反应在SDK4正式版中,即使修改了源码也用不了,于是就顺手改了一下。现在的源码基于SDK4.1正式版,删除了一些原来beta版的时候用来解决beta版bug的代码,并加入了切分字符串的功能。也就是说,如果先输入文字,然后将输入点置于文字中再插入图片,图片会自动将文字分开。唉——转眼间这个源码发布一年了,时间过得真快啊……
顺便说一句:后来我又做了一个魔法表情功能,可以看这里

2009年10月29日更新:今天发现,有几个问题,Flash Builder beta2自带的SDK已经解决了(下面标出了),看来beta确实是不能用于正式产品啊……

2009年10月8日更新:Flash Builder beta 2发布后,spark组件中有些类的名称修改了,比如TextFilter改为TextConverter,SimpleText改为Label,TextArea.textview.textFlow改为TextArea.textFlow……因此如果使用beta2,那么下面的源码可能不会编译通过,请自行修改。


我发布“在Flex中实现聊天表情图片支持-资料篇”后,便有许多朋友找我要那个范例的源码。我在文章中就已提过那范例是从网上down来,并非我所做,自然没有源码。要源码,用X思,你懂的……

那好吧,源码来了。


例子很简单,所有的代码加起来都不到400行,但做的时候却很痛苦。因为要了解spark组件和FXG的特点,还要了解新的skin的做法。不过总算做好了,总结一下,纠结的地方主要有下面几点:

  1. 采用内嵌表情还是采用外部表情图片。
    为了获得更小的文件(Flex4比Flex3编译的文件大了200多K),一直是采用外部表情图片的。在本机调试都正常。但上传到网上后,就无法显示图片。调整了swf的base属性之后,图片可以在输入框和文字框中显示,就是不能显示在图片选择面板中。最后一气之下改成了内嵌图片。后来发现有可能是浏览器缓存问题,不过改就改了,也就没再纠缠这个问题。
    要注意的是,spark的BitmapImage是不支持外部图片的,必须要内嵌。所以如果要用外部图片,就必须用Halo组件中的Image。而由于TLF中的InlineGraphicElement又仅支持URL或者DisplayObject,而BitmapImage无法提供URL(本来嘛,是内嵌的撒)因此在我将外部图片转成内嵌后,原来的程序出了问题。原因是BitmapImage的source属性返回的是BitmapData对象,如果将其提供给InlineGraphicElement的source属性,就会报错。因此在提供图片信息的时候,必须要提供Bitmap才行。2010-10-07:正式版的InlineGraphicElement的source属性已经可以支持BitmapData对象了
  2. <图片插入到TextInput之后不更新。
    检查发现,InlineGraphicElement已经作为textFlow的元素存在了,但是在TextInput中却不显示出来,但如果再输入一些文字的话,图像又可以显示出来。因此判断是textFlow更新后没有执行flowComposer.updateAllControllers。把这个操作放在StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGED事件后就行了。
    2010-10-07正式版中已经支持自动更新了。
  3. Flex4 spark中的TextInpu焦点定位的怪问题。
    在发送输入框文字之后,再将文字清空,如果使用按钮来发送文字,则清空过后还能重新定位回输入框继续输入文字;而如果使用TextInput的enter事件来完成这个动作,则清空后返回虽然能重新定位输入框,并显示闪烁的输入光标,但无论如何也无法输入文字了,必须重新单击一次输入框,才能再次输入。后来用一个变通的方法解决了。就是在为输入框重新设置焦点之前,先将焦点移到按钮上,再移回来…… 很无语
    Flash Builder beta2自带的SDK(以及后面的SDK)已经解决了这个问题
  4. flowComposer自动清空为null的问题。
    flowComposer偶尔会自动清空,造成flowComposer.compose()或者flowComposer.updateAllControllers()失效,后来发现在界面大小变更的时候以及通过text=”设置文字清空的时候,flowComposer都可能会清空为null。而只需要重新将ti或者ta设置焦点就可以填充flowComposer的值。
    Flash Builder beta2自带的SDK(以及后面的的SDK)已经解决了这个问题
  5. 滚动条不更新的问题。
    输入的文字超过一屏之后,TextArea会自动出现滚动条。在Halo组件中,我是通过valueCommit事件来更新滚动条,但在spark中没有。不仅valueCommit没用,change等统统没用。后来改为用updateComplete来更新滚动条。其实,如果用textFlow的事件来更新,应该更加保险。
    另外,spark的scroller组件也是蛮纠结的,在Halo中用ta.verticalScrollPosition = ta.maxVerticalScrollPosition就可以了,可spark又整了个viewport出来。这不,更新语句又要改成ta.scroller.viewport.verticalScrollPosition=ta.scroller.viewport.contentHeight。
  6. 还有几个麻烦的事情,比如ParagraphElement要进行深复制才能用,比如format和hostFormat……算了,不说了,直接看效果好了 :em50:

  聊天表情图片支持源码 (656.3 KiB, 3,580 hits)



发表评论?

71 条评论。

  1. 传图片的功能,我能想到的只有用socket(留言47中的第二种方法)实现了。

  2. 很好,我正好急需这个东西.. 谢谢你的开源

  3. 这个源码TextChat.zip里面的TextChat.fxp用什么打开 ??

  4. 不错!谢谢分享。
    TextChat.fxp 可以用winrar, winzip, 7-zip都能打开

  5. SDK4.5下报…
    1119: 访问可能未定义的属性 textFlow (通过 static 类型 spark.core:IEditableText 引用)。 TextChat.mxml /TextChat/src 第 94 行 Flex 问题



  6. exdoit:

    SDK4.5下报…
    1119: 访问可能未定义的属性 textFlow (通过 static 类型 spark.core:IEditableText 引用)。 TextChat.mxml /TextChat/src 第 94 行 Flex 问题

    已经解决,请重新下载源码。

    问题的原因,在于SDK4.5将TextInput和TextArea的外观部件textDisplay的类型从原来的RichEditableText改为了IEditableText,因此无法得到textFlow属性。这是为了适应Mobile设备。在Spark主题下,它是 RichEditableText,而在Mobile主题下,它是StyleableTextField。

    我解决的办法是强制将IEditableText转换成RichEditableText(见TextChat.mxml第95,100行)。这在Spark主题下当然是没问题的,但这并非是最好的办法。

  7. 你好。发现一个问题:fb4.5 mx+spark工程,输入表情,发送;然后再输入一些文字,发送多次(即形成滚动条);然后下拉到底,再输入,则报错(但奇怪的是你这个页面的测试没问题)

    TypeError: Error #1009: 无法访问空对象引用的属性或方法。
    at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::updateGraphics()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:3182]
    at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::updateCompositionShapes()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:3080]
    at flashx.textLayout.compose::StandardFlowComposer/updateCompositionShapes()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\compose\StandardFlowComposer.as:616]
    at flashx.textLayout.compose::StandardFlowComposer/updateToController()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\compose\StandardFlowComposer.as:559]
    at flashx.textLayout.compose::StandardFlowComposer/updateAllControllers()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\compose\StandardFlowComposer.as:517]
    at flashx.textLayout.container::TextContainerManager/updateContainer()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\TextContainerManager.as:1343]
    at spark.components::RichEditableText/updateDisplayList()[E:\dev\hero_private\frameworks\projects\spark\src\spark\components\RichEditableText.as:2944]
    at mx.core::UIComponent/validateDisplayList()[E:\dev\hero_private\frameworks\projects\framework\src\mx\core\UIComponent.as:8989]
    at mx.managers::LayoutManager/validateDisplayList()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:736]
    at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:819]
    at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]

  8. 你可以打一下断点检测一下到底是哪一步出现了空对象。

  9. 只要不插入表情就没问题,楼主可以把上边的s:TextArea改为10%,字号24,发个表情,然后发4次文字,就会报错。具体断点是直接跑到flex自己的库源码里去了,不在工程代码里,这个不太会调。望楼主测试哈

  10. 是不是在 PopupManager window??!

    如果是请看 http://www.smithfox.com/?e=171

  11. 不是在那。
    简而言之就是滚动到表情消失,再输入一行,就出这个问题

  12. 它是一个程序,还是一个库?

    我找不到可以重用的类… 可惜

  13. 是代码范例。重用的话,你只有自己进行抽象了。

  14. 你这个例子好像不支持动态gif,我正在做修改,打算用GIFPlayer来实现动态GIF的显示,但遇到一个问题,那就是不知道怎么把GIFPlayer对象加入到输入框中,博主能给一点提示吗? :grin: :grin: :grin:

  15. 确实是不支持gif的。主要的原因,一个是要自己实现gif的解码和动画,另一个,就是gif的画质太差,不支持Alpha透明。
    Spark组件中的Text类组件其实是基于TLF开发的,它的本质是显示对象,你把GIFPlayer包装过的显示对象加入到TLF的容器中,应该就可以了。

  16. tenchiwang

    樓主是高手~
    不過好像 不支援中文?
    我自己是發現 S的組件不支持 中文
    改成原本的 MX 的就可以了~

  17. 当然是支持中文的。你没有在上面的Demo中测试么?
    对于Spark组件,你为它们设置一个中文字体,必须“Simsun”就可以支持中文了。

  18. 您好,请教个问题,这个确实可以使用TextConverter.export导出字符串信息,但是如何从带表情的字符串,加入聊天信息显示中啊
    我用TextConverter.importToFlow将导出的字符串导入,结果表情不显示,后来我换成外部图片链接也是一样,不知道这是什么问题,谢谢

  19. var ous:String =TextConverter.export(titf,TextConverter.TEXT_LAYOUT_FORMAT,ConversionType.STRING_TYPE) as String;

    trace(ous);

    var ius:String = this.emotionPanel.format(ous);//将链接类内容替换成外部图片链接

    trace(ius);
    var importer:ITextImporter= TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT);
    importer.throwOnError = true;
    var tfw:TextFlow = importer.importToFlow(ius);;
    ta.textFlow.addChild(tfw.getChildAt(0));
    ta.textFlow.flowComposer.updateAllControllers();

    代码如上,但是文本可以显示,图片区域出不来

  20. 梧桐树下听雨

    我最近也在做这个东西
    AIR写的一个聊天软件,实现方法和你的差不多
    实现了图文混排,字体样式。
    确还有两个问题,百思不得其解。
    1:聊天框信息显示区域,出现滚动条之后,拖动滚动条,表情图片消失
    2:出现滚动条之后,无法添加表情了!
    因为小弟以前是写PHP了,项目需要,写FLEX不足一月,很多FLEX的特性还没掌握,求大侠指点一二。
    QQ:747663826

发表评论


请输入上面的验证码