auzn的Flex中对文本实现高亮显示的经典教程
By Minidxer | July 28, 2008
下面是继KingnareStyle皮肤制作简介之后,auzn为我们带来的又一篇经典之作。这小子写起教程来简直是“一代宗师”,代码+说明+必要的截图,让人很容易理解。不废话了,下面是正文:
相信大家都看过Gskinner的FLEX/AIR正则验证程序(www.regexr.com),其中匹配字符串的高亮效果很好,移过时还可以显示字符串的详细信息:
这是在匹配的字符串处浮动了一个DisplayObject.
下面我们来尝试做这个效果.
注:
本文英文版本:How to Highlight the Text in Flex(with Full Source Code)
如何确定高亮块的位置及高宽是本文的重点。我们可以灵活运用TextField类的几个方法得到相关的数值:
1.getLineIndexOfChar(charIndex:int):int
Returns the zero-based index value of the line containing the character specified by the charIndex parameter.
2.getLineOffset(lineIndex:int):int
Returns the character index of the first character in the line that the lineIndex parameter specifies.
3.getLineLength(lineIndex:int):int
Returns the number of characters in a specific text line.
4.getLineIndexOfChar(charIndex:int):int
Returns the zero-based index value of the line containing the character specified by the charIndex parameter.
5.getCharBoundaries(charIndex:int):Rectangle
Returns a rectangle that is the bounding box of the character.
“2-pixel gutter”这个要特别注意,若忘记加到位置计算公式中,高亮块会发生2像素的偏移.
现在来考虑下高亮块出现的几个位置(本例文本排列均限定为从左至右):
1.选定文本块在TextField显示区的所有行外
这种情况可以不处理.
2. 选定文本块在TextField显示区内
将选定文本块分划为多个”单行”处理:
首行高亮的区间为beginIndex至首行结束字符;
中间高亮的区间均为行首至行尾;
尾行高亮的区间为行首至endIndex.
3. 选定文本块一部分在显示区内,一部分在显示区外。分两种情况:
1) 起始索引小于显示区第一个字符的索引值,只需在下图中beginIndex至endIndex之间绘制高亮
2) 结束索引大于显示区最后一个字符的索引值,只需在下图中beginIndex至endIndex之间绘制高亮
总结如下:
1.获得有效的起始索引及结束索引;
2.如果为单行高亮块,进行单行绘制;
3.如果为多行高亮块,依次进行首行,中间行,尾行的绘制
基本方法确定后,我们在FLEX BUILDER 3中新建项目”HighlightTest”,
新建文件夹com->kingnare->regex
在regex文件夹中新建类HighlightBlock, superclass选择UIMovieClip.
根据前面的思路,我们写出HighlightBlock类:
简单描述一下HighlightBlock的流程:
通过getValidBeginCharIndex和getValidEndCharIndex方法得到高亮块在显示区的起始及结束索引,之后调用normalDraw绘制高亮块.
在normalDraw方法中,通过getDisLineHeightByLine得到输入索引值所在的行相对于文本注册点的距离,便于计算出高亮块的y坐标.
那么怎么使用这个类呢?
我们的接入参数类型是IUITextField,但TextArea等组件的内部文本均为protected,要通过继承来访问.我们新建文件com->components,在components文件夹中新建BlockTextArea类,superclass选择TextArea:
代码如下:
- package com.components
- {
- import com.kingnare.regex.HighlightBlock;
- import flash.display.DisplayObject;
- import flash.geom.Point;
- import mx.controls.TextArea;
- public class BlockTextArea extends TextArea
- {
- private var blockArray:Array;
- public function BlockTextArea()
- {
- super();
- blockArray = [];
- }
- public function showBlock(beginIndex:int, endIndex:int):void
- {
- var movieTip:HighlightBlock= new HighlightBlock(this.textField);
- movieTip.offsetPoint = new Point(0, 0);
- movieTip.highLightDraw(beginIndex, endIndex);
- movieTip.toolTip = “beginIndex: “+beginIndex+“\nendIndex: “+endIndex+“\nlength: “+(endIndex-beginIndex+1).toString()+“\ntext:\t”+this.textField.text.substring(beginIndex, endIndex+1);
- clearBlock();
- this.addChild(movieTip);
- blockArray.push(movieTip);
- }
- public function clearBlock():void
- {
- var len:uint = blockArray.length;
- for(var k:uint=0;k<len;k++)
- {
- var obj:DisplayObject = blockArray[k]
- this.removeChild(obj);
- obj = null;
- }
- blockArray = [];
- }
- }
- }
切换到HighlightTest.mxml,设置主程序高宽为160×420,并添加一个BlockTextArea组件.
之后再加入其他控件:
- <components:BlockTextArea id=”lightText” width=”400″ height=”100″ y=”10″ x=”10″/>
- <mx:Button y=”118″ label=”Show Highlight” right=”10″/>
- <mx:TextInput id=”beginIndexInput” x=”92″ y=”118″ width=”60″/>
- <mx:TextInput id=”endIndexInput” x=”232″ y=”118″ width=”60″/>
- <mx:Label x=”10″ y=”121″ text=”beginIndex:”/>
- <mx:Label x=”160″ y=”121″ text=”endIndex:”/>
切换到Design panel:
接下来为主程序加入ActionScript代码.
首先是Application的applicationComplete事件:
- <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” xmlns:components=”com.components.*”
- width=”420″ height=”160″ applicationComplete=”initApp();”>
然后在ActionScript块中编写initApp方法:
- private function initApp():void
- {
- }
在这个方法里我们初始化lightText,beginIndexInput,endIndexInput的文本,并加入lightText的ScrollEvent事件的Listener:
- import mx.events.ScrollEvent;
- import mx.managers.ToolTipManager;
- private function initApp():void
- {
- //ToolTip立即显示
- ToolTipManager.showDelay = 0;
- lightText.addEventListener(ScrollEvent.SCROLL, scrollEvent);
- lightText.htmlText = “Documentation for classes includes syntax, “ +
- “<b><font size=’18′>usage</font></b> information, and code samples for methods, “ +
- “properties, “ +
- “and event handlers and listeners for those APIs that belong to a specific class “ +
- “in ActionScript (as opposed to global functions or properties). “ +
- “The <font size=’24′>classes</font> are listed alphabetically. “ +
- “If you are not sure to which class a certain method or property belongs, “ +
- “you can look it up in the Index.”;
- beginIndexInput.text = “43″;
- endIndexInput.text = “300″;
- }
再完成”show highlight”按钮的点击方法即高亮显示方法:
- private function showBlock():void
- {
- lightText.showBlock(parseInt(beginIndexInput.text), parseInt(endIndexInput.text));
- }
为了及时更新高亮块,我们还要加入一个计时器,当文本发生变化时调用showBlock重绘高亮块.最终主程序代码如下:
- <?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” xmlns:components=”com.components.*”
- width=”420″ height=”160″ applicationComplete=”initApp();”>
- <mx:Script>
- <![CDATA[
- import mx.events.ScrollEvent;
- import mx.managers.ToolTipManager;
- private var updateTimer:Timer;
- private function initApp():void
- {
- ToolTipManager.showDelay = 0;
- //timer
- updateTimer = new Timer(5, 1);
- updateTimer.addEventListener(TimerEvent.TIMER, validate, false, 0, true);
- lightText.addEventListener(ScrollEvent.SCROLL, scrollEvent);
- lightText.htmlText = "Documentation for classes includes syntax, " +
- "<b><font size='18'>usage</font></b> information, and code samples for methods, " +
- "properties, " +
- "and event handlers and listeners for those APIs that belong to a specific class " +
- "in ActionScript (as opposed to global functions or properties). " +
- "The <font size='24'>classes</font> are listed alphabetically. " +
- "If you are not sure to which class a certain method or property belongs, " +
- "you can look it up in the Index.";
- beginIndexInput.text = "43";
- endIndexInput.text = "300";
- }
- private function showBlock():void
- {
- lightText.showBlock(parseInt(beginIndexInput.text), parseInt(endIndexInput.text));
- }
- //validate
- private function validate(event:TimerEvent):void
- {
- showBlock();
- }
- //scrollEvent
- private function scrollEvent(event:ScrollEvent):void
- {
- updateBlock();
- }
- //更新
- private function updateBlock():void
- {
- updateTimer.reset();
- updateTimer.start();
- }
- ]]>
- </mx:Script>
- <components:BlockTextArea id=”lightText” width=”400″ height=”100″ y=”10″ x=”10″/>
- <mx:Button y=”118″ label=”Show Highlight” click=”showBlock();” right=”10″/>
- <mx:TextInput id=”beginIndexInput” x=”92″ y=”118″ width=”60″/>
- <mx:TextInput id=”endIndexInput” x=”232″ y=”118″ width=”60″/>
- <mx:Label x=”10″ y=”121″ text=”beginIndex:”/>
- <mx:Label x=”160″ y=”121″ text=”endIndex:”/>
- </mx:Application>
然后我们开始测试.点击”Debug”按钮:
点击”Show Highlight”按钮,可以看到绘制出的淡蓝色高亮块:
滚动条滚动时会调用updateBlock方法,在5ms后调用showBlock方法重绘高亮块:
(如果beginIndex小于0或endIndex大于等于文本长度,或者endIndex小于beginIndex均不会显示高亮块)
如果认为这种显示方式过于死板,你可以更改HighlightBlock类的drawBlock方法,或者继承HighlightBlock类重写drawBlock方法,做出诸如波浪线,下划线等效果.
如果将HighlightBlock类的_textField类型由IUITextField更换为TextField并做相关改动,HighlightBlock类也可用于ActionScript Project.
OK,HighlightBlock的编写及使用方法已经介绍完毕.
Cheers.
Topics:
Flex |
No Comments » |
Tags: AIR, auzn, DisplayObject, Gskinner, regexr, 字符串, 高亮