Styling both foreground and background selection c

2019-07-05 02:12发布

问题:

Flex exposes a "selectionColor" CSS property for styling the background color of a selected list/datagrid. However, I cannot figure out how to style the foreground or text color of selected list. It appears you can only change the foreground color for all rows.

So, for example, that I wanted a very dark selection background color and a very light deselected background color. You would similarly want a light text color for selection and a dark text color for deselected.

I know I could do this with a custom item renderer, but that seems rather silly. The point is to style all lists/datagrids in my app. I don't want to have to set a custom item renderer or extend Datagrid for each place I use it. Note that I am using Flex 4 and am willing to use skins though I don't know if that means anything considering DataGrid is not sparkified yet.

回答1:

Flex 3 used textRollOverColor and textSelectedColor but Flex 4 components does not support them anymore.

The following example demonstrates all this + adding support for this colors for spark List:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx">

    <fx:Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        @namespace mx "library://ns.adobe.com/flex/mx";

        global
        {
            textRollOverColor: yellow;
            textSelectedColor: green;
        }

    </fx:Style>

    <fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;

        private function getListDataProvider():ArrayCollection
        {
            return new ArrayCollection([ "Item 1", "Item 2", "Item 3"]);
        }

        private function getGridDataProvider():ArrayCollection
        {
            return new ArrayCollection([ { name: "Item 1" }, { name: "Item 2" }, { name: "Item 3" } ]);
        }

    ]]>
    </fx:Script>

    <s:layout>
        <s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/>
    </s:layout>

    <s:List dataProvider="{getListDataProvider()}"/>

    <s:List dataProvider="{getListDataProvider()}" itemRenderer="ColoredItemRenderer"/>

    <mx:List dataProvider="{getListDataProvider()}"/>

    <mx:DataGrid dataProvider="{getGridDataProvider()}"/>

</s:Application>

ColoredItemRenderer:

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    autoDrawBackground="true">

    <fx:Script>
    <![CDATA[

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);

            var color:uint;
            if (selected)
                color = getStyle("textSelectedColor");
            else if (hovered)
                color = getStyle("textRollOverColor");
            else
                color = getStyle("color");
            sparkLabel.setStyle("color", color);
        }

    ]]>
    </fx:Script>

    <s:Label id="sparkLabel" text="{data}"/>

</s:ItemRenderer>


回答2:

Here is an example on how to do it in Flex 4 using states and itemRenders

<s:List itemRenderer="com.renderer.GlossaryRenderer" change="handleGridClick(event)" width="293" height="206" styleName="glossaryList" dataProvider="{_glossary}">
    <s:layout>
        <s:VerticalLayout horizontalAlign="justify" paddingLeft="5" requestedRowCount="9" />
    </s:layout>
</s:List>

You could set up your item renderer like this

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" 
            autoDrawBackground="false">
<s:states>
    <s:State name="normal" />
    <s:State name="hovered" />
    <s:State name="selected" />
</s:states>
<s:Label id="sparkLabel" backgroundColor.selected="#ff0000" color.selected="#FFFFFF" color.hovered="#FFFFFF" text="{data.word}" left="2" right="2" top="4" bottom="4" />
</s:ItemRenderer>


回答3:

For Spark DataGrid you need to create a new item renderer based on GridItemRenderer. Then assign that to the DataGrid itemRenderer property.

MyGridItemRender.mxml:

<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark"  
            width="100%"
            height="100%">

    <fx:Script>
        <![CDATA[

            override public function prepare(hasBeenRecycled:Boolean):void {
                super.prepare(hasBeenRecycled);

                var styleClient:IStyleClient = owner as IStyleClient;
                var color:uint;

                if (selected && styleClient.getStyle("textSelectionColor")!==undefined) {
                    color = styleClient.getStyle("textSelectionColor");
                }
                else if (selected && styleClient.getStyle("textSelectedColor")!==undefined) {
                    color = styleClient.getStyle("textSelectedColor");
                }
                else if (hovered && styleClient.getStyle("textRollOverColor")!==undefined) {
                    color = styleClient.getStyle("textRollOverColor");
                }
                else {
                    color = styleClient.getStyle("color");
                }

                labelDisplay.setStyle("color", color);
            }

        ]]>
    </fx:Script>

    <s:Label id="labelDisplay" 
             paddingLeft="3" paddingRight="3" 
             paddingTop="5" paddingBottom="5"
             verticalCenter="2"
             left="2"/>

</s:GridItemRenderer>

Code:

<s:DataGrid id="dataGrid" itemRenderer="MyGridItemRenderer"/>

You can also use this DataGrid, which has it on by default.