コンボボックスでカスタム アイテム レンダラーを使用して、デフォルトのテキスト ラベルの代わりにカスタム描画を表示しています。
これはドロップダウン リストでは正常に機能しますが、表示される項目 (リストが閉じられている場合) は、オブジェクトのテキスト表現のままです。
表示されたアイテムをドロップダウンと同じ方法でレンダリングする方法はありますか?
コンボボックスでカスタム アイテム レンダラーを使用して、デフォルトのテキスト ラベルの代わりにカスタム描画を表示しています。
これはドロップダウン リストでは正常に機能しますが、表示される項目 (リストが閉じられている場合) は、オブジェクトのテキスト表現のままです。
表示されたアイテムをドロップダウンと同じ方法でレンダリングする方法はありますか?
デフォルトでは、これを行うことはできません。ただし、ComboBoxを拡張すると、この機能を簡単に追加できます。これは簡単な例です。これは大まかなバージョンであり、おそらくテスト/調整が必要ですが、これをどのように達成できるかを示しています。
package
{
import mx.controls.ComboBox;
import mx.core.UIComponent;
public class ComboBox2 extends ComboBox
{
public function ComboBox2()
{
super();
}
protected var textInputReplacement:UIComponent;
override protected function createChildren():void {
super.createChildren();
if ( !textInputReplacement ) {
if ( itemRenderer != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer to use in place of the text input
textInputReplacement = itemRenderer.newInstance();
addChild(textInputReplacement);
}
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if ( textInputReplacement ) {
textInputReplacement.width = unscaledWidth;
textInputReplacement.height = unscaledHeight;
}
}
}
}
上記の解決策を試しましたが、コンボボックスを閉じたときに selectedItem が表示されないことがわかりました。itemRenderer データ プロパティを selectedItem にバインドするには、追加のコード行が必要でした。
if ( !textInputReplacement ) {
if ( itemRenderer != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer to use in place of the text input
textInputReplacement = itemRenderer.newInstance();
// ADD THIS BINDING:
// Bind the data of the textInputReplacement to the selected item
BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true);
addChild(textInputReplacement);
}
}
デーンのコードをもう少し拡張しました。場合によっては、クリックしてもレンダラーでドロップボックスが開かず、通常のFlexComboBoxスキンが起動しないことに気付きました。したがって、replaceTextInput()で、いくつかのイベントリスナーを追加し、スキンの表示に使用されるComboBoxボタンへの参照を保存しました。これで、通常のComboBoxと同じように動作します。
コードは次のとおりです。
パッケージ
{{
インポートflash.events.Event;
インポートflash.events.KeyboardEvent;
インポートflash.events.MouseEvent;
import mx.binding.utils.BindingUtils;
import mx.controls.Button;
import mx.controls.ComboBox;
import mx.core.IFactory;
import mx.core.UIComponent;
import mx.events.DropdownEvent;
/ **
*割り当てられた「itemRenderer」を使用する標準のComboBoxの拡張
*リストアイテムと選択したアイテムの両方。
*
*以下のコードに基づく:
* http://stackoverflow.com/questions/269773/flex-custom-item-renderer-for-the-displayed-item-in-the-combobox
* /
パブリッククラスComboBoxFullRendererはComboBoxを拡張します
{{
保護された変数textInputReplacement:UIComponent;
private var _increaseW:Number = 0;
private var _increaseH:Number = 0;
/ **
*ドロップダウンリストの現在のオープン/クローズ状態を追跡します。
* /
保護されたvar_isOpen:Boolean = false;
/ **
*ComboBoxをオーバーレイする「ボタン」への参照を格納します。許可します
*スキンが適切にトリガーされるようにイベントを渡します。
* /
保護されたvar_buttonRef:Button = null;
/ **
*コンストラクタ。
* /
パブリック関数ComboBoxFullRenderer(){
素晴らしい();
}
/ **
*サイズを調整するためにComboBoxの幅を広げる値を設定します。
*
* @paramvalComboBoxの幅を増やすためのピクセル数。
* /
パブリック関数セットincreaseW(val:Number):void {
_increaseW = val;
}
/ **
*サイズを調整するためにComboBoxの高さを増やす値を設定します。
*
* @paramvalComboBoxの高さを増やすためのピクセル数。
* /
パブリック関数セットincreaseH(val:Number):void {
_increaseH = val;
}
/ **
*'itemRenderer'セッターをオーバーライドして、選択したセッターも置き換えることができるようにします
*アイテムレンダラー。
*
*@paramvalueドロップダウンリストアイテムを表示するために使用されるレンダラー
*および選択したアイテム。
* /
パブリック関数セットitemRenderer(value:IFactory):void{をオーバーライドします
super.itemRenderer=値;
replaceTextInput();
}
/ **
*ベースの'createChildren()'ルーチンをオーバーライドして、'replaceTextInput()'を呼び出します
*標準の選択されたアイテムレンダラーを置き換える方法。
*
* @see #replaceTextInput();
* /
保護された関数createChildren():void{をオーバーライドします
super.createChildren();
replaceTextInput();
}
/ **
*ComboBoxの'textInput'の子を独自の子に置き換えるルーチン
*選択したデータ要素をレンダリングします。のインスタンスを作成します
*このComboBoxに設定された「itemRenderer」。
* /
保護された関数replaceTextInput():void {
if(!textInputReplacement){
if(this.itemRenderer!= null && textInput!= null){
//デフォルトのtextInputを削除します
removeChild(textInput);
//テキスト入力の代わりに使用する新しいitemRendererインスタンスを作成します
textInputReplacement = this.itemRenderer.newInstance();
//クリックをリッスンして、ドロップダウンを開いたり閉じたりできるようにします
//レンダラーコンポーネントがクリックされます。
textInputReplacement.addEventListener(MouseEvent.CLICK、_onClick);
//レンダラーでマウスイベントをリッスンして、それらをフィードできるようにします
//ComboBoxオーバーレイボタン。これにより、ボタンのスキンが確認されます
//アクティブ化されます。ComboBox :: commitProperties()コードを参照してください。
textInputReplacement.addEventListener(MouseEvent.MOUSE_DOWN、_onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.MOUSE_UP、_onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.ROLL_OVER、_onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.ROLL_OUT、_onMouseEvent);
textInputReplacement.addEventListener(KeyboardEvent.KEY_DOWN、_onMouseEvent);
//textInputReplacementのデータを選択したアイテムにバインドします
BindingUtils.bindProperty(textInputReplacement、 "data"、this、 "selectedItem"、true);
//レンダラーを子として追加します。
addChild(textInputReplacement);
//状態を維持できるように、opencloseをリッスンします。The
//'isShowingDropdown'プロパティはmx_internalであるため、
//アクセスできます。
this.addEventListener(DropdownEvent.OPEN、_onOpen);
this.addEventListener(DropdownEvent.CLOSE、_onClose);
//コンボボックスのmx_internalボタンへの参照を保存します。
//これが必要になるので、dispatchEvent()メソッドを呼び出すことができます。
for(var i:int = 0; i <this.numChildren; i ++){
var temp:Object = this.getChildAt(i);
if(temp is Button){
_buttonRef = temp as Button;
壊す;
}
}
}
}
}
/ **
*ドロップダウンリストで開いているイベントを検出して、現在のイベントを追跡します
*ドロップダウン状態により、選択したクリックに適切に反応できるようになります
*アイテムレンダラー。
*
*@parameventコンボボックスのDropdownEvent.OPENイベント。
* /
保護された関数_onOpen(event:DropdownEvent):void {
_isOpen = true;
}
/ **
*ドロップダウンリストでクローズイベントを検出して、現在のイベントを追跡します
*ドロップダウン状態により、選択したクリックに適切に反応できるようになります
*アイテムレンダラー。
*
*@parameventコンボボックスのDropdownEvent.CLOSEイベント。
* /
保護された関数_onClose(event:DropdownEvent):void {
_isOpen = false;
}
/ **
*レンダラーのクリックを検出すると、ドロップダウンリストを開いたり閉じたりします
*ドロップダウンが現在開いているか閉じているかに基づいています。
*
*@paramevent選択したアイテムレンダラーからのCLICKイベント。
* /
保護された関数_onClick(event:MouseEvent):void {
if(_isOpen){
this.close(event);
} そうしないと {
this.open();
}
}
/ **
*選択したアイテムレンダラーで特定のマウス/キーボードイベントに反応し、
*スキンが適切になるようにイベントをComboBoxの「ボタン」に渡します
* 適用。
*
* @parameventComboBoxボタンに送信するマウスまたはキーボードのイベント。
*
* /
保護された関数_onMouseEvent(event:Event):void {
if(_buttonRef!= null){
_buttonRef.dispatchEvent(event);
}
}
}//クラスを終了
}//パッケージを終了
maclemaとMauritsdeBoerに感謝します。私のニーズに合うように、このクラスにさらにいくつかのものを追加しました。
set itemRendererをオーバーライドして、mxmlではなくASを介してitemRendererを設定した場合にこれが機能するようにします。重複を避けるために、テキスト入力置換コードを独自の関数に移動しました。
最初はレンダラーが大きすぎたため、必要に応じてコンボボックスのサイズを変更するために「increaseW」と「increaseH」のセッターを追加しました。
textInputReplacementの幅から25を引いたので、ドロップダウンボタンと重ならないようにしています...さまざまなスキンなどに対応するために、より比例したものを使用する方がよい場合があります。
コード:
package
{
import mx.binding.utils.BindingUtils;
import mx.controls.ComboBox;
import mx.core.IFactory;
import mx.core.UIComponent;
public class ComboBox2 extends ComboBox
{
public function ComboBox2()
{
super();
}
protected var textInputReplacement:UIComponent;
private var _increaseW:Number = 0;
private var _increaseH:Number = 0;
public function set increaseW(val:Number):void
{
_increaseW = val;
}
public function set increaseH(val:Number):void
{
_increaseH = val;
}
override public function set itemRenderer(value:IFactory):void
{
super.itemRenderer = value;
replaceTextInput();
}
override protected function createChildren():void
{
super.createChildren();
replaceTextInput();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
unscaledWidth += _increaseW;
unscaledHeight += _increaseH;
super.updateDisplayList(unscaledWidth, unscaledHeight);
if ( textInputReplacement ) {
textInputReplacement.width = unscaledWidth - 25;
textInputReplacement.height = unscaledHeight;
}
}
protected function replaceTextInput():void
{
if ( !textInputReplacement ) {
if ( this.itemRenderer != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer to use in place of the text input
textInputReplacement = this.itemRenderer.newInstance();
addChild(textInputReplacement);
// ADD THIS BINDING:
// Bind the data of the textInputReplacement to the selected item
BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true);
addChild(textInputReplacement);
}
}
}
}
}
Spark ComboBox を使用してこれを行う方法を探していました。
このスレッドは私にとって非常に役に立ちましたが、これまでのところ、mx:ComboBox を使用してそれを行う方法についての回答しかありませんでした。spark ComboBox を使用してそれを行う方法についての回答を追加する必要があると思いました。
スキンは次のようになります。
<s:SparkSkin>
<... Lots of other stuff/>
<s:BorderContainer height="25">
<WHATEVER YOU NEED HERE!/>
</s:BorderContainer>
<!-- Disable the textInput and hide it -->
<s:TextInput id="textInput"
left="0" right="18" top="0" bottom="0"
skinClass="spark.skins.spark.ComboBoxTextInputSkin"
visible="false" enabled="false"/>
</s:SparkSkin>
Spark ComboBox を使用すると、このプロセスは非常に簡単で、ComboBox を拡張する必要はありません。