7


2

Flex ItemRendererはテキスト入力間のタブ操作の使用を防止します

私は3つのパネルのそれぞれに5つのテキスト入力を表示するカスタム* ItemRenderer *を持っています。


残念ながら、ItemRendererとして使用した場合、テキスト入力間のタブ移動は、上記のtabIndex値を使用しても機能しません。 このコードを独自のMXMLアプリケーションにコピーした場合、テキスト入力間のタブ移動は予想どおりに機能します。

誰かがこのシナリオでタブを復元する方法を知っていますか? 私がそのような単純なユーザビリティ要素なしでこのアプリをリリースしなければならないならば、それは残念です。

私は `+ mx.managers.IFocusManagerComponent +`を実装する必要があるかもしれませんが、それを行う方法に関する例が見つかりません。また、http://livedocs.adobe.com/flex/3/langref/mx/ managers / FocusManager.html [FocusManager docs]も役に立たない。

9 Answer


3


私のデータグリッドでは、rendererIsEditor = "true"のカスタムitemRendererとしてmx:VBoxを使用していましたが、タブオーダーの問題も発生していました。

私が考え出したのは、メインアプリケーションのFocusManager()が正しくタブ付けできるようにするには、itemRendererがIFocusManagerComponentを実装する必要があるということです。 私はそのインターフェースを実装してみました:

[残りのitemRendererコード]

…​and it turns out to be rather complex to do…​lots of interface 実装する機能

しかし私の場合は幸運でした。私のitemRendererにはTextInput要素が1つしかありません(残りはすべてカスタムコード、バリデータです)

[残りのitemRendererコード]

ほら! タブオーダーの問題が修正されました。

もっと複雑なitemRendererを持つあなたのための結論はあなたのクラスにIFocusManagerComponentインターフェースを完全に実装する必要があるでしょう…それはflexがあなたのitemRendererを通してカスタムタブする方法を教えるように見えるのでおそらく良いですフィールド あるいは、最上位タグをすでにインターフェースを実装しているものに変更することもできます。例えば、以下のようにmx:VBoxをネストできます。


…​and have it work perhaps? Someone with more complex code than I 試してみて、何が起こるかを確認してください。


3


「ListBase派生」コンポーネントで使用されているitemRenderで同じ問題に遭遇しました。 私は、すべての "ListBase派生"コンポーネントが、ListBaseContentHolder内のすべてのアイテムレンダラーをラップすることを発見しました。

ListBaseのソースから。

/ **
 *  すべてのアイテムレンダラーを親とする内部表示オブジェクト
 *  選択と強調表示インジケータと他のサポートグラフィック。
 *  これは、のcontentPaneとほぼ同じです。
 *  コンテナクラス。スクロールを管理するために使用されます。 * / protected var listContent:ListBaseContentHolder;

このクラスの_tabChildren_および_tabEnabled_プロパティはデフォルトでfalseに設定されています。 私が見つけた唯一の回避策は、Listから派生するMyListコンポーネントを作成し、createChildrenメソッド(listContentが初期化されている場所)を次のようにオーバーライドすることです。

import flash.display.DisplayObject; import mx.controls.List;

パブリッククラスMyListは、List {override protected function createChildren()をオーバーライドします。void {super.createChildren();} this.listContent.tabChildren = this.tabChildren this.listContent.tabEnabled = this.tabEnabled}}

それから ""コンポーネントの代わりに ""を使うことでItemRenderのタブ機能を取り戻しました。

それが役に立てば幸い、


0


私は正しい方向に動いているかもしれないと思います、しかし私はまだ完全にそこにいません。

カスタムItemRendererを使用したHorizo​​ntalListを使用して、私のメインアプリケーションを作成しました。


元の質問のコードサンプルを更新して、ItemRenderer MXML全体(該当部分)を含めました。これがActionScriptの分離コードです。

/ *
 *  ChainListRenderer.mxml.as  -  ChainListRenderer.mxml * /の分離コード

import flash.events.Event; import flash.events.KeyboardEvent; flash.ui.Keyboardをインポートします。

//used to combine all textboxes in a single array to make looping through them with the TAB key easier
private var allBoxes:Array。

パブリック関数expandPanel(e:Event):void {trace(e.currentTarget);} var state:String = e.currentTarget.parent.parent.id; if(state!= this.currentState)this.currentState = state。 }

