为DataGride单元格添加背景色

 英文原文:《Coloring the Background of Cells》
原文地址: http://weblogs.macromedia.com/pent/archives/2007/02/coloring_the_ba.cfm
原文作者: Peter Ent

译者: Dreamer。
引用地址: http://www.zhuoqun.net/trackback.asp?tbID=405

为单元格添加背景色


Flex中的DataGrid可能是最经常用到的一个控件(除了Label和Button)。一个总是被提出的问题是:“我如何才能给单元格添加上背景色?”我将会回答这个问题,而且还会演示如何为行和列添加背景色。


单元格背景色

你需要一个 itemRenderer来改变特定单元格的背景色。一个itemRenderer既可以应用到一个DataGrid的所有单元格(在标签中定义的时候),也可以应用到某一列的所有单元格(在标签中定义的时候)。

这里有一个给Year这一列得单元格添加了背景色的例子。那些值小于2000的背景为蓝色,而值大于2000的背景为绿色。



改变一个单元格的背景颜色很简单,只需要覆写 updateDisplayList函数来画一个填充矩形就行了。如果你只是想更改一个单元格的背景色,你可以创建一个扩展自mx.controls.Label的itemRenderer。下面的代码就是一个基于Label的itemRenderer,它使得year的值小于2000的单元格的背景色为蓝色,否则为绿色。

程序代码

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
     {
          super.updateDisplayList(unscaledWidth,unscaledHeight);
          var g:Graphics = graphics;
          g.clear();
          g.beginFill( data.year < 2000 ? 0x0000FF : 0x00FF00 );
          g.drawRect(0,0,unscaledWidth,unscaledHeight);
          g.endFill();
     }
   ]]>



列的背景色

如果你想要将某一列中的所有单元格都设置背景色的话,就不需要创建一个itemRenderer了。DataGridColumn类使用了 backgroundColor样式并且将其均一地应用到某一列。实际上,这个背景是一个真正的背景——它和单元格一点关系没有,因为颜色被应用到单元格的下面。

程序代码


Year这一列得背景色将一致为红色。单元格高亮和选中的颜色被应用到背景的上面,所以这些将可以被看到。但是所有的行的颜色,比如DataGird的行的间隔颜色,将不会被看到,这是因为列的backgroundColor是一致的并且在行的颜色的上面。这里有一个为列添加颜色的例子:



列的背景的透明度

很不幸,DataGridColumn并没有使用 backgroundAlpha样式而且颜色总是一致的。但是如果你想要某一列的背景有点透明的话,这点是很容易做到的。

你需要做的第一件事情就是创建一个扩展自DataGrid的类。你既可以创建一个MXML文件(使用DataGrid作为它的根标签)也可以创建一个扩展自DataGrid的ActionScript类。

在你创建的类中,覆写 drawColumnBackground函数来调整透明度:

程序代码
override protected function drawColumnBackground(s:Sprite, columnIndex:int, color:uint,
                                                                            column:DataGridColumn):void
{
      super.drawColumnBackground(s,columnIndex,color,column);

      var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
      if( background ) {
          background.alpha = 0.5;
      }
}


这个函数调用父类的函数来做所有复杂的工作,然后将背景的透明度设置为0.5。现在颜色将会变成半透明的,而且会显示出行的间隔颜色,如下图所示:



为了让这个类变得更容易重用,可以为透明度的值添加一个公有变量。将

程序代码
public var columnBackgroundAlpha:Number = 1;


添加到类中,然后更改函数:

程序代码
backgroundAlpha = columnBackgroundAlpha;


默认的功能就是和DataGrid的功能一样并添加一个一致的背景颜色。如果要使背景透明一点的话:

程序代码


这里假设你将创建的类命名为ColoredBackgroundDataGrid,上面的MXML标签中将透明度设置为0.3会使其更加透明。现在你就有了一个可以重用的类。

行的背景色

除了如何为特定单元格添加背景色的问题,如何为一整行添加背景色可能是最经常被提出的与颜色有关的DataGrid问题了。下面有一个例子,它根据行中的数据为某些行添加了背景色。



为一行添加背景色诗通过覆写 drawRowBackground函数来实现的:

程序代码
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
                                                                      dataIndex:int):void
{
      color = 0xFF0000;
      super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}


不管你传送给函数的颜色值是多少,这个例子中的行将拥有一致的红色背景。当然,我们的目标是根据给定行中的数据来确定是什么颜色。所以函数更改为:

程序代码
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
                                                                       dataIndex:int):void
{
      var dp:ArrayCollection = dataProvider as ArrayCollection;
      var item:Object;
      if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
      if( item != null && item.year < 20000 ) color = 0xFF8800;
      else if( item != null && item.year>= 2000 ) color = 0xFFFFFF;
      else color = 0x00CC00;
      super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
      }


