2011-06-24 52 views
0

我需要創建一個菜單組件,其中每個菜單項看起來是這樣的:Flex菜單的快捷鍵和自定義渲染

圖標標籤右對齊鍵盤的快捷

我試圖創建一個自定義菜單項渲染器,但a)鍵盤快捷鍵未對齊 b)子菜單存在很多問題。

我也嘗試使用數據網格和麪板和它們的混合來繪製這種菜單,但它太混亂了。

任何關於如何實現這一目標的指針?

編輯:添加源代碼

Main.mxml 

<mx:Style source="assets/main.css" /> 

<mx:Script> 
    <![CDATA[ 
     import FlyOutMenuItem; 
     import FlyOutMenuRenderer; 
     import com.jusfortechies.controls.CustomMenuItemRenderer; 
     import com.jusfortechies.controls.ValueObject; 

     import mx.collections.ArrayCollection; 
     import mx.controls.Menu; 
     import mx.events.CollectionEvent; 
     import mx.events.MenuEvent; 

     [Bindable] 
     private var myMenuData:ArrayCollection = new ArrayCollection(); 

     [Bindable] 
     private var mainMenuData:ArrayCollection = new ArrayCollection(); 

     [Bindable] 
     [Embed(source="Button.png")] 
     public var Button:Class; 

     [Bindable] 
     public var state:Boolean = false; 

     [Bindable] 
     private var myMenu:Menu; 

     [Bindable] 
     private var mainMenu:Menu; 

     // Create and display the Menu control. 
     private function createAndShow():void { 

      mainMenu = Menu.createMenu(null, mainMenuData, false); 
      mainMenu.labelField="label"; 

      //myMenu.itemRenderer = new ClassFactory(CustomMenuItemRenderer); 
      mainMenu.itemRenderer = new ClassFactory(FlyOutMenuRenderer); 

      mainMenu.addEventListener(KeyboardEvent.KEY_DOWN,handleFlyOutMenuKeyStroke); 
      mainMenu.addEventListener(KeyboardEvent.KEY_UP,handleFlyOutMenuKeyStrokeUp); 
      mainMenu.addEventListener(MenuEvent.ITEM_CLICK,handleFlyOutMenuHandleClick); 

      myMenu = Menu.createMenu(mainMenu, myMenuData, false); 
      myMenu.labelField="label"; 

      //myMenu.itemRenderer = new ClassFactory(CustomMenuItemRenderer); 
      myMenu.itemRenderer = new ClassFactory(FlyOutMenuRenderer); 

      myMenu.addEventListener(KeyboardEvent.KEY_DOWN,handleFlyOutMenuKeyStroke); 
      myMenu.addEventListener(KeyboardEvent.KEY_UP,handleFlyOutMenuKeyStrokeUp); 
      myMenu.addEventListener(MenuEvent.ITEM_CLICK,handleFlyOutMenuHandleClick); 

      mainMenu.addChild(myMenu); 

      //Position the menu and show it when the button is clicked 
      mainMenu.show((this.width/2 - this.myButton.width/2), 50); 
     } 

     protected function handleFlyOutMenuKeyStrokeUp(event:KeyboardEvent):void { 
      state = false; 
     } 

     protected function handleFlyOutMenuKeyStroke(event:KeyboardEvent):void { 
      trace("target:"+event.currentTarget+"state:"+state+";keycode:"+event.keyCode); 

      // tried to check for keycode's like 2, 3 which correspond to ctrl+b and ctrl+c respectively 
      // did not work. Hence go for state based individual key check 

      if(event.keyCode == Keyboard.ESCAPE && myMenu.visible) { 
       myMenu.hide(); 
      } else if (state) { 
       if (event.keyCode >=65 && event.keyCode <= 90) { // check if any alphabet was pressed after control key 
        // A ascii code = 65. But in our data array, A starts at 1 NOT 0. So we detect 65-1 = 64 
        trace("Inside handleFlyOutMenuKeyStroke"+event.keyCode); 
       } 
      } else if(event.keyCode == Keyboard.CONTROL){ 
       state = true; 
       return; 
      } 
      state=false; 

      if(myMenu.visible) { 
       myMenu.hide(); 
      } 
     } 

     protected function handleFlyOutMenuHandleClick(event:MenuEvent):void 
     { 
      if(event.currentTarget == mainMenu){ 
       trace('MainMenu HandleClick'); 
       myMenu.show((mainMenu.x + mainMenu.width), (mainMenu.y + mainMenu.height/2)); 
       //myMenu.show((this.width/2 - this.myButton.width/2), 50); 
      } 
      trace("Inside MenuHandleClick"); 
     } 



     public function init():void { 
      /*mainMenuData.addItem(new ValueObject("MA", "MenuItem A", "menuOddItem")); 
      mainMenuData.addItem(new ValueObject("MB", "MenuItem B", "menuEvenItem")); 
      mainMenuData.addItem(new ValueObject("MC", "MenuItem C", "menuOddItem")); 
      mainMenuData.addItem(new ValueObject("MD", "MenuItem D", "menuEvenItem"));*/ 

      myMenuData.addItem(new FlyOutMenuItem("Item A", "A", "Button")); 
      myMenuData.addItem(new FlyOutMenuItem("Item B", "B", "Button")); 
      myMenuData.addItem(new FlyOutMenuItem("Item CM", "C", "Button")); 
      myMenuData.addItem(new FlyOutMenuItem("Item DE", "D", "Button")); 
     } 
    ]]> 
