我需要创建一个菜单组件,其中每个菜单项如下所示:
图标标签右对齐键盘快捷键
我尝试创建自定义菜单项渲染器,但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
包 { [绑定] 公共类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
包 { import 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();
}
}
}
来自justfortechies.com的CustomMenuItemRenderer.as / * * /
包com.jusfortechies.controls { import 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);
}
}
}
来自justfortechies.com的ValueObject.as / * * /
包com.jusfortechies.controls { [绑定] 公共类ValueObject { public var id:String; 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 :(得分:2)
这是我打算做同样事情的MenuBar实验的源代码 - 使用自定义渲染器显示不同类型的菜单。
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>