现在颜色是由每一行的year数据域中的值决定的:小于2000的是橙色,大于等于2000的是白色,没有数据项的是绿色。

dataIndex可能比dataProvider中元素的个数的值要大。这是因为行数可能比数据要多。例如,如果你可以看到DataGrid中有十行但是在dataProvider中只有6条记录,就会有4行没有数据,所以数据项可能会是null。

这个例子中的颜色是硬编码的而且由一个特定的数据域所决定,这个数据域同样是硬编码的。你可以向类中添加一个颜色函数使其可以重用,这个函数就像是列的 labelFunction,只不过它会返回一个颜色值而不是一个字符串。为了达到这个目的,要添加另一个公有变量:

程序代码
public var rowColorFunction:Function;


注意这个变量的类型是Function。你可以在 drawRowBackground函数中使用它:

程序代码
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
                                                                       dataIndex:int):void
{
      if( rowColorFunction != null ) {
           var dp:ArrayCollection = dataProvider as ArrayCollection;
           var item:Object;
           if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
           color = rowColorFunction( item, rowIndex, dataIndex, color );
      }
      super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}


现在drawRowBackground将会先查看是否定义了rowColorFunction,如果没有定义, 标准颜色就会被使用。如果定义了rowColorFunction,它就会被调用并传入参数,而且它将会返回一种颜色。

这里有一个例子,结果如上面的图所示:

程序代码


private function rowColorFunction( item:Object, rowIndex:int, dataIndex:int, oldColor:uint ) : uint
{
      if( item == null ) return 0x00CC00; // green are empty rows
      if( item.year< 2000 ) return 0xFFCC00;
      else if( item.year >= 2000 ) return 0xFFFFFF;
}


硬编码的drawRowFunction中使用的逻辑现在被放在主程序的一个函数中。这意味着你可以在任何可以正常使用DataGrid的地方使用ColoredBackgroundDataGrid。

列的高级背景色

一个和rowColorFunction相似的函数可以被应用到列上。这里展示了一种可能:



考虑一下这个columnBackgroundFunction:

程序代码
private function columnGradient(column:DataGridColumn, columnIndex:int, columnShape:Shape,
                                               x:Number, y:Number, width:Number, height:Number) : void
{
      var m:Matrix = new Matrix();
      m.createGradientBox(width,height,0,x,0);
      columnShape.graphics.clear();
      columnShape.graphics.beginGradientFill(GradientType.LINEAR,[0xFFFF00,0xFF0000],[1,1],[0,255],m);
      columnShape.graphics.drawRect(x,y,width,height);
      columnShape.graphics.endFill();
}


这个函数在columnShape(见上图)中画了一个渐变填充的矩形。使用Shape可以允许轻量级的图形作为列的背景;你也可以对行使用同样的技巧。

在DataGrid中对 drawColumnBackground做如下更改:

程序代码
override protected function drawColumnBackground(s:Sprite, columnIndex:int, color:uint,
                                                                           column:DataGridColumn):void
{
      super.drawColumnBackground(s,columnIndex,color,column);

      var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
      if( background ) {
          background.alpha = columnBackgroundAlpha;
      }

      if( columnBackgroundFunction != null ) {
          var columnShape:Shape = Shape(s.getChildByName("lines"+columnIndex.toString()));
          if( columnShape == null ) {
              columnShape = new Shape();
              columnShape.name = "lines"+columnIndex;
              s.addChild(columnShape);
          }
          var lastRow:Object = rowInfo[listItems.length - 1];
          var xx:Number = listItems[0][columnIndex].x;
          var yy:Number = rowInfo[0].y;
          var ww:Number = listItems[0][columnIndex].width;
          if (this.headerHeight > 0)
          yy += rowInfo[0].height;
          var hh:Number = Math.min(lastRow.y + lastRow.height,
                                                  listContent.height - yy);
          columnBackgroundFunction( column, columnIndex, columnShape, xx, yy, ww, hh );
      }
}


正如你所看到的那样,这一个比较复杂,因为必须创建一个Shape,然后添加到Sprite,并且要计算出位置和维数。

总结

虽然DataGrid确实提供了为列添加背景色的功能,但是你不能更改列的背景透明度。你也不需要使用itemRenderer来给某一行(或某一列)添加背景色。你只需要创建一个扩展自DataGrid的类并覆写一些函数,就可以很容易地为行或列(或二者同时)添加背景色,而且你可以使这个类变得更为通用。

当你考虑DataGrid的背景的可能性时,高级的columnBackgroundFunction应该就“可以做到什么程度”给了你一些想法。

你可能感兴趣的:(为DataGride单元格添加背景色)