我需要/想要在我的某些数据网格的标题中添加s:TextInput
,以便为表格提供过滤功能(其思路是:“在输入字段中键入文本,按Enter键,数据网格过滤”)。目前我正在使用s:TextInput
处理HeaderRenderer,但也会有使用s:CheckBoxes
和s:DropDownLists
的渲染器。
我正在尝试使用自定义RendererSkin,但我遇到了几个问题:
s:TextInput
(虽然鼠标悬停时光标会变为工字梁,但控件会获得焦点边框。)s:TextInputs
似乎“泄漏”了某种白色矩形(见截图)。verticalAlign="bottom"
似乎没有像我认为的那样工作。到目前为止,我的HeaderRenderer看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<s:DefaultGridHeaderRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"
mouseEnabledWhereTransparent="true">
<fx:Script>
<![CDATA[
import spark.components.DataGrid;
import spark.components.GridColumnHeaderGroup;
import spark.components.TextInput;
import spark.components.gridClasses.GridColumn;
import spark.components.gridClasses.IGridVisualElement;
import spark.primitives.supportClasses.GraphicElement;
import mx.collections.ArrayCollection;
import mx.core.IFactory;
import mx.core.IVisualElement;
import mx.events.FlexEvent;
// chrome color constants and variables
private static const DEFAULT_COLOR_VALUE:uint = 0xCC;
private static const DEFAULT_COLOR:uint = 0xCCCCCC;
private static const DEFAULT_SYMBOL_COLOR:uint = 0x000000;
private static var colorTransform:ColorTransform = new ColorTransform();
private function dispatchChangeEvent(type:String):void {
if (hasEventListener(type))
dispatchEvent(new Event(type));
}
// ----------------------------------
// maxDisplayedLines
// ----------------------------------
private var _maxDisplayedLines:int = 1;
[Bindable("maxDisplayedLinesChanged")]
[Inspectable(minValue="-1")]
override public function get maxDisplayedLines():int {
return _maxDisplayedLines;
}
/**
* @private
*/
override public function set maxDisplayedLines(value:int):void {
if (value == _maxDisplayedLines)
return;
_maxDisplayedLines = value;
if (labelDisplay)
labelDisplay.maxDisplayedLines = value;
invalidateSize();
invalidateDisplayList();
dispatchChangeEvent("maxDisplayedLinesChanged");
}
// ----------------------------------
// sortIndicator
// ----------------------------------
private var _sortIndicator:IFactory;
private var sortIndicatorInstance:IVisualElement;
[Bindable("sortIndicatorChanged")]
override public function get sortIndicator():IFactory {
return (_sortIndicator) ? _sortIndicator : defaultSortIndicator;
}
override public function set sortIndicator(value:IFactory):void {
if (_sortIndicator == value)
return;
_sortIndicator = value;
if (sortIndicatorInstance) {
sortIndicatorGroup.includeInLayout = false;
sortIndicatorGroup.removeElement(sortIndicatorInstance);
sortIndicatorInstance = null;
}
invalidateDisplayList();
dispatchChangeEvent("sortIndicatorChanged");
}
override public function prepare(hasBeenRecycled:Boolean):void {
super.prepare(hasBeenRecycled);
if (labelDisplay && labelDisplayGroup && (labelDisplay.parent != labelDisplayGroup)) {
labelDisplayGroup.removeAllElements();
labelDisplayGroup.addElement(labelDisplay);
}
if (labelDisplayGroup.numChildren < 2) {
var filter:TextInput = new TextInput();
filter.percentWidth = 100;
filter.addEventListener(FlexEvent.ENTER, filter_handleEnter);
filterDisplayGroup.addElement(filter);
}
const column:GridColumn = this.column;
if (sortIndicator && column && column.grid && column.grid.dataGrid && column.grid.dataGrid.columnHeaderGroup) {
const dataGrid:DataGrid = column.grid.dataGrid;
const columnHeaderGroup:GridColumnHeaderGroup = dataGrid.columnHeaderGroup;
if (columnHeaderGroup.isSortIndicatorVisible(column.columnIndex)) {
if (!sortIndicatorInstance) {
sortIndicatorInstance = sortIndicator.newInstance();
sortIndicatorGroup.addElement(sortIndicatorInstance);
chromeColorChanged = true;
invalidateDisplayList();
}
// Initialize sortIndicator
sortIndicatorInstance.visible = true;
const gridVisualElement:IGridVisualElement = sortIndicatorInstance as IGridVisualElement;
if (gridVisualElement)
gridVisualElement.prepareGridVisualElement(column.grid, -1, column.columnIndex);
sortIndicatorGroup.includeInLayout = true;
sortIndicatorGroup.scaleY = (column.sortDescending) ? 1 : -1;
} else {
if (sortIndicatorInstance) {
sortIndicatorGroup.removeElement(sortIndicatorInstance);
sortIndicatorGroup.includeInLayout = false;
sortIndicatorInstance = null;
}
}
}
}
private var chromeColorChanged:Boolean = false;
private var colorized:Boolean = false;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
// Apply chrome color
if (chromeColorChanged) {
var chromeColor:uint = getStyle("chromeColor");
if (chromeColor != DEFAULT_COLOR || colorized) {
colorTransform.redOffset = ((chromeColor & (0xFF << 16)) >> 16) - DEFAULT_COLOR_VALUE;
colorTransform.greenOffset = ((chromeColor & (0xFF << 8)) >> 8) - DEFAULT_COLOR_VALUE;
colorTransform.blueOffset = (chromeColor & 0xFF) - DEFAULT_COLOR_VALUE;
colorTransform.alphaMultiplier = alpha;
transform.colorTransform = colorTransform;
var exclusions:Array = [labelDisplay, sortIndicatorInstance];
// Apply inverse colorizing to exclusions
if (exclusions && exclusions.length > 0) {
colorTransform.redOffset = -colorTransform.redOffset;
colorTransform.greenOffset = -colorTransform.greenOffset;
colorTransform.blueOffset = -colorTransform.blueOffset;
for (var i:int = 0; i < exclusions.length; i++) {
var exclusionObject:Object = exclusions[i];
if (exclusionObject && (exclusionObject is DisplayObject || exclusionObject is GraphicElement)) {
colorTransform.alphaMultiplier = exclusionObject.alpha;
exclusionObject.transform.colorTransform = colorTransform;
}
}
}
colorized = true;
}
chromeColorChanged = false;
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
override public function styleChanged(styleProp:String):void {
var allStyles:Boolean = !styleProp || styleProp == "styleName";
super.styleChanged(styleProp);
if (allStyles || styleProp == "chromeColor") {
chromeColorChanged = true;
invalidateDisplayList();
}
}
private function filter_handleEnter(event:FlexEvent):void {
if (this.grid.dataProvider is ArrayCollection) {
(this.grid.dataProvider as ArrayCollection).refresh();
}
}
]]>
</fx:Script>
<fx:Declarations>
<fx:Component id="defaultSortIndicator">
<s:Path data="M 3.5 7.0 L 0.0 0.0 L 7.0 0.0 L 3.5 7.0" implements="spark.components.gridClasses.IGridVisualElement">
<fx:Script>
<![CDATA[
import spark.components.DataGrid;
import spark.components.Grid;
public function prepareGridVisualElement(grid:Grid, rowIndex:int, columnIndex:int):void {
const dataGrid:DataGrid = grid.dataGrid;
if (!dataGrid)
return;
const color:uint = dataGrid.getStyle("symbolColor");
arrowFill1.color = color;
arrowFill2.color = color;
}
]]>
</fx:Script>
<s:fill>
<s:RadialGradient rotation="90" focalPointRatio="1">
<s:GradientEntry id="arrowFill1" color="0" alpha="0.6"/>
<s:GradientEntry id="arrowFill2" color="0" alpha="0.8"/>
</s:RadialGradient>
</s:fill>
</s:Path>
</fx:Component>
<s:Label id="labelDisplay" verticalCenter="1" left="0" right="0" top="0" bottom="0" textAlign="start"
fontWeight="bold" verticalAlign="bottom" maxDisplayedLines="1" showTruncationTip="true"/>
</fx:Declarations>
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="down"/>
</s:states>
<!-- layer 1: shadow -->
<s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0x000000" color.down="0xFFFFFF" alpha="0.01" alpha.down="0"/>
<s:GradientEntry color="0x000000" color.down="0xFFFFFF" alpha="0.07" alpha.down="0.5"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 2: fill -->
<s:Rect id="fill" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" color.hovered="0xBBBDBD" color.down="0xAAAAAA" alpha="0.85"/>
<s:GradientEntry color="0xD8D8D8" color.hovered="0x9FA0A1" color.down="0x929496" alpha="0.85"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 3: fill lowlight -->
<s:Rect id="lowlight" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="270">
<s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627"/>
<s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099"/>
<s:GradientEntry color="0x000000" ratio="0.48001" alpha="0"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 4: fill highlight -->
<s:Rect id="highlight" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" ratio="0.0" alpha="0.33" alpha.hovered="0.22" alpha.down="0.12"/>
<s:GradientEntry color="0xFFFFFF" ratio="0.48" alpha="0.33" alpha.hovered="0.22" alpha.down="0.12"/>
<s:GradientEntry color="0xFFFFFF" ratio="0.48001" alpha="0"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 5: highlight stroke (all states except down) -->
<s:Rect id="highlightStroke" left="0" right="0" top="0" bottom="0" excludeFrom="down">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xFFFFFF" alpha.hovered="0.22"/>
<s:GradientEntry color="0xD8D8D8" alpha.hovered="0.22"/>
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 6: highlight stroke (down state only) -->
<s:Rect id="hldownstroke1" left="0" right="0" top="0" bottom="0" includeIn="down">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0x000000" alpha="0.25" ratio="0.0"/>
<s:GradientEntry color="0x000000" alpha="0.25" ratio="0.001"/>
<s:GradientEntry color="0x000000" alpha="0.07" ratio="0.0011"/>
<s:GradientEntry color="0x000000" alpha="0.07" ratio="0.965"/>
<s:GradientEntry color="0x000000" alpha="0.00" ratio="0.9651"/>
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<s:Rect id="hldownstroke2" left="1" right="1" top="1" bottom="1" includeIn="down">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0x000000" alpha="0.09" ratio="0.0"/>
<s:GradientEntry color="0x000000" alpha="0.00" ratio="0.0001"/>
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<s:VGroup bottom="5" left="7" right="7" top="5" gap="2" verticalAlign="bottom">
<s:Group id="filterDisplayGroup" width="100%"/>
<s:HGroup bottom="5" left="7" right="7" top="5" gap="2" verticalAlign="bottom">
<s:Group id="labelDisplayGroup" width="100%" left="8" right="8"/>
<s:Group id="sortIndicatorGroup" includeInLayout="false"/>
</s:HGroup>
</s:VGroup>
</s:DefaultGridHeaderRenderer>
所以基本上,我想要的是这个(基本上是一种更简单的this $800 datagrid component形式):
我目前拥有的是(带有上述问题):
s:TextInput
似乎有焦点,但您无法输入任何人都可以给我一个暗示我的渲染器出了什么问题(主要是为什么我不能输入输入字段的freck以及这个白色东西来自哪里)?
答案 0 :(得分:1)
的Datagrid:
<mx:DataGrid id="myGrid" dataProvider="{initDG}" variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn headerText="col1"/>
<mx:DataGridColumn headerText="col2"/>
<mx:DataGridColumn headerText="col3"/>
<mx:DataGridColumn headerRenderer="col4DGheaderRenderer"/>
</mx:columns>
</mx:DataGrid>
然后是col4DGheaderRenderer的完整代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:s="library://ns.adobe.com/flex/spark">
<s:TextInput/>
<mx:Label text="label text"/>
</mx:VBox>
答案 1 :(得分:1)
正如我们在评论中所讨论的那样,您的代码中有很多内容可能成为不当行为的可能来源。我碰巧有一个标题渲染器,其功能非常相似,完美无缺。所以我只是将代码转储到这里,你可以开始解决这个问题了。
一些注意事项:
fill
组件
<s:GridItemRenderer minWidth="21" minHeight="21"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:vmm="library://ns.vmm.be/flex/components">
<fx:Declarations>
<fx:Component id="defaultSortIndicator">
<s:Path data="M 3.5 7.0 L 0.0 0.0 L 7.0 0.0 L 3.5 7.0" implements="spark.components.gridClasses.IGridVisualElement">
<s:fill>
<s:RadialGradient rotation="90" focalPointRatio="1">
<s:GradientEntry id="arrowFill1" color="0" alpha="0.6" />
<s:GradientEntry id="arrowFill2" color="0" alpha="0.8" />
</s:RadialGradient>
</s:fill>
</s:Path>
</fx:Component>
<s:Label id="labelDisplay" verticalCenter="1" left="0" right="0" top="0" bottom="0"
textAlign="start" verticalAlign="middle" maxDisplayedLines="1" showTruncationTip="true"
color.normal="0x555555" color="0x90a938" fontWeight="bold" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.components.gridClasses.IGridVisualElement;
import mx.core.IVisualElement;
import spark.components.DataGrid;
import spark.components.GridColumnHeaderGroup;
import spark.components.gridClasses.GridColumn;
import spark.primitives.supportClasses.GraphicElement;
private function dispatchChangeEvent(type:String):void {
if (hasEventListener(type)) dispatchEvent(new Event(type));
}
//----------------------------------
// maxDisplayedLines
//----------------------------------
private var _maxDisplayedLines:int = 1;
[Bindable("maxDisplayedLinesChanged")]
[Inspectable(minValue="-1")]
public function get maxDisplayedLines():int {
return _maxDisplayedLines;
}
public function set maxDisplayedLines(value:int):void {
if (value == _maxDisplayedLines) return;
_maxDisplayedLines = value;
if (labelDisplay) labelDisplay.maxDisplayedLines = value;
invalidateSize();
invalidateDisplayList();
dispatchChangeEvent("maxDisplayedLinesChanged");
}
//----------------------------------
// sortIndicator
//----------------------------------
private var _sortIndicator:IFactory;
private var sortIndicatorInstance:IVisualElement;
[Bindable("sortIndicatorChanged")]
public function get sortIndicator():IFactory {
return (_sortIndicator) ? _sortIndicator : defaultSortIndicator;
}
public function set sortIndicator(value:IFactory):void {
if (_sortIndicator == value) return;
_sortIndicator = value;
if (sortIndicatorInstance) {
sortIndicatorGroup.includeInLayout = false;
sortIndicatorGroup.removeElement(sortIndicatorInstance);
sortIndicatorInstance = null;
}
invalidateDisplayList();
dispatchChangeEvent("sortIndicatorChanged");
}
override public function prepare(hasBeenRecycled:Boolean):void {
super.prepare(hasBeenRecycled);
if (labelDisplay && labelDisplayGroup && (labelDisplay.parent != labelDisplayGroup)) {
labelDisplayGroup.removeAllElements();
labelDisplayGroup.addElement(labelDisplay);
}
const column:GridColumn = this.column;
if (sortIndicator && column && column.grid && column.grid.dataGrid && column.grid.dataGrid.columnHeaderGroup) {
const dataGrid:DataGrid = column.grid.dataGrid;
const columnHeaderGroup:GridColumnHeaderGroup = dataGrid.columnHeaderGroup;
if (columnHeaderGroup.isSortIndicatorVisible(column.columnIndex)) {
if (!sortIndicatorInstance) {
sortIndicatorInstance = sortIndicator.newInstance();
sortIndicatorGroup.addElement(sortIndicatorInstance);
invalidateDisplayList();
}
// Initialize sortIndicator
sortIndicatorInstance.visible = true;
const gridVisualElement:IGridVisualElement = sortIndicatorInstance as IGridVisualElement;
if (gridVisualElement)
gridVisualElement.prepareGridVisualElement(column.grid, -1, column.columnIndex);
sortIndicatorGroup.includeInLayout = true;
sortIndicatorGroup.scaleY = (column.sortDescending) ? 1 : -1;
}
else if (sortIndicatorInstance) {
sortIndicatorGroup.removeElement(sortIndicatorInstance);
sortIndicatorGroup.includeInLayout = false;
sortIndicatorInstance = null;
}
}
}
override public function styleChanged(styleProp:String):void {
var allStyles:Boolean = !styleProp || styleProp == "styleName";
super.styleChanged(styleProp);
if (allStyles) invalidateDisplayList();
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="down" />
</s:states>
<s:Rect id="fill" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color.normal="0xf9f9f9" color.hovered="0xfcfdfa"
color.down="0xdceac2" alpha="0.85" />
<s:GradientEntry color.normal="0xeaeaea" color.hovered="0xdceac2"
color.down="0xd2e1b5" alpha="0.85" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:VGroup left="7" right="7" top="5" bottom="5" gap="6" verticalAlign="middle">
<s:TextInput width="100%" />
<s:HGroup width="100%">
<s:Group id="labelDisplayGroup" width="100%" />
<s:Group id="sortIndicatorGroup" includeInLayout="false" />
</s:HGroup>
</s:VGroup>
</s:GridItemRenderer>
答案 2 :(得分:0)
下面的代码显示了如何使用Header Renderer将输入框放入Header。我希望这可以解决问题。
<fx:Script>
<![CDATA[
import mx.controls.Alert;
protected function button1_clickHandler(event:MouseEvent):void
{
Alert.show(s.headerText);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:DataGrid id="myGrid" x="-4" y="0" width="528" horizontalScrollPolicy="off"
variableRowHeight="true" verticalScrollPolicy="off">
<mx:columns>
<mx:DataGridColumn headerText="col1"/>
<mx:DataGridColumn headerText="col2"/>
<mx:DataGridColumn headerText="col3"/>
<mx:DataGridColumn id="s">
<mx:headerRenderer>
<fx:Component>
<mx:VBox >
<s:TextInput width="{outerDocument.s.width}" id="p" change="{outerDocument.s.headerText=p.text}"/>
<s:Label text="col4"/>
</mx:VBox>
</fx:Component>
</mx:headerRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
<s:Button x="10" y="150" label="click" click="button1_clickHandler(event)"/>