Mobile Flex聊天功能(支持表情显示)

[TOC]

ChatTextBox.mxml 表情文本显示

<?xml version="1.0" encoding="utf-8"?>  
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
          xmlns:s="library://ns.adobe.com/flex/spark"
          gap="0" horizontalAlign="left" verticalAlign="middle"
          minWidth="0" maxWidth="{forceWidth}">  
    <fx:Script>  
        <![CDATA[  
            import com.person.model.modelData.ModelFaces;  
 
            import mx.core.UIComponent;  
            import mx.events.FlexEvent;  
 
            import spark.components.HGroup;  
            import spark.components.Image;  
 
            private var currentHB:HGroup;  
            private var currentInLineWidth:Number = 0;  
            private var maxText:int = 100;  
            private var sendTxtArr:Array=[];  //type: 1,text 2,img   
            private var leftStr:String = "[";  
            private var rightStr:String = "]";  
            private var currentIndex:Number = -1;  
 
 
            private var muiltTextArr:Array =[];  
 
            public var lineSpace:Number = 2;  
            public var bold:String='normal';  
            public var italic:String="normal";  
            public var underline:String="none";  
            public var color:uint = 0x000000;  
 
            [Bindable]  
            public var forceWidth:Number = 210;  
            public var forceImageSize:Number = 30;  
            public var fontSize:Number = 18;  
 
 
            /**  
             * 信息分类处理方法  
             */
            public function splitString(txt:String):void
            {     
                var a1:Array=txt.split(leftStr);  
                for(var i:int=0; i < a1.length; i++)  
                {  
                    if (i == 0)  
                    {  
                        sendTxtArr.push({label:a1[i], type:'1'});  
                    }  
                    else
                    {  
                        var s1:String=a1[i].toString()  
                        if (s1.indexOf(rightStr) != -1)  
                        {  
                            var s2:String=s1.substring(0, s1.indexOf(rightStr));  
 
                            if (s2.length <= 2)  
                            {  
                                var smile:String = leftStr + s2 + rightStr;  
                                for each (var smiley:Object in ModelFaces.getInstance().faces)   
                                {  
                                    if (smile == smiley.imageName)  
                                    {  
                                        sendTxtArr.push({label:smiley.imageUrl, type:'2'});  
                                        var s3:String=s1.substring(s1.indexOf(rightStr) + 1, s1.length);  
                                        if(s3.length>0)  
                                        {  
                                            sendTxtArr.push({label:s3, type:'1'});  
                                        }  
                                    }  
                                }  
                            }  
 
                        }  
                        else
                        {  
                            sendTxtArr.push({label:leftStr + s1, type:'1'});  
                        }  
                    }  
                }  
 
                createChildQueue();  
            }  
 
            /**  
             * 创建子项队列方法  
             */
            private function createChildQueue():void
            {  
                ++currentIndex;  
                if (sendTxtArr[currentIndex] != undefined)  
                {  
                    if (Object(sendTxtArr[currentIndex]).type == '1')  
                    {  
                        addTxt(Object(sendTxtArr[currentIndex]).label)  
                    }  
                    else if (Object(sendTxtArr[currentIndex]).type == '2')  
                    {  
                        addImg(Object(sendTxtArr[currentIndex]).label)  
                    }  
 
                }  
                else
                {  
                    dispatchEvent(new Event('ChildCreateComplete'));  
                }  
            }  
 
            /**  
             * 添加表情  
             */
            private function addImg(url:Class):void
            {  
                addNewHBox();  
                var img:Image=new Image();  
                img.source= new url();  
                img.visible=false;  
                img.addEventListener(FlexEvent.UPDATE_COMPLETE, imgComplete,false,0,true);  
                currentHB.addElement(img);  
            }  
 
 
            /**  
             * 图片加载完成事件  
             */
            private function imgComplete(e:FlexEvent):void
            {  
                var img:Image=Image(e.currentTarget);  
                if (img.width == 0)  
                {  
                    return ;  
                }  
 
                if (img.width > forceImageSize)  
                {  
                    img.width = forceImageSize;  
                    img.height = forceImageSize;  
                }  
 
                if ((img.x + img.width) > forceWidth)  
                {  
                    currentHB.removeElement(img);  
                    addNewHBox(true);  
                    addImg(getDefinitionByName(getQualifiedClassName(img.source)) as Class);  
                }  
                else
                {  
                    img.visible = true;  
                    currentInLineWidth = img.x + img.width;  
                    createChildQueue();  
                    currentHB.invalidateProperties();  
                    currentHB.invalidateSize();  
                    currentHB.invalidateDisplayList();  
                }  
                img.smooth = true;  
            }  
 
 
            /**  
             *  添加文字  
             */
            public function addTxt(str:String):void
            {         
                if(str.length > maxText)  
                {  
                    str=str.substring(0,maxText)+"...";  
                }  
                addNewHBox();  
 
                if ((forceWidth - currentInLineWidth) <= fontSize)  
                {  
                    addNewHBox(true);  
                }  
 
                var t:TextField = new TextField();  
                t.width = forceWidth - currentInLineWidth;  
                t.visible = false;  
                t.text=str;  
                t.wordWrap = true;  
                var fm:TextFormat = new TextFormat();  
                fm.bold = bold == 'bold' ? true : false;  
                fm.italic = italic == "italic" ? true : false;  
                fm.underline = underline == "underline" ? true : false;  
                fm.color=color;  
                fm.size=fontSize;  
                t.setTextFormat(fm);  
                t.addEventListener(Event.ADDED_TO_STAGE, txtCreateComplete,false,0,true);  
                var ui:UIComponent=new UIComponent();  
                ui.addChild(t);  
                currentHB.addElement(ui);  
            }                 
 
            /**  
             *  文字加载完成事件  
             */
            private function txtCreateComplete(e:Event):void
            {  
                var t:TextField = TextField(e.currentTarget);  
                var fm:TextFormat = new TextFormat();  
                fm.color = color;  
                fm.size = fontSize;  
                t.setTextFormat(fm);      
                var ui:UIComponent = UIComponent(t.parent);  
                ui.width = t.textWidth;  
                ui.height= t.textHeight/t.numLines + lineSpace;  
                if (t.numLines > 1)  
                {  
                    var out0:String="";  
                    var out:String='';  
                    for(var i:int=0; i < t.numLines; i++)  
                    {                                         
                        if (i != 0)  
                        {                         
                            out += t.getLineText(i);                                              
                        }  
                    }     
                    t.textColor = color;  
                    t.htmlText = t.getLineText(0);  
                    t.visible = true;  
                    muiltTextAddRow(out);  
                    fm.size = fontSize;  
                    t.setTextFormat(fm);  
                }  
                else
                {  
                    t.visible=true;  
                    currentInLineWidth = ui.x + ui.width;  
                    createChildQueue();  
                }  
 
            }  
 
 
            /**  
             *  添加多行文本  
             */
            private function muiltTextAddRow(s:String):void
            {  
 
                addNewHBox(true);  
                var t:TextField=new TextField();  
                t.width = forceWidth - currentInLineWidth;  
                t.visible=false;  
                t.htmlText = s;  
                t.wordWrap=true;  
                var fm:TextFormat=new TextFormat();  
                fm.bold=bold == 'bold' ? true : false;  
                fm.italic=italic == "italic" ? true : false;  
                fm.underline=underline == "underline" ? true : false;  
                fm.color=color;  
                fm.size=fontSize;  
                t.setTextFormat(fm);  
                t.addEventListener(Event.ADDED_TO_STAGE, txtCreateComplete,false,0,true);  
                var ui:UIComponent=new UIComponent();  
                ui.addChild(t);  
                currentHB.addElement(ui);  
            }  
 
            /**  
             * 新建一行  
             * @param   bool: 是否强制新建一行  
             */
            private function addNewHBox(bool:Boolean=false):HGroup  
            {  
                if (bool)  
                {  
                    currentInLineWidth=0;  
 
                    var hb:HGroup = new HGroup();  
                    hb.verticalAlign = "middle";  
                    hb.horizontalAlign = "left";  
                    hb.gap = 0;  
                    this.addElement(hb);  
                    currentHB=hb;  
 
                    return currentHB;  
                }  
 
                if (currentHB == null)  
                {  
                    hb = new HGroup();  
                    hb.verticalAlign = "middle";  
                    hb.horizontalAlign = "left";  
                    hb.gap = 0;  
                    this.addElement(hb);  
                    currentHB = hb;  
                }  
                return currentHB;  
            }  
        ]]>  
    </fx:Script>  
    <fx:Declarations>  
        <!-- 将非可视元素(例如服务、值对象)放在此处 -->  
    </fx:Declarations>  
    <fx:Metadata>  
        [Event(name="ChildCreateComplete", type="flash.events.Event")]  
    </fx:Metadata>  
