1

次のコードは、カスタム セル レンダラー (CustomListCell クラス) を使用するメイン コントローラー クラスで List オブジェクトを設定します。CustomListCell クラスは、List の DataProvider からセル自体を削除するために使用されるセルの Button オブジェクトを作成します。

カスタム セル レンダラーから親 List オブジェクトに正しくアクセスするにはどうすればよいですか?

//Controller Class
private function createList():void
 {
 provider = new DataProvider(data);

 list = new List();
 list.width = 200;
 list.height = 400;
 list.rowHeight = 50;
 list.dataProvider = provider;
 list.setStyle("cellRenderer", CustomListCell);
 }

-----

//CustomListCell Class
import fl.controls.Button;

public class CustomListCell extends Sprite implements ICellRenderer
 {     
 public function CustomListCell()
  {
  var button:Button = new Button();
  button.label = "Delete Cell";
  button.addEventListener(MouseEvent_MOUSE_DOWN, deleteCellHandler);
        addChild(button);
  }

 private function deleteCellHandler(evt:MouseEvent):void
  {
  //Access List/DataProvider Here
  }

 //required implemented ICellRenderer functions follow
 }

アップデート

以下は、Flash v3 List コンポーネントを使用して ICellRenderer を実装する、私の作業中のカスタム レンダラーです。List の dataProvider は、各セルの 2 つの要素 (randomColor と randomNumber) で構成されます。

package
{
//Imports
import fl.controls.Button;
import fl.controls.List;
import fl.controls.listClasses.ICellRenderer; 
import fl.controls.listClasses.ListData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.geom.ColorTransform;

//Class
public class TouchListRenderer extends Sprite implements ICellRenderer
    {
    //Properties
    private var cellWidthProperty:Number;
    private var cellHeightProperty:Number;
    private var dataProperty:Object;
    private var listDataProperty:ListData;  
    private var selectedProperty:Boolean;

    //Cell Display Objects
    private var backgroundCanvas:MySprite = new MySprite();
    private var numberTextField:TextField = new TextField();
    private var button:Button = new Button();

    //Constructor
    public function TouchListRenderer()
        {
        }

    //Size Setter (Getter Functions Intentionally Omitted)
    public function setSize(width:Number, height:Number):void
        {
        cellWidthProperty = width;
        cellHeightProperty = height;
        }

    //Data Setter
    public function set data(value:Object):void
        {
        dataProperty = value;
        }

    //Data Getter
    public function get data():Object
        { 
        return dataProperty; 
        }

    //List Data Setter
    public function set listData(value:ListData):void
        { 
        listDataProperty = value;
        }

    //List Data Getter
    public function get listData():ListData
        { 
        return listDataProperty; 
        }

    //Selected Setter
    public function set selected(value:Boolean):void
        { 
        selectedProperty = value;

        layout();
        }

    //Selected Getter
    public function get selected():Boolean
        { 
        return selectedProperty;
        }

    //Size And Layout
    private function layout():void
        {
        var newColor:ColorTransform = new ColorTransform();
        newColor.color = dataProperty.randomColor;

        backgroundCanvas.transform.colorTransform = newColor;
        backgroundCanvas.scaleX = cellWidthProperty / backgroundCanvas.width;
        backgroundCanvas.scaleY = cellHeightProperty / backgroundCanvas.height;

        numberTextField.text = dataProperty.randomNumber;
        numberTextField.autoSize = TextFieldAutoSize.LEFT;
        numberTextField.textColor = 0xFFFFFF;
        numberTextField.x = 50;
        numberTextField.y = cellHeightProperty / 2 - numberTextField.height / 2;
        numberTextField.border = true;
        numberTextField.selectable = false;

        button.label = "Delete";
        button.x = cellWidthProperty - button.width - 50;
        button.y = cellHeightProperty / 2 - button.height / 2;
        button.drawNow();
        button.addEventListener(MouseEvent.MOUSE_DOWN, buttonClickEventHandler);

        addChild(backgroundCanvas);
        addChild(numberTextField);
        addChild(button);
        }

    //Button Click Event Handler
    private function buttonClickEventHandler(evt:MouseEvent):void
        {
        List(listDataProperty.owner).removeItemAt(listDataProperty.index);
        }

    //Style Setter
    public function setStyle(style:String, value:Object):void
        {
        }

    //Mouse State Setter
    public function setMouseState(state:String):void
        {
        }
    } 
} 

package
{
import flash.display.Sprite;

public class MySprite extends Sprite
    {
    public function MySprite()
        {
        graphics.beginFill(0xFF0000);
        graphics.drawRect(0, 0, 10, 10);
        graphics.endFill();
        }
    }
}
4

2 に答える 2

2

うーん!答えはずっと目の前にありました!次回は、ドキュメントを確認するように通知してください:

List(listData.owner)

fl.controls.listClasses.ListData.owner

于 2010-12-24T11:18:47.203 に答える
1

これを行うには複数の方法があります。

これは非常にハックな解決策です。アイコンを使用し、そのアイコンに close イベントをディスパッチさせます。

