在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:

请使用下面的链接升级 Flash Player 到最新版本:

安装最新的Flash Player插件

1 文件