</s:VGroup>

ChatMsgItem.mxml 聊天对话框

<?xml version="1.0" encoding="utf-8"?>  
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:items="com.person.views.items.*"
         width="100%">  
    <fx:Script>  
        <![CDATA[  
            import mx.events.FlexEvent;  
 
            import spark.events.ElementExistenceEvent;  
 
            [Bindable]  
            public var chatTime:String;  
 
            [Bindable]  
            public var isDisappear:Boolean = false;  
 
            [Bindable]  
            private var msg:String = "";  
 
            [Bindable][Embed(source="assets/person/person.swf",symbol="other")]  
            private var img_other:Class;  
            [Bindable][Embed(source="assets/person/person.swf",symbol="me")]  
            private var img_me:Class;  
 
            [Bindable]  
            private var bg_color:uint = 0xb4e447;  
 
 
            /**  
             *  设置信息方法  
             *  @param  msg 信息   
             *  @param  isSelf  是否是自己发的信息  
             */
            public function setMsg( msg:String,sendDate:String ,sendImg:String, isSelf:Boolean):void
            {  
                this.msg = msg;  
                if(isSelf)  
                {  
                    grp_main.right = 0;  
                    grp_item.swapElements(img_photo,grp_msg);  
                    img_pic.source = img_me;  
                    bg_color = 0xf3f3f3;  
                }  
                else
                {  
                }  
                img_photo.source = sendImg;  
                lab_date.text = sendDate;  
                content.splitString(msg);  
                this.visible = false;  
            }  
 
            public function uptext():void
            {  
                if(this.parentDocument.content.contentHeight > this.parentDocument.content.height )  
                {  
                    trace("msg.substr(msg.length-1,1) =" + msg.substr(msg.length-1,msg.length-1) );  
                    if(msg.substr(msg.length-1,msg.length-1) == "]")  
                    {  
                        this.parentDocument.content.verticalScrollPosition = this.parentDocument.content.contentHeight - this.parentDocument.content.height;  
                    }  
                    else
                    {  
                        this.parentDocument.content.verticalScrollPosition = this.parentDocument.content.contentHeight;  
                    }  
                }  
            }  
        ]]>  
    </fx:Script>  
    <fx:Declarations>  
        <!-- 将非可视元素(例如服务、值对象)放在此处 -->  
    </fx:Declarations>  
    <s:Label id="lab_date" height="20" width="100%" color="#5C5C5C" fontSize="14" textAlign="center"
             verticalAlign="middle"/>  
    <s:VGroup id="grp_main" top="2" gap="2" paddingLeft="10" paddingTop="20" paddingRight="10">  
        <s:HGroup id="grp_item" width="100%" gap="-1">  
            <s:BitmapImage id="img_photo" width="48" height="48" smooth="true">  
                <s:mask>  
                    <s:BorderContainer width="48" height="48" cornerRadius="5"/>  
                </s:mask>  
            </s:BitmapImage>  
            <s:VGroup id="grp_pic" width="10" height="48" depth="1" horizontalAlign="right"
                      verticalAlign="middle">  
                <s:BitmapImage id="img_pic" width="10" fillMode="scale" source="{img_other}"/>  
            </s:VGroup>    
            <s:Group id="grp_msg" height="90%">  
                <s:BorderContainer width="100%" height="100%" backgroundColor="{bg_color}"
                                   cornerRadius="8" dropShadowVisible="true" verticalCenter="0"/>  
                <s:Group left="6" right="8" top="5" bottom="5" height="100%">  
                    <items:ChatTextBox id="content" width="100%" height="100%" ChildCreateComplete="this.visible = true;uptext()"/>  
                </s:Group>  
            </s:Group>    
        </s:HGroup>    
    </s:VGroup>  
</s:Group>

ChatMessageShowView.mxml 显示面板框

<?xml version="1.0" encoding="utf-8"?> 
<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                      xmlns:s="library://ns.adobe.com/flex/spark"> 
    <fx:Script> 
        <![CDATA[ 
 
            /** 
             *  控制文字输入后置底 
             */
            [Bindable] 
            public function updateText():void
            { 
                 if(content.contentHeight > content.height) 
                { 
                    content.verticalScrollPosition = content.contentHeight - content.height; 
                }  
            } 
        ]]> 
 
    </fx:Script> 
    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout> 
    <s:Group bottom="10" width="100%" height="100%"> 
        <s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0"> 
            <s:fill> 
                <s:SolidColor color="#f3f1da"/> 
            </s:fill> 
        </s:Rect>   
    <s:Scroller id="chatMessageScroller" width="100%" height="100%" > 
        <s:VGroup id="content" width="100%" height="100%" gap="10" hasFocusableChildren="true"
                  paddingBottom="10" verticalAlign="top" resize="updateText()"/> 
    </s:Scroller>    
    </s:Group> 
</s:SkinnableContainer>