</mx:Script> 

<mx:VBox> 
    <!-- Define a Button control to open the menu --> 
    <mx:Button id="myButton" initialize="init()" label="Open Menu" click="createAndShow();"/> 
</mx:VBox> 

FlyOutMenuItem.as

包 { [綁定] 酒館lic class FlyOutMenuItem { public var label:String; public var shortCut:String; public var icon:String;

public function FlyOutMenuItem(label:String, shortcut:String, icon:String) 
    { 
     this.label = label + " Ctrl+"+shortcut; 
     this.shortCut = shortcut; 
     this.icon = icon; 
    } 
} 

}

FlyOutMenuRenderer.as

包 { 進口mx.controls.Label; import mx.controls.menuClasses.MenuItemRenderer;

import spark.components.Label; 

[Bindable] 
public class FlyOutMenuRenderer extends MenuItemRenderer 
{ 
    override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void { 

     //Get the style name from Menu VO and set to the menu item 
     //this.styleName = ValueObject(this.data).styleName; 

     this.label.ignorePadding = true; 
     trace("Style.align.MenuRenderer.label:"+this.label.getStyle("textAlign")); 

     super.updateDisplayList(unscaledWidth, unscaledHeight); 
    } 

    public function FlyOutMenuRenderer() 
    { 
     super(); 
    } 
} 

}

CustomMenuItemRenderer.as/*從justfortechies.com */

包com.jusfortechies.controls { 進口mx.controls.menuClasses.MenuItemRenderer;

[Bindable] 
public class CustomMenuItemRenderer extends MenuItemRenderer 
{ 
    override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void { 

     //Get the style name from Menu VO and set to the menu item 
     this.styleName = ValueObject(this.data).styleName; 

     super.updateDisplayList(unscaledWidth, unscaledHeight); 
    } 
} 

}

ValueObject.as/*從justfortechies.com */

包com.jusfortechies.controls { [綁定] 公共類的ValueObject { 公共變種ID:串; public var label:String; public var styleName:String;

public function ValueObject(id:String, label:String, styleName:String) 
    { 
     this.id = id; 
     this.label = label; 
     this.styleName = styleName; 
    } 

} 

}

+0

可以在此添加的代碼爲您自定義項目渲染 – Neeraj

+0

Neeraj ..我編輯我的問題,包括源代碼。所以你可以看到我正在創建一個自定義渲染器,然後我需要像正常菜單一樣顯示所有內容。子菜單顯示得不太好,並且事件處理存在問題。任何指針都會很棒。 – Neo

+0

另外,我試圖用MenuBar來做到這一點。我將在一段時間內收錄這篇文章的源代碼。所以我不能回答我自己的問題,因爲我有一個代表<100. :) – Neo

