flex-DataGrid列太多,横向滚动条特别卡的解决方法

做项目的时候遇到了DataGrid列太多,导致横向滚动条特别卡,界面反应非常慢。

在网上找了一下解决方法,最终只找到这一个

http://blogs.adobe.com/aharui/2008/11/faster_datagrid_horizontal_scr.html 

但是这里面的大师提供的例子代码是有问题的,不过细心的人仔细看评论有人修复了这些bug。

我在这里把修复后的代码贴出来,方便大家查看



package components
{
	import flash.geom.Point;
	
	import mx.collections.CursorBookmark;
	import mx.controls.DataGrid;
	import mx.controls.dataGridClasses.DataGridColumn;
	import mx.controls.listClasses.IListItemRenderer;
	import mx.core.mx_internal;

	use namespace mx_internal;
	
	public class BetterDataGrid extends DataGrid
	{
		/** 
		 *  remember the number of columns in case it changes
		 */
		private var lastNumberOfColumns:int;
		
		/**
		 *  a flag as to whether we can use the optimized scrolling
		 */
		private var canUseScrollH:Boolean;
		
		/**
		 *  when the horizontal scrollbar is changed it will eventually set horizontalScrollPosition
		 *  This value can be set programmatically as well.
		 */
		override public function set horizontalScrollPosition(value:Number):void
		{
			// remember the setting of this flag.  We will tweak it in order to keep DataGrid from
			// doing its default horizontal scroll which essentially refreshes every renderer
			var lastItemsSizeChanged:Boolean = itemsSizeChanged;
			
			// remember the current number of visible columns.  This can get changed by DataGrid
			// as it recomputes the visible columns when horizontally scrolled.
			lastNumberOfColumns = visibleColumns.length;
			
			// reset the flag for whether we use our new technique
			canUseScrollH = false;
			
			// call the base class.  If we can use our technique we'll trip that flag
			super.horizontalScrollPosition = value;
			
			// if the flag got tripped run our new technique
			if (canUseScrollH){
				scrollLeftOrRight();
				configureScrollBars();				
			}
			// reset the flag
			itemsSizeChanged = lastItemsSizeChanged;
			
		}
		
		// remember the parameters to scrollHorizontally to be used in our new technique
		private var pos:int;
		private var deltaPos:int;
		private var scrollUp:Boolean;
		
		// override this method.  If it gets called that means we can use the new technique
		override protected function scrollHorizontally(pos:int, deltaPos:int, scrollUp:Boolean):void
		{
			// just remember the args for later;
			this.pos = pos;
			this.deltaPos = deltaPos;
			this.scrollUp = scrollUp;
			if (deltaPos < visibleColumns.length)
			{
				canUseScrollH = true;
				
				// need this to prevent DG from asking for a full refresh
				itemsSizeChanged = true;
			}
		}
		
		/**
		 *  The new technique does roughly what we do vertically.  We shift the renderers on screen and in the
		 *  listItems array and only make the new renderers.
		 *  Because we can't get internal access to the header, we fully refresh it, but that's only one row
		 *  of renderers.  There's significant gains to be made by not fully refreshing the every row of columns
		 *
		 *  Key thing to note here is that visibleColumns has been updated, but the renderer array has not
		 *  That's why we don't do this in scrollHorizontally as the visibleColumns hasn't been updated yet
		 *  But because of that, sometimes we have to measure old renderers, and sometimes we measure the columns
		 */
		private function scrollLeftOrRight():void
		{
			// trace("scrollHorizontally " + pos);
			var i:int;
			var j:int;
			
			var numCols:int;
			var uid:String;
			
			var curX:Number;
			
			var rowCount:int = rowInfo.length;
			var columnCount:int = listItems[0].length;
			var cursorPos:CursorBookmark;
			
			var moveBlockDistance:Number = 0;
			
			var c:DataGridColumn;
			var item:IListItemRenderer;
			var itemSize:Point;
			var data:Object;
			
			var xx:Number;
			var yy:Number;
			
			if (scrollUp) // actually, rows move left
			{
				// determine how many columns we're discarding
				var discardCols:int = deltaPos;
				
				// measure how far we have to move by measuring the width of the columns we
				// are discarding
				
				moveBlockDistance = sumColumnWidths(discardCols, true);
				// trace("moveBlockDistance = " + moveBlockDistance);
				
				//  shift rows leftward and toss the ones going away
				for (i = 0; i < rowCount; i++)
				{
					numCols = listItems[i].length;
					if(numCols == 0) //empty row
						continue;
					// move the positions of the row, the item renderers for the row,
					// and the indicators for the row
					moveRowHorizontally(i, discardCols, -moveBlockDistance, numCols);
					// move the renderers within the array of rows
					shiftColumns(i, discardCols, numCols);
					truncateRowArray(i);
				}
				
				// generate replacement columns
				cursorPos = iterator.bookmark;
				
				var firstNewColumn:int = lastNumberOfColumns - deltaPos;
				curX = listItems[0][firstNewColumn - 1].x + listItems[0][firstNewColumn - 1].width;
				
				
				for (i = 0; i < rowCount; i++)
				{
					if(iterator == null || iterator.afterLast || !iteratorValid)
						continue;
					data = iterator.current;
					iterator.moveNext();
					uid = itemToUID(data);
					
					xx = curX;
					yy = rowInfo[i].y;
					for (j = firstNewColumn; j < visibleColumns.length; j++)
					{
						
						c = visibleColumns[j];
						item = setupColumnItemRenderer(c, listContent, i, j, data, uid);
						itemSize = layoutColumnItemRenderer(c, item, xx, yy);
						xx += itemSize.x;
					}
					// toss excess columns
					while (listItems[i].length > visibleColumns.length)
					{
						addToFreeItemRenderers(listItems[i].pop());
					}
				}
				
				iterator.seek(cursorPos, 0);           
			}
			else
			{
				numCols = listItems[0].length;
				if(deltaPos > visibleColumns.length)
					deltaPos = visibleColumns.length;
				moveBlockDistance = sumColumnWidths(deltaPos, false);
				
				// shift the renderers and slots in array
				for (i = 0; i < rowCount; i++)
				{
					numCols = listItems[i].length;
					if(numCols == 0)
						continue;
					
					moveRowHorizontally(i, 0, moveBlockDistance, numCols);
					// we add placeholders at the front for new renderers
					addColumnPlaceHolders(i, deltaPos);
					
				}
				
				cursorPos = iterator.bookmark;
				
				for (i = 0; i < rowCount; i++)
				{
					if(iterator == null || iterator.afterLast || !iteratorValid)
						continue;
					data = iterator.current;
					iterator.moveNext();
					uid = itemToUID(data);
					
					xx = 0;
					yy = rowInfo[i].y;
					for (j = 0; j < deltaPos; j++)
					{
						c = visibleColumns[j];
						item = setupColumnItemRenderer(c, listContent, i, j, data, uid);
						itemSize = layoutColumnItemRenderer(c, item, xx, yy);
						xx += itemSize.x;
					}
					// toss excess columns
					while (listItems[i].length > visibleColumns.length)
					{
						addToFreeItemRenderers(listItems[i].pop());
					}
				}
				
				iterator.seek(cursorPos, 0);           
			}
			
			// force update the header
			header.headerItemsChanged = true;
			header.visibleColumns = visibleColumns;
			header.invalidateDisplayList();
			header.validateNow();
			
			// draw column lines and backgrounds
			drawLinesAndColumnBackgrounds();
		}        
		
		// if moving left, add up old renderers
		// if moving right, add up new columns
		private function sumColumnWidths(num:int, left:Boolean):Number
		{
			var i:int;
			var value:Number = 0;
			if (left)
			{
				for (i = 0; i < num; i++)
				{
					value += listItems[0][i].width;
				}
			}
			else
				for (i = 0; i < num; i++)
				{
					value += visibleColumns[i].width;
				}
			
			return value;
		}
		
		// shift position of renderers on screen
		private function moveRowHorizontally(rowIndex:int, start:int, distance:Number, end:int):void
		{
			for (;start < end; start++)
				listItems[rowIndex][start].x += distance;
		}
		
		// shift renderer assignments in listItems array
		private function shiftColumns(rowIndex:int, shift:int, numCols:int):void
		{
			var item:IListItemRenderer;
			var uid:String = itemToUID(listItems[rowIndex][0].data);
			for (var i:int = 0; i < shift; i++)
			{
				//rebuild the listContent.visibleData map entry
				listContent.visibleData[uid] = listItems[rowIndex][0];
				item = listItems[rowIndex].shift();
				addToFreeItemRenderers(item);
			}
		}
		
		// add places in front of row for new columns
		private function addColumnPlaceHolders(rowIndex:int, count:int):void
		{
			for (var i:int = 0; i < count; i++)
			{
				listItems[rowIndex].unshift(null);
			}
		}
		
		// remove excess columns
		private function truncateRowArray(rowIndex:int):void
		{
			while (listItems[rowIndex].length > visibleColumns.length)
			{
				var item:IListItemRenderer;
				{
					item = listItems[rowIndex].pop();
					addToFreeItemRenderers(item);
				}
			}
		}
	}
}

这下拖动速度还是比较快了,希望能帮助到正在苦恼这个问题的人

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值