此处是私聊面板多行输入框的图文混排实现,类似于QQ聊天面板。
想要单行的输入框图文混排,请点击这里传送:
本文代码在上一篇文章中的代码简单修改而来,所以就不做注释了。
所有的注释都在上一篇文章的代码里,请自行移步。
package
{
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.filters.GlowFilter;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.ui.Keyboard;
import flash.utils.getDefinitionByName;
public class InputText extends Sprite
{
private const PLACEHOLDER:String = String.fromCharCode(12288);
public var textField:TextField;
private var mcLayer:Sprite;
private var dataList:Vector.<Express>;
private var begin:int = 0;
private var end:int = 0;
private var scrollV:int = 0;
private var keyCode:uint = 0;
private var defaultFormat:TextFormat;
private var placeFormat:TextFormat;
public function InputText(w:Number = 400, h:Number = 200)
{
defaultFormat = new TextFormat();
defaultFormat.color = 0xFFFFFF;
defaultFormat.size = 12;
defaultFormat.leading = 10;
defaultFormat.letterSpacing = 0;
defaultFormat.align = TextFormatAlign.LEFT;
defaultFormat.font = "SimSun";
placeFormat = new TextFormat();
placeFormat.letterSpacing = 16;
textField = new TextField();
textField.width = w;
textField.height = h;
textField.type = TextFieldType.INPUT;
textField.defaultTextFormat = defaultFormat;
textField.multiline = true;
textField.wordWrap = true;
textField.mouseWheelEnabled = false;
textField.restrict = "^" + PLACEHOLDER;
textField.filters = [new GlowFilter(0x0, 1, 3, 3, 3)];
textField.maxChars = 200;
textField.addEventListener(Event.SCROLL, onTextScroll);
textField.addEventListener(Event.CHANGE, afterChange);
textField.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
this.addChild(textField);
var mask:Shape = new Shape();
mask.graphics.beginFill(0);
mask.graphics.drawRect(0, 0, w, h);
mask.graphics.endFill();
this.addChild(mask);
mcLayer = new Sprite();
mcLayer.mask = mask;
this.addChild(mcLayer);
dataList = new Vector.<Express>();
}
private function onTextScroll(e:Event):void
{
if(textField.scrollV != scrollV)
{
scrollV = textField.scrollV;
layout();
}
}
private function onKeyDown(e:KeyboardEvent):void
{
begin = textField.selectionBeginIndex;
end = textField.selectionEndIndex;
keyCode = e.keyCode;
}
private function afterChange(e:Event = null):void
{
var $begin:int = begin;
if(begin == end)
{
if(keyCode == Keyboard.BACKSPACE)
{
delExpress(begin - 1);
$begin = (begin > 0) ? begin - 1 : 0;
}
else if(keyCode == Keyboard.DELETE)
{
delExpress(begin);
}
}
else
{
for(var i:int = begin; i < end; i++)
{
delExpress(i);
}
}
updateExpressIndex($begin);
layout();
keyCode = 0;
}
private function layout():void
{
if(textField.length == 0)
{
clear();
return;
}
textField.setTextFormat(defaultFormat, 0, textField.length);
var textStr:String = textField.text;
for(var i:int = 0; i < textStr.length; i++)
{
var char:String = textStr.charAt(i);
if(char == PLACEHOLDER)
{
textField.setTextFormat(placeFormat, i, i + 1);
}
}
while(mcLayer.numChildren > 0)
{
mcLayer.removeChildAt(0);
}
for each(var data:Express in dataList)
{
var rect:Rectangle = textField.getCharBoundaries(data.index);
if(rect != null)
{
data.mc.x = rect.x + 2;
data.mc.y = rect.y - 6;
mcLayer.addChild(data.mc);
}
}
}
public function insertExpression(sign:String):void
{
if(textField.length >= textField.maxChars)
{
return;
}
begin = textField.selectionBeginIndex;
end = textField.selectionEndIndex;
for(var i:int = begin; i < end; i++)
{
delExpress(i);
}
textField.replaceText(begin, end, PLACEHOLDER);
var $i:int = -1;
for(i = 0; i < dataList.length; i++)
{
var data:Express = dataList[i];
if(data.index >= begin)
{
$i = i;
break;
}
}
var mc:MovieClip = getMovieClip(sign);
if($i == -1)
{
dataList.push(new Express(begin, sign, mc));
}
else
{
dataList.splice($i, 0, new Express(begin, sign, mc));
}
updateExpressIndex(begin);
layout();
textField.setSelection(begin + 1, begin + 1);
}
private function updateExpressIndex($begin:int):void
{
var $i:int = -1;
for(var i:int = 0; i < dataList.length; i++)
{
if(dataList[i].index >= $begin)
{
$i = i;
break;
}
}
if($i != -1)
{
var textStr:String = textField.text;
for(i = $begin; i < textStr.length; i++)
{
if(textStr.charAt(i) == PLACEHOLDER)
{
dataList[$i++].index = i;
}
}
}
}
private function getExpress(index:int):Express
{
for each(var data:Express in dataList)
{
if(data.index == index)
{
return data;
}
}
return null;
}
private function delExpress(index:int):void
{
for(var i:int = 0; i < dataList.length; i++)
{
var data:Express = dataList[i];
if(data.index == index)
{
dataList.splice(i, 1);
if(mcLayer.contains(data.mc))
{
mcLayer.removeChild(data.mc);
}
return;
}
}
}
private function getMovieClip(sign:String):MovieClip
{
var $_class:Class = getDefinitionByName(sign) as Class;
var $_item:MovieClip = new $_class();
$_item.mouseChildren = false;
$_item.mouseEnabled = false;
return $_item;
}
public function get srcContent():String
{
var charArr:Array = [];
var textStr:String = textField.text;
for(var i:int = 0; i < textStr.length; i++)
{
var char:String = textStr.charAt(i);
if(char == PLACEHOLDER)
{
var data:Express = getExpress(i);
charArr.push(data.sign);
}
else
{
charArr.push(char);
}
}
return charArr.join("");
}
public function set srcContent(content:String):void
{
clear();
var reg:RegExp = new RegExp("chat_expression_[0-9]{2}", "igm");
var signArr:Array = content.match(reg);
content = content.replace(reg, PLACEHOLDER);
if(content.length > textField.maxChars)
{
content = content.substr(0, textField.maxChars);
}
for(var i:int = 0; i < content.length; i++)
{
var char:String = content.charAt(i);
if(char == PLACEHOLDER)
{
var sign:String = signArr.shift() as String;
var mc:MovieClip = getMovieClip(sign);
dataList.push(new Express(i, sign, mc));
}
}
textField.text = content;
layout();
}
public function clear():void
{
textField.htmlText = "";
begin = end = scrollV = keyCode = 0;
dataList = new Vector.<Express>();
if(mcLayer != null)
{
while(mcLayer.numChildren > 0)
{
mcLayer.removeChildAt(0);
}
}
}
}
}
/*===============================================*/
import flash.display.MovieClip;
class Express
{
public var index:int;
public var sign:String;
public var mc:MovieClip;
public function Express(index:int, sign:String, mc:MovieClip)
{
this.index = index;
this.sign = sign;
this.mc = mc;
}
}