实现Flex的TextArea文本中关键字的高亮显示
最近做的Flex项目中有一个需求,要求在一个TextArea中输入文本时,当文本中出现SQL关键字(如select,from,where等)时,让这些关键字高亮显示。
经过一个下午的研究最终算是基本上实现了,实现的过程就是一个学习的过程。
前几天机器重装了系统,FlexBuilder要重新装,从官网上下了最新版的FlexBuilder4.6装到机器上,算是尝了鲜,不过感觉和4.5差别并不大。接下来便是一步步实现的过程了。
首先要知道使用TextArea的change事件和TextRange类可以动态更改TextArea部分文本的样式。
--------------------------------------------
mx.controls.TextArea.change
- 当 TextArea 控件中的文本通过用户输入发生更改时分派。使用数据绑定或 ActionScript 代码更改文本时不会引发此事件。
即使 Event.bubbles
属性的默认值是 true
,该控件也会在 Event.bubbles
属性设置为 false
时分派此事件。
- 事件类型:
- flash.events.Event.CHANGE
- 语言版本:
- 3.0
- Player 版本:
- Flash 9, AIR 1.1
- 产品版本:
- Flex 3
--------------------------------------------
mx.controls.textClasses.TextRange
- TextRange 类提供在 Label、Text、TextArea、TextEditor 和 RichTextEditor 控件中选择和格式化文本范围的属性。
--------------------------------------------
mx.controls.textClasses.TextRange.TextRange(owner:UIComponent, modifiesSelection:Boolean=false, beginIndex:int=-1, endIndex:int=-1)
- 创建提供文本控件内容子集的新 TextRange Object,包括格式化信息。
- 参数:
- owner 包含文本的控件。此控件必须包含
textField
属性,或者像 RichTextEditor 控件一样包含textArea
属性。 - modifiesSelection 是否选择范围中的文本。如果将此参数设置为
true
并且不指定与控件中文本相对应的起始或结束索引,则 Flex 将使用当前文本选项的起始或结束索引。如果此参数为true
,您省略了beginIndex
和endIndex
参数,并且不存在任何选项,则 TextRange 对象为空。 - beginIndex 范围中第一个字符从零开始的索引。如果
modifiesSelection
参数为false
,并且您省略此参数或指定了一个负值,则范围将从第一个文本字符开始。 - endIndex 范围中最后一个字符后的位置从零开始的索引。如果
modifiesSelection
参数为false
,并且您省略此参数、指定了一个负值或指定的值超出文本结束范围,则范围将以最后一个文本字符结束。 - 语言版本:
- 3.0
- Player 版本:
- Flash 9, AIR 1.1
- 产品版本:
- Flex 3
关键是如何让指定的关键字样式发生变化。首先想到了正则表达式,但由于对正则表达式并不熟悉,所以采取了截取这些字符串,当出现关键字时,更改关键字的样式。
HighlightKeywordTextArea.mxml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:TextArea xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
change="textArea_change(event)" width="100%" height="100%"
creationComplete="textarea_creationCompleteHandler(event)">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.controls.textClasses.TextRange;
import mx.events.FlexEvent;
[Bindable]
public var keyArray:ArrayCollection;
[Bindable]
public var keyColor:String = "red";
private var tr:TextRange;
private var crlf:String = String.fromCharCode(13);
private var regEx:RegExp = new RegExp(crlf, "g");
private function setKeyColor(num:int,key:String):void
{
var text :String = this.text.toUpperCase().replace(regEx," ");
var str : String = text.substr(num,text.length);
var strArray : Array = str.split(" ");
var keyIndex : int = strArray.indexOf(key);
if(keyIndex!=-1)
{
if(keyIndex!=0)
{
for(var i:int;i< keyIndex;i++)
{
num += (strArray[i] as String).length+1;
}
}
var length:int = key.length;
tr = new TextRange(this, false, num, num + length);
tr.color = keyColor;
num += (length+1);
if(num<text.length)
{
setKeyColor(num,key);
}
}
}
private function addTextRange():void{
try {
tr = new TextRange(this);
tr.color = "black";
tr.textDecoration = "normal";
tr.fontSize = 20;
for each(var key:String in keyArray)
{
setKeyColor(0,key);
}
} catch (err:RangeError) {
}
}
private function textArea_change(evt:Event):void {
addTextRange();
}
protected function textarea_creationCompleteHandler(event:FlexEvent):void
{
addTextRange();
}
]]>
</fx:Script>
</mx:TextArea>
测试主程序HLKeyTaTest.mxml如下:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:components="com.stf.components.*">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
public var keyArray : ArrayCollection = new ArrayCollection(["AS","SELECT","FROM","WHERE","AND","OR"]);
]]>
</fx:Script>
<components:HighlightKeywordTextArea width="500" height="300"
keyColor="red" keyArray="{keyArray}"
text="select name as 姓名 from user_info where id='key'">
</components:HighlightKeywordTextArea>
</s:Application>
测试效果如下:
还存在一些问题:
1.对于很长很长的文本,字符串截取比对效率有点低,有点卡。
2.对于Sql的语的处理还有点弱,比如在引号中如果出现SQL关键字时同样会高亮显示,要是实现SQL编辑中的效果还差的有点远。