アイデアは、カスタム ムービークリップを各リスト セルにアイコンとして配置することです。そのアイコンは、クリックされたセルのインデックスでイベントを送出するので、それを削除できます。

最初のステップ: セル インデックスを渡すための基本的なカスタム イベントを作成します。

package{

    import flash.events.Event;

    public class CloseEvent extends Event{

        public static const CLOSE:String = 'close';
        public var index:int;

        public function CloseEvent(type:String,bubbles:Boolean = true,cancelable:Boolean=true){
            super(type,bubbles,cancelable);
        }

    }

}

2番目のステップ: : 閉じるアイコンか何かを描画し、それを MovieClip に変換してActionscript 用にエクスポートします。

ステップ 3 : イベント リスナーを追加して、閉じるアイコンがクリックされたときにカスタム イベントをディスパッチします。

閉じるアイコン ムービー クリップ内に、次のアクションを配置しました。

import fl.controls.listClasses.CellRenderer;

//setup click
buttonMode = true;
if(parent) parent.mouseChildren = true;
addEventListener(MouseEvent.MOUSE_DOWN,dispatchClose);
//setup event
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE,true);
if(parent) closeEvent.index = CellRenderer(parent).listData.index;
//listen to click and pass on
function dispatchClose(event:MouseEvent):void {
    dispatchEvent(closeEvent);
}

非常に基本的なもので、マウスダウンをリッスンし、イベントを作成してインデックスを設定し、クリック時にそのイベントをディスパッチします。アイコンはセル レンダラーに追加されるため、セル レンダラーはその親であり、とりわけ、セルのインデックスを保持するlistDataプロパティを持っています。

テスト スニペットは次のようになります。

import fl.data.DataProvider;

var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1),icon:Close});
ls.dataProvider = dp;

addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
    ls.removeItemAt(event.index);
}

CloseEvent はバブルするので、セル レンダラーのアイコンの外側からそれをキャッチし、そのインデックスの項目を削除するようにリストに指示できます。アイコン内でそれを行うことは可能ですが、階層をリストまでずっと「登る」必要があり、それはすでにかなりハックです.

私がこれを行ったのは、おそらく @TheDarkIn1978 :P ICellRenderer 関数を実装するのと同じくらい怠惰だったからです。次に、質問コードをもう一度見て、CellRenderer が既に ICellRenderer 関数を既に実装しているのに、なぜカスタム セルがスプライトを拡張するのか理解できませんでした。

そこで、ハックを減らした方法でそれを行う私の試みを次に示します。

package{

    import fl.controls.*;
    import fl.controls.listClasses.*;
    import fl.data.*;
    import flash.events.*;

    public class SCListCell extends CellRenderer implements ICellRenderer{

        protected var closeButton:Button;
        protected var closeEvent:CloseEvent;

        override protected function configUI():void {
            super.configUI();
            closeButton = new Button();
            closeButton.label = 'x';
            closeButton.buttonMode = true;
            closeButton.setSize(30,20);
            closeButton.drawNow();
            closeButton.addEventListener(MouseEvent.CLICK,close);
            addChild(closeButton);
            closeEvent = new CloseEvent(CloseEvent.CLOSE);
        }

        private function close(event:MouseEvent):void{
            closeEvent.index = listData.index;
            dispatchEvent(closeEvent);
        }

        override protected function drawLayout():void{
            mouseChildren = true;
            closeButton.x = width-closeButton.width;
        }

    }

}

同じ CloseEvent を使用してインデックスを渡し、カスタム セルはlistDataオブジェクトに直接アクセスしてインデックスをフェッチするため、サンプル スニペットは次のようになります。

import fl.data.DataProvider;

var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;

addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
    ls.removeItemAt(event.index);
}

ls.setStyle('cellRenderer',SCListCell);

あなたの質問に答えるには:

カスタム セル レンダラーから親 List オブジェクトに正しくアクセスするにはどうすればよいですか?

セル レンダラーの listData プロパティを使用できます。必要に応じてできますが、それはいくつかのレベルを上げることを意味します:

package{

    import fl.controls.*;
    import fl.controls.listClasses.*;
    import fl.data.*;
    import flash.events.*;

    public class SCListCell extends CellRenderer implements ICellRenderer{

        protected var closeButton:Button;

        override protected function configUI():void {
            super.configUI();
            closeButton = new Button();
            closeButton.label = 'x';
            closeButton.buttonMode = true;
            closeButton.setSize(30,20);
            closeButton.drawNow();
            closeButton.addEventListener(MouseEvent.CLICK,close);
            addChild(closeButton);
        }

        private function close(event:MouseEvent):void{
            List(this.parent.parent.parent).removeItemAt(listData.index);
        }

        override protected function drawLayout():void{
            mouseChildren = true;
        closeButton.x = width-closeButton.width;
        }

    }

}

これにより、リスト作成部分は次のように単純になります。

import fl.data.DataProvider;

var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;

ls.setStyle('cellRenderer',SCListCell);

この場合、CloseEvent は必要ありません。

HTH

于 2010-12-15T00:48:40.580 に答える