Flex中文本高亮显示
HighlightBlock .as:
package com.kingnare.regex
{
?import flash.display.Shape;
?import flash.geom.Point;
?import flash.geom.Rectangle;
?import flash.text.TextLineMetrics;
?
?import mx.core.IUITextField;
?import mx.flash.UIMovieClip;
?
?/**
? *
? * 根据IUITextField文本的起始和结束字符索引绘制图形并显示在文本选择区。
? * <br/><br/>
? * E-mail:auzn1982[at]gmail.com
? * @author auzn at Kingnare.com
? *
? */?
?
?public class HighlightBlock extends UIMovieClip
?{
??/**
?? * 目标文本
?? */??
??private var _textField:IUITextField;
??/**
?? * 偏移点,调整绘图Shape与目标文本的位置差距
?? */??
??private var _offsetPoint:Point;
??
??
??/**
?? *
?? * HighlightBlock 构造方法
?? * @param textField 目标文本
?? *
?? */??
??public function HighlightBlock(textField:IUITextField)
??{
???super();
???_offsetPoint = new Point(0, 0);
???_textField = textField;
??}
??
??/**
?? *
?? * 绘制高亮块
?? * 根据起始字符索引及结束字符索引获得有效的绘制范围
?? * 如果绘制范围合法,将绘制高亮块。
?? *
?? * @param beginIndex 目标文本中起始字符索引
?? * @param endIndex 目标文本中结束字符索引
?? *
?? * @see #getValidBeginCharIndex()
?? * @see #getValidEndCharIndex()
?? */??
??public function highLightDraw(beginIndex:Number, endIndex:Number):void
??{
???var beginValidIndex:Number = getValidBeginCharIndex(beginIndex);
???var endValidIndex:Number = getValidEndCharIndex(endIndex);
???if(beginValidIndex == -1 || endValidIndex == -2)
???{
????//throw new Error("Invalid value");
????return;
???}
???if(beginValidIndex<=endValidIndex)
???{
????normalDraw(beginValidIndex, endValidIndex);
???}
??}
??
??/**
?? *
?? * 根据起始字符索引及结束字符索引绘制,单行/多行。
?? *
?? * @param beginIndex 目标文本中起始字符索引
?? * @param endIndex 目标文本中结束字符索引
?? *
?? * @see #drawSingleLine()
?? */??
??private function normalDraw(beginIndex:Number, endIndex:Number):void
??{
???//trace("Normal Draw");
???var beginLineIndex:Number = _textField.getLineIndexOfChar(beginIndex);
???var endLineIndex:Number = _textField.getLineIndexOfChar(endIndex);
???var disLineNum:Number = endLineIndex-beginLineIndex;
???//1行
???if(disLineNum<1)
???{
????drawSingleLine(beginIndex, endIndex);
????return;
???}
???//大于或等于一行
???//首行
???drawSingleLine(beginIndex, _textField.getLineOffset(beginLineIndex)+_textField.getLineLength(beginLineIndex)-1);
???//中间行
???for(var i:Number=beginLineIndex+1;i<endLineIndex;i++)
???{
????drawSingleLine(_textField.getLineOffset(i), _textField.getLineOffset(i)+_textField.getLineLength(i)-1);
???}
???//尾行
???drawSingleLine(_textField.getLineOffset(endLineIndex), endIndex);
??}
??
??/**
?? *
?? * 根据起始字符索引及结束字符索引绘制,单行。
?? *
?? * @param beginIndex 目标文本中起始字符索引
?? * @param endIndex 目标文本中结束字符索引
?? *
?? * @throws Error? 起始和结束索引跨多个行。
?? */??
??private function drawSingleLine(beginIndex:Number, endIndex:Number):void
??{
???endIndex--;
???var beginLineIndex:Number = _textField.getLineIndexOfChar(beginIndex);
???var endLineIndex:Number = _textField.getLineIndexOfChar(endIndex);
???var disLineNum:Number = endLineIndex-beginLineIndex;
???//1行
???if(disLineNum<1)
???{
????var frame:Rectangle = _textField.getCharBoundaries(beginIndex);
????frame.y = getDisLineHeightByLine(beginLineIndex);
????frame.width = _textField.getCharBoundaries(endIndex).x - _textField.getCharBoundaries(beginIndex).x+_textField.getCharBoundaries(endIndex).width;
????showBlock(frame);
???}
???else
???{
????throw new Error("drawSingleLine:disLineNum >= 1.");
???}
??}
??
??/**
?? *
?? * 通过行索引查找相对显示行的总高度
?? * @param lineIndex 行索引
?? * @return 相对高度
?? *
?? */??
??public function getDisLineHeightByLine(lineIndex:Number):Number
??{
???
???var addHeight:Number = 2;
???for(var i:Number=_textField.scrollV-1;i<lineIndex;i++)
???{
????var showLine:TextLineMetrics = _textField.getLineMetrics(i);
????addHeight += showLine.height;
???}
???return addHeight;
??}
??
??/**
?? *
?? * 通过字符索引查找相对显示行的总高度
?? * @param charIndex 字符索引
?? * @return 相对高度
?? *
?? */??
??public function getDisLineHeightByChar(charIndex:Number):Number
??{
???var line:Number = _textField.getLineIndexOfChar(charIndex);
???return getDisLineHeightByLine(line);
??}
??
??/**
?? *
?? * 获取当前有效的起始字符索引
?? * @param beginIndex 起始字符索引
?? * @return 有效的索引值。若索引值超出文本范围,返回-1
?? *
?? */??
??public function getValidBeginCharIndex(beginIndex:Number):Number
??{
???var len:Number = _textField.text.length;
???if(beginIndex<0 || beginIndex>len-1)
???{
????return -1;
???}
???var line:Number = _textField.getLineIndexOfChar(beginIndex);
???
???if(line<_textField.scrollV-1)
???{
????line = _textField.scrollV-1;
????return _textField.getLineOffset(line);
???}
???return beginIndex;
??}
??
??
??/**
?? *
?? * 获取当前有效的结束字符索引
?? * @param endIndex 结束字符索引
?? * @return 有效的索引值。若索引值超出文本范围,返回-2
?? *
?? */??
??public function getValidEndCharIndex(endIndex:Number):Number
??{
???var len:Number = _textField.text.length;
???if(endIndex<0 || endIndex>len-1)
???{
????return -2;
???}
???var line:Number = _textField.getLineIndexOfChar(endIndex);
???if(line>_textField.bottomScrollV-1)
???{
????line = _textField.bottomScrollV-1;
????return _textField.getLineOffset(line)+_textField.getLineLength(line)-1;
???}
???return endIndex;
??}
??
??
??/**
?? *
?? * 绘制并加到显示容器中
?? * @param pos
?? *
?? */??
??private function showBlock(pos:Rectangle):void
??{
???var rect:Rectangle = new Rectangle(_offsetPoint.x+pos.x, _offsetPoint.y+pos.y, pos.width, pos.height);
???this.addChild(drawBlock(rect));
??}
??
??
??/**
?? *
?? * 绘制
?? * @param rect
?? * @return 绘制图形
?? *
?? */??
??protected function drawBlock(rect:Rectangle):Shape
??{
???var block:Shape = new Shape();
???block.graphics.clear();
???block.graphics.beginFill(0x0099CC, .35);
???block.graphics.lineStyle(1, 0x0099CC, .65, true);
???block.graphics.drawRoundRectComplex(rect.x, rect.y, rect.width, rect.height, 0, 0, 0, 0);
???block.graphics.endFill();
???return block;
??}
??
??/**
?? *
?? * 目标文本组件
?? * @param tf 目标文本
?? *
?? */??
??public function set textField(tf:IUITextField):void
??{
???_textField = tf;
??}
??
??/**
?? *
?? * @private
?? * @return 目标文本
?? *
?? */??
??public function get textField():IUITextField
??{
???return _textField;
??}
??
??/**
?? *
?? * 偏移点
?? * @param op 偏移点
?? *
?? */??
??public function set offsetPoint(op:Point):void
??{
???_offsetPoint = op;
??}
??
??/**
?? *
?? * @private
?? * @return 偏移点
?? *
?? */??
??public function get offsetPoint():Point
??{
???return _offsetPoint;
??}
?}
}
BlockTextArea.as:
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 = [];
??}
?}
}
Test.mxml:
<?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>
下面是源码包!!!转自:http://blog.minidx.com/2008/07/28/1178.html
?