List rendery a styly

9.11.2009· Autor: Ondřej Brichta· Počet komentářů: 1

Použití vlastních komponent coby item rendererů List komponent je snadnou záležitostí. Jakmile ale potřebujeme vytvořit vlastní styly výběru/vybrané položky seznamu, narazíme na omezení, která v si dnešním článku představíme.

Vlastní item renderery a vlastní styly výběru

Item renderery (http://www.flash.cz/portal/clanek.aspx?id=546) jsou vlastní kompomenty, které umožňují v aplikacích Flash/Flex Builderu upraviot vzhled prvků nejrůznějších seznamů(List komponenty). Každá z těchto komponent umožňuje nastavit barvu vysvícení a barvu výběru aktivní položky, kterou jsme zvolili nebo na kterou jsme najeli kurzorem myši.

Drobné problémy nastanou v okamžiku, kdy si chceme vytvořit vlastní styl vykreslování aktivních položek. Dokud se vše děje v rovině změny barvy položky, není zde žádný problém, stačí pouze upravit příslušný parametr stylu (rollOverColor,selectionColor). Jakmile ale chceme připravit jiný styl, například zobrazení stínu, objeví se problém.

Samotný efekt zobrazení/schování stínu podle kurzoru myši si můžeme připravit ve vlastním itemRendereru:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas mouseChildren="false" mouseOut="outState()" mouseOver="overState()" xmlns:mx="http://www.adobe.com/2006/mxml" width="220" height="110" >
 <mx:Script>
 <![CDATA[
 private function outState():void{
 hb.filters = [];
 lbl.setStyle("color",0x000000);
 }
 private function overState():void{
 var f:DropShadowFilter = new DropShadowFilter();
 f.inner = true;
 f.blurX = 5;
 f.blurY = 5;
 hb.filters = [f];
 lbl.setStyle("color",0xff0000);
 }
 ]]>
 </mx:Script>
 <mx:HBox id="hb" width="150" height="100" horizontalCenter="0" top="5" horizontalAlign="center" verticalAlign="middle" borderStyle="solid" borderColor="#000000" cornerRadius="6" backgroundColor="#FFFFFF">
 <mx:Label text="{data}" fontWeight="bold" color="#000000" fontSize="12" width="100%" id="lbl" textAlign="center"/>
 </mx:HBox>
</mx:Canvas>

Kolize s defaultním vysvícením


Jenže pokud takovýto renderer použijeme v nějaké List komponentě, bude se kromě našeho stínu zobrazovat i defaultní vysvícení podle nastaveného stylu. Máme sice možnost upravit prostřednictvím atributu „selectionEasingFunction" připojit vlastní funkci pro vykreslení efektu vysvícení (bude vracet 0), ovšem nezabráníme tím zobrazování vybrané položky.
Žádný parametr pro zakázání vykreslování aktivních/vybraných prvků tady nenajdeme.

Rozšíření List komponenty

Na řadu tak přichází nutnost vytvoření vlastní List komponenty, ve které přímo přepíšeme původní funkce vykreslování výběru a tím je deaktivujeme. Pokud budeme upravovat HorizontalList komponentu, pak bude naše nová komponenta vypadat takto:

package com{
 import flash.display.Sprite;
 import mx.controls.HorizontalList;
 import mx.controls.listClasses.IListItemRenderer;
 public class MyHList extends HorizontalList{
 //
 public function MyHList(){
 super();
 }
 //
 override protected function drawItem(item:IListItemRenderer,
 selected:Boolean = false,
 highlighted:Boolean = false,
 caret:Boolean = false,
 transition:Boolean = false):void {
 //spuštění funkce setSelected itemRendereru
 if(selected){
 item["setSelected"](selected);
 }else{
 item["setSelected"](highlighted);
 }
 super.drawItem(item,selected,highlighted,caret,transition);
 }
 //
 override protected function drawHighlightIndicator(
 indicator:Sprite, x:Number, y:Number,
 width:Number, height:Number, color:uint,
 itemRenderer:IListItemRenderer):void{
 }
 //
 override protected function drawSelectionIndicator(
 indicator:Sprite, x:Number, y:Number,
 width:Number, height:Number, color:uint,
 itemRenderer:IListItemRenderer):void {
 }
 }
}

Původní komponenta využívá funkce drawItem (vykreslení pozadí položky), drawHighlightIndicator (vykreslení aktivního prvku po najetí myši) a drawSelectionIndicator (vykreslení vybrané položky).

Pokud necháme funkce pro vykreslení aktivní a vybrané položky bez jakékoliv akce, nebude docházet k defaultnímu překreslování položek. Nesmíme ovšem zapomenout na funkci drawItem, kterou využijeme pro zobrazení našeho vlastního efektu - to je zajištěno funkcí setSelected kterou jsme si ve vlastním rendereru připravili:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="220" height="110" >
 <mx:Script>
 <![CDATA[
 //funkce pro nastavení efektu stínu
 public function setSelected(sel:Boolean):void{
 if(sel){
 overState();
 }else{
 outState();
 }
 }
 private function outState():void{
 hb.filters = [];
 lbl.setStyle("color",0x000000);
 }
 private function overState():void{
 var f:DropShadowFilter = new DropShadowFilter();
 f.inner = true;
 f.blurX = 5;
 f.blurY = 5;
 hb.filters = [f];
 lbl.setStyle("color",0xff0000);
 }
 ]]>
 </mx:Script>
 <mx:HBox id="hb" width="150" height="100" horizontalCenter="0" top="5" horizontalAlign="center" verticalAlign="middle" borderStyle="solid" borderColor="#000000" cornerRadius="6" backgroundColor="#FFFFFF">
 <mx:Label text="{data}" fontWeight="bold" color="#000000" fontSize="12" width="100%" id="lbl" textAlign="center"/>
 </mx:HBox>
</mx:Canvas>

Pokud vše dáme dohromady a porovnáme s originální HorizontalList komponentou, vidíme že upravený styl je mnohem lepší:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="initMe()" xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:ns1="com.*">
<mx:Script>
 <![CDATA[
 [Bindable]
 private var listData:Array;
 private function initMe():void{
 listData = new Array();
 for(var i:uint=0;i<20;i++){
 var s:String = "Položka "+i;
 listData.push(s);
 }
 }
 ]]>
</mx:Script>
 <mx:HorizontalList itemRenderer="ListRenderNoEff" width="550" height="130" dataProvider="{listData}"></mx:HorizontalList>
 <ns1:MyHList itemRenderer="ListRender" dataProvider="{listData}" width="550" height="130"/>
</mx:Application>

Ondřej Brichta Vývojář multimediálních aplikací, šéfredaktor Flash.cz, školitel produktů Flash, Flex, Flash Media Server

Web: http://www.obria.cz |

Motto: <°))))><

Komentáře k článku  
Vďaka. al | 9.11.2009 14:19

Přihlášení uživatele