回答

2

這是菜單欄實驗打算同樣的事情,我的源代碼 - 使用自定義渲染器來顯示不同類型的菜單。

P.S .:這不是這個問題的答案。這篇文章是爲了分離我採取的兩種方法而創建的。

FlyOutMenuItem.as

package 
{ 
    import mx.controls.Menu; 

    [Bindable] 
    public class FlyOutMenuItem extends Menu 
    { 
     public var label:String; 
     public var shortCut:String; 
     public var icon:String; 

     public function FlyOutMenuItem(label:String, shortcut:String, icon:String) 
     { 
      this.label = label + " Ctrl+"+shortcut; 
      trace("Creating new Flyoutmenuitem with label:"+this.label); 
      this.shortCut = shortcut; 
      this.icon = icon; 
     } 
    } 
} 

FlyoutMenuBar.as

package 
{ 
    import mx.controls.Menu; 
    import mx.controls.MenuBar; 
    import mx.core.ClassFactory; 

    [Bindable] 
    public class FlyoutMenuBar extends MenuBar 
    { 
     public function FlyoutMenuBar() 
     { 
      super(); 
     } 

     override public function getMenuAt(index:int) : Menu  
     { 
      var menu:Menu = super.getMenuAt(index); 
      //menu.styleName = "myMenuItemRendererStyleName"; 
      menu.itemRenderer = new ClassFactory(FlyoutMenuItemRenderer); 

      return menu; 
     } 
    } 
} 

FlyoutMenuItemRenderer.as

package 
{ 
    import mx.controls.Alert; 
    import mx.controls.menuClasses.MenuItemRenderer; 
    import mx.core.IFlexDisplayObject; 

    [Bindable] 
    public class FlyoutMenuItemRenderer extends MenuItemRenderer 
    { 
     public function FlyoutMenuItemRenderer() 
     { 
      super(); 
     } 

     [Embed(source="Button.png")] 
     public var Button:Class; 

     override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void { 
      trace("MenuRenderer.label:"+this.label.text+"; id:"+this.id); 
      super.updateDisplayList(unscaledWidth, unscaledHeight); 
     } 
    } 
} 

Main.mxml

<?xml version="1.0" encoding="utf-8"?> 
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx" 
         xmlns:renderers="*"> 
    <fx:Script> 
     <![CDATA[ 
      import FlyOutMenuItem; 

      import mx.collections.ArrayCollection; 
      import mx.controls.Alert; 
      import mx.controls.Menu; 
      import mx.controls.menuClasses.MenuBarItem; 
      import mx.events.FlexEvent; 

      [Bindable] 
      private var menuBarData:ArrayCollection = new ArrayCollection(); 

      protected function flyoutMenuBar_creationCompleteHandler(event:FlexEvent):void 
      { 
       //var numMenus:int = flyoutMenuBar.menus.length; 
       //var numChild:int = flyoutMenuBar.numChildren; 
       //Alert.show("numMenus:"+numMenus+"; numChild:"+numChild, "CreationComplete"); 

       flyoutMenuBar.addChild(new FlyOutMenuItem("Item A", "A", "Button")); 
       var child:Menu = flyoutMenuBar.getMenuAt(0); 
      } 

     ]]> 
    </fx:Script> 
    <fx:Declarations> 
     <!-- Place non-visual elements (e.g., services, value objects) here --> 
     <fx:XML id="mainMenuBarButtonData"> 
      <root> 
       <menuitem label="Flyout Menu"> 
        <menuitem label="ABC"/> 
        <menuitem label="DEF"> 
         <menuitem label="GHI" /> 
        </menuitem> 
       </menuitem> 
      </root> 
     </fx:XML> 
    </fx:Declarations> 
    <renderers:FlyoutMenuBar id="flyoutMenuBar" creationComplete="flyoutMenuBar_creationCompleteHandler(event)" 
       labelField="@label" dataProvider="{mainMenuBarButtonData}" showRoot="false"> 
    </renderers:FlyoutMenuBar> 

</s:WindowedApplication>