private function onCreationComplete():void {//この関数は、マップ関数function forEach(o:Object、index:int、ar:Array)を介して各オブジェクトに対して実行されます。void {o.addEventListener(FocusEvent.FOCUS_IN、expandPanel) o.addEventListener(MouseEvent.CLICK、stopBubble); //クリックイベントを伝播しない(これは基本状態に戻る)o.addEventListener(KeyboardEvent.KEY_DOWN、customTabbing); //テキストフィールド間のタブ移動を修正します}

this.addEventListener(KeyboardEvent.KEY_DOWN、customTabbing);

//テキストボックスをループして、focusInイベントリスナーを追加する。tpBoxes.getChildren()。map(forEach); lpBoxes.getChildren()。map(forEach); apBoxes.getChildren()。map(forEach);

// customTabbing関数によって使用される "allBoxes"配列を作成します。allBoxes = tpBoxes.getChildren(); function forEachTabbing(o:オブジェクト、index:int、ar:Array):void {allBoxes.splice(allBoxes.length、0、o);} lpBoxes.getChildren()。map(forEachTabbing); apBoxes.getChildren()。map(forEachTabbing); }

//this function is used to prevent event bubbling
プライベート関数stopBubble(e:Event):void {e.stopPropagation();} }

//this function re-implements tabbing between text fields, which is broken when inside an itemRenderer
パブリック関数customTabbing(e:KeyboardEvent):void {trace( 'keyCode:'

//矢印キーが水平リストをナビゲートするのを防ぎますe.stopPropagation(); }}

基本的に、私がここでやろうとしているのは、各テキストフィールドのkey_downイベントでTABキーをチェックし、それを使って次のTextInputにフォーカスを移動することでタブ操作を再実装することです。 これは望みどおりの効果はありませんが、フォーカスはこのHorizo​​ntalListの外側の次のコントロールにジャンプします。

ここからどこへ行くべきアイデアがありますか?


0


なぜtabChildren = "false"をしているのですか? HorziontalListの子にタブを付けたくありませんか。 itemRendererはリストの子だからです。


0


これは私が使っていた方法では不可能なようです。 カスタムのアイテムレンダラーを含むリストを使用する代わりに、単一アイテムのビューコンポーネントとすべてのアイテムの概要を表示する別のリストに切り替えて、問題を解決しました。


0


私は同じ問題を抱えていて、タブボタンの動作を再実装しようとすることによってそれを解決しました。 成功の手がかりは、単に `+ event.preventdefault()+`メソッドを使用することです。 使用されているコードは前に示されています。

private function initFocusMap():void {
    focusMap = {
        InNom:benefPersona.InApePat,
        InApePat:benefPersona.InApeMat,
        InApeMat:benefPersona.InFecNacimiento,
        InFecNacimiento:benefPersona.InRFC,
        InRFC:benefPersona.InCURP,
        InCURP:benefPersona.InIdSexo,
        InIdSexo:benefPersona.InIdParentesco,
        InIdParentesco:benefPersona.InPorc,
        InPorc:domBeneficiario.InCalle,
        InCalle:domBeneficiario.InNumExterior,
        InNumExterior:domBeneficiario.InNumInterior,
        InNumInterior:domBeneficiario.InCP,
        InCP:domBeneficiario.InColonia,
        InColonia:domBeneficiario.InIdPais,
        InIdPais:domBeneficiario.InIdEdo,
        InIdEdo:domBeneficiario.InIdCiudad,
        InIdCiudad:benefPersona.InNom
    }
}

private function kfcHandler(event:FocusEvent):void {
    var id:String = ""
    if (event.target is AperClsDateField || event.target is AperClsCombo) {
        id = event.target.id;
    } else {
        id = event.target.parent.id;
    }
    if (id != "InIdDelegacionMunic") {
        event.preventDefault();
        focusManager.setFocus(focusMap[id]);
    }
}


0


これがComboBoxのitemEditorでどうなっているかです。


0


私はAdvancedDataGridでitemRendererの1つをタブ付けするという同じ問題を抱えていました(ところで、私はFlex SDK 3.5を使用しています)が、この記事は私のタブフレンドリなitemRendererを作ることを可能にするのに非常に役に立ちました同様に貢献:)

これを機能させるには、gridとgridColumnのいくつかのプロパティも変更する必要があります。

最初にgridとgridColumnについて説明しましょう。

グリッドの "editable"プロパティを "true"に設定すると、ご存知のように、各列のセルをタブで移動できます(列の "editable"プロパティを "false"に設定していないと仮定します)。

*ステップ#1 *、グリッドの "編集可能"プロパティを "true"に設定する

*ステップ#2 *、グリッドの列の "editable"プロパティも "true"に、 "rendererIsEditor"を "true"に設定します。

レンダラーをエディターとして設定しているので、itemRendererで更新したものはすべてdataFieldに割り当てられるため、dataFieldを偽のフィールドに設定することが重要です。 dataFieldをint型の "Foo"に設定し、comboBoxのitemRendererを生成する非プリミティブオブジェクトを使用します。 選択すると、そのオブジェクトは "Foo"に割り当てられます。

*ステップ#3 *、グリッドの列の "dataField"プロパティも偽のフィールドに設定する。

それでは、itemRendererでタブ操作ができるようにしましょう。

これは最適化されたバージョンではないことを私は知っていますが、これは1回目のパスではうまくいくでしょう。

import mx.core.mx_internal; import mx.managers.IFocusManagerComponent;名前空間mx_internalを使用してください。

パブリッククラスFriendlyItemRendererContainerはHBoxの実装を拡張しますIFocusManagerComponent {

パブリック関数FriendlyItemRendererContainer(){super(); addEventListener(FocusEvent.KEY_FOCUS_CHANGE、keyFocusChangeHandler); }

private var _listData:DataGridListData; //これはitemEditorとして機能するために必要です。public var text:String;

プライベート関数keyFocusChangeHandler(event:FocusEvent):void {if(event.keyCode == Keyboard.TAB) event.isDefaultPrevented()

event.preventDefault();

}

}

プライベート関数findNextChildToFocus(shiftKey:Boolean):ブール値{var myChildrenAry:Array = getChildren(); var incr:int = shiftKey? -1:1 var index:int = shiftKey? myChildrenAry.length:0; var focusChildIndex:int = 0; var found:Boolean = false;

for(focusChildIndex = 0; focusChildIndex <myChildrenAry.length; focusChildIndex){if(!(myChildrenAry [focusChildIndex]はUIComponentとして。)||(myChildrenAry [focusChildIndex]はContainer)] {//それが見えないコンテナーの場合Uompそれから続けてください。 }

if(myChildrenAry [focusChildIndex]はTextInput){if(systemManager.stage.focus ==(myChildrenAry [focusChildIndex]はTextInput)です。 found = true;ブレーク; drawFocus(false); else {if(systemManager.stage.focus == myChildrenAry [focusChildIndex])({UIComponentとしてのmyChildrenAry [focusChildIndex]).drawFocus(false);}} found = true;ブレーク; }}}

if(!found){focusChildIndex = 0; }

while(true){focusChildIndex = focusChildIndex incr;

if((focusChildIndex <0)||(focusChildIndex> = myChildrenAry.length)){UIComponentGlobals.nextFocusObject = null; falseを返します。そうでなければ(myChildrenAry [focusChildIndex]がUIComponent){(UIComponentとしてのmyChildrenAry [focusChildIndex]).setFocus(); (UIComponentとしてのmyChildrenAry [focusChildIndex]).drawFocus(true);

ブレーク; }}

trueを返します。 }

public function setFocus()をオーバーライドします。void {var myChildrenAry:Array = getChildren();} if(myChildrenAry.length> 0){(var i:int = 0; i <myChildrenAry.length; i){(((myChildrenAry [i]はUIComponent)です))

}

パブリック関数get listData():BaseListData {return _listData;} }

public function set listData(値:BaseListData):void {_listData = DataGridListData(値); }}

あなたのitemRendererでそれを使用する方法の例:

<

それをgridColumnに入れるだけです。

楽しい。


0


基本的にあなたはフォーカス変更イベントのデフォルトの振舞いを取り除きたいです。 私はあなたがこれをする必要があると思います:

1。 yourRenderer.addEventListener(FocusEvent.KEY_FOCUS_CHANGE、onKeyFocusChange); 2。 タブキーを停止したいので、ハンドラで次のようにします。if(event.keyCode == Keyboard.TAB)event.preventDefault() keyDownハンドラーでTABをキャッチすると、手動でフォーカスを移動できます。