auzn的Flex中对文本实现高亮显示的经典教程

By Minidxer | July 28, 2008

下面是继KingnareStyle皮肤制作简介之后,auzn为我们带来的又一篇经典之作。这小子写起教程来简直是“一代宗师”,代码+说明+必要的截图,让人很容易理解。不废话了,下面是正文:

相信大家都看过Gskinner的FLEX/AIR正则验证程序(www.regexr.com),其中匹配字符串的高亮效果很好,移过时还可以显示字符串的详细信息:

clip_image002

这是在匹配的字符串处浮动了一个DisplayObject.

下面我们来尝试做这个效果.

注:
本文英文版本:How to Highlight the Text in Flex(with Full Source Code)

Search-256x256 Demo | DownloadDownload Full Project


如何确定高亮块的位置及高宽是本文的重点。我们可以灵活运用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.

此外,我们再来看幅图片,了解一下Flash文本的结构:clip_image003

“2-pixel gutter”这个要特别注意,若忘记加到位置计算公式中,高亮块会发生2像素的偏移.

现在来考虑下高亮块出现的几个位置(本例文本排列均限定为从左至右):

1.选定文本块在TextField显示区的所有行外

clip_image005

这种情况可以不处理.

2. 选定文本块在TextField显示区内

clip_image007

clip_image008

将选定文本块分划为多个”单行”处理:

首行高亮的区间为beginIndex至首行结束字符;

中间高亮的区间均为行首至行尾;

尾行高亮的区间为行首至endIndex.

3. 选定文本块一部分在显示区内,一部分在显示区外。分两种情况:

1) 起始索引小于显示区第一个字符的索引值,只需在下图中beginIndex至endIndex之间绘制高亮

clip_image010clip_image011

2) 结束索引大于显示区最后一个字符的索引值,只需在下图中beginIndex至endIndex之间绘制高亮

clip_image013 clip_image015

总结如下:

1.获得有效的起始索引及结束索引;

2.如果为单行高亮块,进行单行绘制;

3.如果为多行高亮块,依次进行首行,中间行,尾行的绘制

基本方法确定后,我们在FLEX BUILDER 3中新建项目”HighlightTest”,

clip_image017

新建文件夹com->kingnare->regex

在regex文件夹中新建类HighlightBlock, superclass选择UIMovieClip.

clip_image019

根据前面的思路,我们写出HighlightBlock类:

HighlightBlock.as

简单描述一下HighlightBlock的流程:

通过getValidBeginCharIndex和getValidEndCharIndex方法得到高亮块在显示区的起始及结束索引,之后调用normalDraw绘制高亮块.

在normalDraw方法中,通过getDisLineHeightByLine得到输入索引值所在的行相对于文本注册点的距离,便于计算出高亮块的y坐标.

那么怎么使用这个类呢?

我们的接入参数类型是IUITextField,但TextArea等组件的内部文本均为protected,要通过继承来访问.我们新建文件com->components,在components文件夹中新建BlockTextArea类,superclass选择TextArea:

clip_image021

代码如下:

  1. package com.components
  2. {
  3. import com.kingnare.regex.HighlightBlock;
  4. import flash.display.DisplayObject;
  5. import flash.geom.Point;
  6. import mx.controls.TextArea;
  7.  
  8. public class BlockTextArea extends TextArea
  9. {
  10. private var blockArray:Array;
  11.  
  12. public function BlockTextArea()
  13. {
  14. super();
  15. blockArray = [];
  16. }
  17.  
  18. public function showBlock(beginIndex:int, endIndex:int):void
  19. {
  20. var movieTip:HighlightBlock= new HighlightBlock(this.textField);
  21.  
  22. movieTip.offsetPoint = new Point(0, 0);
  23. movieTip.highLightDraw(beginIndex, endIndex);
  24. movieTip.toolTip = “beginIndex: “+beginIndex+“\nendIndex: “+endIndex+“\nlength: “+(endIndex-beginIndex+1).toString()+“\ntext:\t”+this.textField.text.substring(beginIndex, endIndex+1);
  25. clearBlock();
  26. this.addChild(movieTip);
  27. blockArray.push(movieTip);
  28. }
  29.  
  30. public function clearBlock():void
  31. {
  32. var len:uint = blockArray.length;
  33.  
  34. for(var k:uint=0;k<len;k++)
  35. {
  36. var obj:DisplayObject = blockArray[k]
  37. this.removeChild(obj);
  38. obj = null;
  39. }
  40. blockArray = [];
  41. }
  42. }
  43. }

切换到HighlightTest.mxml,设置主程序高宽为160×420,并添加一个BlockTextArea组件.

之后再加入其他控件:

  1. <components:BlockTextArea id=”lightTextwidth=”400height=”100y=”10x=”10/>
  2. <mx:Button y=”118label=”Show Highlightright=”10/>
  3. <mx:TextInput id=”beginIndexInputx=”92y=”118width=”60/>
  4. <mx:TextInput id=”endIndexInputx=”232y=”118width=”60/>
  5. <mx:Label x=”10y=”121text=”beginIndex:/>
  6. <mx:Label x=”160y=”121text=”endIndex:/>

切换到Design panel:

clip_image023

接下来为主程序加入ActionScript代码.

