ActionScript-カスタムCellRendererのアクセスリスト/DataProvider
-
10-10-2019 - |
質問
以下のコードは、カスタムセルレンダラー(CustomListCellクラス)を使用するメインコントローラークラスのリストオブジェクトを設定します。 CustomListCellクラスは、リストのDataProviderから削除するために使用されるセルのボタンオブジェクトを作成します。
カスタムセルレンダラーから親リストオブジェクトに適切にアクセスするにはどうすればよいですか?
//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
}
アップデート
以下は、IcellRendererをFlash V3リストコンポーネントで実装する私の作業カスタムレンダラーです。リストのDataProviderは、各セルの2つの要素、ランダムカラーとランダム数で構成されています。
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();
}
}
}
解決
うーん!答えはずっと私の前にありました!次回はドキュメントを確認するように思い出させてください。
List(listData.owner)
他のヒント
これを行うには複数の方法があります。
がここにあります 非常にハッキーなソリューション: :アイコンを使用して、そのアイコンに近いイベントを発送します。
アイデアは、各リストセルにカスタムMovieclipをアイコンとして配置することです。そのアイコンは、セルのインデックスをクリックしてイベントを派遣して、削除できます。
最初のステップ: :セルインデックスを通過する基本的なカスタムイベントを作成します。
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);
}
近接泡はバブルであるため、セルレンダラーのアイコンの外側からキャッチし、そのインデックスでアイテムを削除するようにリストに指示することができます。アイコン内でそれを行うことは可能ですが、リストまで階層を「登る」ことが必要であり、すでにかなりハッキーです。
私はこれをしました。なぜなら、私はおそらく @thedarkin1978:Pと同じくらい怠zyだったからです。それから私は再び質問コードを見ましたが、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);
する あなたの質問に答えてください:
カスタムセルレンダラーから親リストオブジェクトに適切にアクセスするにはどうすればよいですか?
セルレンダラーの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