首先是Application的applicationComplete事件:

  1. <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxmllayout=”absolutexmlns:components=”com.components.*”
  2. width=”420height=”160applicationComplete=”initApp();”>

然后在ActionScript块中编写initApp方法:

  1. private function initApp():void
  2. {
  3. }

在这个方法里我们初始化lightText,beginIndexInput,endIndexInput的文本,并加入lightText的ScrollEvent事件的Listener:

  1. import mx.events.ScrollEvent;
  2. import mx.managers.ToolTipManager;
  3.  
  4. private function initApp():void
  5. {
  6. //ToolTip立即显示
  7. ToolTipManager.showDelay = 0;
  8. lightText.addEventListener(ScrollEvent.SCROLL, scrollEvent);
  9. lightText.htmlText = “Documentation for classes includes syntax, “ +
  10. “<b><font size=’18′>usage</font></b> information, and code samples for methods, “ +
  11. properties, “ +
  12. and event handlers and listeners for those APIs that belong to a specific class “ +
  13. in ActionScript (as opposed to global functions or properties). “ +
  14. The <font size=’24′>classes</font> are listed alphabetically. “ +
  15. “If you are not sure to which class a certain method or property belongs, “ +
  16. “you can look it up in the Index.”;
  17. beginIndexInput.text = “43″;
  18. endIndexInput.text = “300″;
  19. }

再完成”show highlight”按钮的点击方法即高亮显示方法:

  1. private function showBlock():void
  2. {
  3. lightText.showBlock(parseInt(beginIndexInput.text), parseInt(endIndexInput.text));
  4. }

为了及时更新高亮块,我们还要加入一个计时器,当文本发生变化时调用showBlock重绘高亮块.最终主程序代码如下:

  1. <?xml version=”1.0encoding=”utf-8?>
  2. <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxmllayout=”absolutexmlns:components=”com.components.*”
  3. width=”420height=”160applicationComplete=”initApp();”>
  4. <mx:Script>
  5.  
  6. <![CDATA[
  7.  
  8. import mx.events.ScrollEvent;
  9. import mx.managers.ToolTipManager;
  10. private var updateTimer:Timer;
  11.  
  12. private function initApp():void
  13. {
  14. ToolTipManager.showDelay = 0;
  15.  
  16. //timer
  17. updateTimer = new Timer(5, 1);
  18. updateTimer.addEventListener(TimerEvent.TIMER, validate, false, 0, true);
  19. lightText.addEventListener(ScrollEvent.SCROLL, scrollEvent);
  20.  
  21. lightText.htmlText = "Documentation for classes includes syntax, " +
  22. "<b><font size='18'>usage</font></b> information, and code samples for methods, " +
  23. "properties, " +
  24. "and event handlers and listeners for those APIs that belong to a specific class " +
  25. "in ActionScript (as opposed to global functions or properties). " +
  26. "The <font size='24'>classes</font> are listed alphabetically. " +
  27. "If you are not sure to which class a certain method or property belongs, " +
  28. "you can look it up in the Index.";
  29.  
  30. beginIndexInput.text = "43";
  31. endIndexInput.text = "300";
  32. }
  33.  
  34. private function showBlock():void
  35. {
  36. lightText.showBlock(parseInt(beginIndexInput.text), parseInt(endIndexInput.text));
  37. }
  38.  
  39. //validate
  40. private function validate(event:TimerEvent):void
  41. {
  42. showBlock();
  43. }
  44.  
  45. //scrollEvent
  46. private function scrollEvent(event:ScrollEvent):void
  47. {
  48. updateBlock();
  49. }
  50.  
  51. //更新
  52. private function updateBlock():void
  53. {
  54. updateTimer.reset();
  55. updateTimer.start();
  56. }
  57. ]]>
  58.  
  59. </mx:Script>
  60.  
  61. <components:BlockTextArea id=”lightTextwidth=”400height=”100y=”10x=”10/>
  62. <mx:Button y=”118label=”Show Highlightclick=”showBlock();” right=”10/>
  63. <mx:TextInput id=”beginIndexInputx=”92y=”118width=”60/>
  64. <mx:TextInput id=”endIndexInputx=”232y=”118width=”60/>
  65. <mx:Label x=”10y=”121text=”beginIndex:/>
  66. <mx:Label x=”160y=”121text=”endIndex:/>
  67.  
  68. </mx:Application>

然后我们开始测试.点击”Debug”按钮:

clip_image025

点击”Show Highlight”按钮,可以看到绘制出的淡蓝色高亮块:

clip_image027

滚动条滚动时会调用updateBlock方法,在5ms后调用showBlock方法重绘高亮块:

clip_image029

(如果beginIndex小于0或endIndex大于等于文本长度,或者endIndex小于beginIndex均不会显示高亮块)

如果认为这种显示方式过于死板,你可以更改HighlightBlock类的drawBlock方法,或者继承HighlightBlock类重写drawBlock方法,做出诸如波浪线,下划线等效果.

如果将HighlightBlock类的_textField类型由IUITextField更换为TextField并做相关改动,HighlightBlock类也可用于ActionScript Project.

OK,HighlightBlock的编写及使用方法已经介绍完毕.

Cheers.

Topics: Flex | Tags: , , , , , ,

Search Posts

Archives

Sponsored Ads