Button skin issue in Flex - apache-flex

I have created a button skin named HTMLBtnBlue.mxml, I created another skin with copy of HTMLBtnBlue.mxml and named it HTMLBtnYellow and changes up color to 0xF8C313.
code for HTMLBtn.mxml is as follow
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo">
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/halo";
.upStyle {
color: #FF0000;
}
.overStyle {
color: #009900;
}
.downStyle {
color: #00FF00;
}
.disabledStyle {
color: #666666;
}
</fx:Style>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Label
id="labelDisplay"
styleName.up="upStyle"
styleName.over="overStyle"
styleName.down="downStyle"
styleName.disabled="disabledStyle"/>
<s:Rect width="100%" height="1" includeIn="over,up" bottom="0">
<s:fill>
<s:SolidColor color.over="#009900" color.up="#0000FF"/>
</s:fill>
</s:Rect>
</s:Skin>
The code for buttons is as follows
<s:Button label="Open Menu" id="bluebtn" skinClass="skins.HTMLBtn" />
<s:Button label="Close Menu" id="yellowbtn" skinClass="skins.YellowSkin" />
but it applies HTMLBtn skin to both Open Menu and Close Menu button.

Following your example above in Flash Builder 4.6 with AIR 3.4 :
<s:Button id="bluebtn" label="Open Menu" skinClass="skins.HTMLBtnBlue"/>
<s:Button id="yellowbtn" label="Close Menu" skinClass="skins.HTMLBtnYellow"/>
I had no problems with this.
Skin Class "HTMLBtnYellow":
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo">
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/halo";
.upStyle {
color: #FF0000;
}
.overStyle {
color: #009900;
}
.downStyle {
color: #00FF00;
}
.disabledStyle {
color: #666666;
}
</fx:Style>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Rect width="100%" height="1" includeIn="over,up" bottom="0">
<s:fill>
<s:SolidColor color.over="#009900" color.up="#F8C313"/>
</s:fill>
</s:Rect>
<s:Label
id="labelDisplay"
styleName.up="upStyle"
styleName.over="overStyle"
styleName.down="downStyle"
styleName.disabled="disabledStyle"/>
Skin Class "HTMLBtnBlue":
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo">
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/halo";
.upStyle {
color: #FF0000;
}
.overStyle {
color: #009900;
}
.downStyle {
color: #00FF00;
}
.disabledStyle {
color: #666666;
}
</fx:Style>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Label
id="labelDisplay"
styleName.up="upStyle"
styleName.over="overStyle"
styleName.down="downStyle"
styleName.disabled="disabledStyle"/>
<s:Rect width="100%" height="1" includeIn="over,up" bottom="0">
<s:fill>
<s:SolidColor color.over="#009900" color.up="#0000FF"/>
</s:fill>
</s:Rect>

Related

Adobe Flex Show Content inside Rectangle (itemRenderer)

I have a simple question, but at first I describe the scenario:
Just wrote my first ItemRenderer for testing suppose. I got a userlist view in my application and declared some objects in a dataprovider on it. On the itemRenderer, I want to display each object (user with name and an icon) inside of a rectangle in a TileGroup. My problem is now, that the rectangle is displayed next to the (user-)objects and not around it and component declarations inside the rectangle are not allowed.
This is the code of my itemRenderer:
<s:TileGroup requestedColumnCount="4" requestedRowCount="1">
<s:Rect id="infoRect" width="100%" height="100%" left="0" right="0">
<s:stroke>
<s:SolidColorStroke color="0xFFFFFF" weight="1" />
</s:stroke>
<s:fill>
<s:SolidColor color="white" />
</s:fill>
</s:Rect>
<s:VGroup width="100%" height="100%">
<s:Label id="labelName" text="Name: {data.Name}"
color="red" />
<s:Label id="labelVerbindung" text="Verbindung: {data.Verbindung}"
color="red" />
<s:BitmapImage id="labelIcon" source="{data.Icon}" />
</s:VGroup>
</s:TileGroup>
As workaround I tried to use simple CSS and gave the VGroup the following attributes styleName=".borderClass", but also that showed no effect:
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
.borderClass {
border-style: solid;
border-width: 3px;
border-color: red;
}
</fx:Style>
Any recommendations on how to solve this?
Okay, I am simply stupid... just used a BorderContainer instead of a Rectangle and it works perfectly fine.

Flex 4.6 DropDownlist with an icon

I have some problem to do a simple dropdownlist with an icon to the left of entries.
I have already done the itemRenderer part so when I open the dropdownlist everything is fine. I have issue with the main skin:
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled=".5">
<!-- host component -->
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.DropDownList")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
/* Define the content fill items that should be colored by the "contentBackgroundColor" style. */
static private const contentFill:Array = ["bgFill"];
/**
* #private
*/
override public function get contentItems():Array {return contentFill};
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
if (getStyle("borderVisible") == false)
{
if (border)
border.visible = false;
if (background)
{
background.left = background.top = background.right = background.bottom = 0;
}
if (scroller)
scroller.minViewportInset = 0;
}
else
{
if (border)
border.visible = true;
if (background)
{
background.left = background.top = background.right = background.bottom = 1;
}
if (scroller)
scroller.minViewportInset = 1;
}
if (dropShadow)
dropShadow.visible = getStyle("dropShadowVisible");
openButton.setStyle("cornerRadius", getStyle("cornerRadius"));
if (borderStroke)
{
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="open" />
<s:State name="disabled" />
</s:states>
<!---
The PopUpAnchor control that opens the drop-down list.
<p>In a custom skin class that uses transitions, set the
<code>itemDestructionPolicy</code> property to <code>never</code>.</p>
-->
<s:PopUpAnchor id="popUp" displayPopUp.normal="false" displayPopUp.open="true" includeIn="open"
left="0" right="0" top="0" bottom="0" itemDestructionPolicy="auto"
popUpPosition="below" popUpWidthMatchesAnchorWidth="true">
<!---
This includes borders, background colors, scrollers, and filters.
#copy spark.components.supportClasses.DropDownListBase#dropDown
-->
<s:Group id="dropDown">
<!--- #private -->
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.45" distance="7"
angle="90" color="#000000" left="0" top="0" right="0" bottom="0"/>
<!--- #private -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0">
<s:stroke>
<!--- border stroke #private -->
<s:SolidColorStroke id="borderStroke" weight="1"/>
</s:stroke>
</s:Rect>
<!-- fill -->
<!--- Defines the appearance of drop-down list's background fill. -->
<s:Rect id="background" left="1" right="1" top="1" bottom="1" >
<s:fill>
<!---
The color of the drop down's background fill.
The default color is 0xFFFFFF.
-->
<s:SolidColor id="bgFill" color="0xFFFFFF" />
</s:fill>
</s:Rect>
<!--- #private -->
<s:Scroller id="scroller" left="0" top="0" right="0" bottom="0" hasFocusableChildren="false" minViewportInset="1">
<!--- #copy spark.components.SkinnableDataContainer#dataGroup-->
<s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="contentJustify" requestedMinRowCount="1" requestedMaxRowCount="6"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
</s:Group>
</s:PopUpAnchor>
<!--- The default skin is DropDownListButtonSkin.
#copy spark.components.supportClasses.DropDownListBase#openButton
#see spark.skins.spark.DropDownListButtonSkin -->
<s:Button id="openButton" left="0" right="0" top="0" bottom="0" focusEnabled="false" tabEnabled="false"
skinClass="spark.skins.spark.DropDownListButtonSkin" />
<!--- #copy spark.components.DropDownList#labelDisplay
<s:Label id="labelDisplay" verticalAlign="middle" maxDisplayedLines="1"
mouseEnabled="false" mouseChildren="false"
left = "7" right = "30" top = "2" bottom = "2" width = "75" verticalCenter = "1" / > -->
<s:HGroup left="5" right="30" top="2" bottom="2" verticalAlign="middle" verticalCenter="1" paddingTop="5" paddingBottom="5">
<s:BitmapImage id="bitmapIcon" top="0" width="34" height="34" source="{hostComponent.selectedItem.icon}"/>
<s:Label id="labelDisplay" verticalAlign="middle" maxDisplayedLines="1" mouseEnabled="false" mouseChildren="false" left="3" right="30" top="2" bottom="2" verticalCenter="1" />
</s:HGroup>
The important part is :
<s:HGroup left="5" right="30" top="2" bottom="2" verticalAlign="middle" verticalCenter="1" paddingTop="5" paddingBottom="5">
<s:BitmapImage id="bitmapIcon" top="0" width="34" height="34" source="{hostComponent.selectedItem.icon}"/>
<s:Label id="labelDisplay" verticalAlign="middle" maxDisplayedLines="1" mouseEnabled="false" mouseChildren="false" left="3" right="30" top="2" bottom="2" verticalCenter="1" />
</s:HGroup>
The "hostComponent.selectedItem.icon" don't work anymore in flex 4.6, I have this warning:
warning: unable to bind to property 'icon' on class 'Object' (class is not an IEventDispatcher)
I don't know how to set the value by other way...
ok I think I figured out...
I have to create a custom Class DropDownListIcon for example, with an [Bindable] public var icon:Class;
I override selectedItem and set icon.
override public function set selectedItem(value:*):void
{
super.selectedItem = value;
if ( value ) icon = value.icon;
}
And in DropDownListSkin I get the icon from the hostComponent.
<s:BitmapImage id="bitmapIcon" top="0" width="34" height="34" source="{hostComponent.icon}"/>

how to get ActionBar at the bottom in Flex mobile Application

ViewNavigator has ActionBar on top by default. I want move at the bottom.
navigator.actionbar.y=415 //gets actionbar at bottom
but in next view it comes back on top. You can set height in each view but it will show bar at the top for few seconds before bring back to bottom.
You want to skin the ViewNavigator to put the ActionBar on the bottom.
In the main app, you can add a style:
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
s|ViewNavigator {
skinClass: ClassReference("CustomViewNavigatorSkin")
}
</fx:Style>
Then, create your CustomViewNavigatorSkin class:
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<!-- host component -->
<fx:Metadata>
[HostComponent("spark.components.ViewNavigator")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="landscapeAndOverlay" />
<s:State name="portraitAndOverlay" />
<s:State name="landscape" />
<s:State name="portrait" />
<s:State name="disabled" />
<s:State name="normal" />
</s:states>
<s:VGroup width="100%" height="100%">
<s:VGroup id="contentGroup" height="100%" width="100%" />
<s:ActionBar id="actionBar" width="100%" />
</s:VGroup>
</s:Skin>

Flex 4 Spark component Panel - Hide Title Bar

I have used Spark panel to display the object inside a container. The panel and the inside elements are created dynamically. (using ActionScript). I need to remove the title bar of the panel in actionscript. When I tried to remove that, I am unable to hide the same.
Tried below ways.
Used style (classname) and set headerheight = 0.
Override the panel component and used the property this.titleBar.visible = false.
But not able to hide the titlebar.
I have used Panel spark component and Flash Builder 4.5 for development.
If there is any other way to achieve this, please let me know.
Your best bet is to create a custom skin and move the title bar pieces from the skin. It was very quick to put together a sample.
This is your custom skin; created as a copy of the PanelSkin with visual elements commented out.
<?xml version="1.0" encoding="utf-8"?>
<!--
ADOBE SYSTEMS INCORPORATED
Copyright 2008 Adobe Systems Incorporated
All Rights Reserved.
NOTICE: Adobe permits you to use, modify, and distribute this file
in accordance with the terms of the license agreement accompanying it.
-->
<!--- The default skin class for a Spark Panel container.
#see spark.components.Panel
#langversion 3.0
#playerversion Flash 10
#playerversion AIR 1.5
#productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" blendMode="normal" mouseEnabled="false"
minWidth="131" minHeight="127" alpha.disabled="0.5" alpha.disabledWithControlBar="0.5">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Panel")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
import mx.core.FlexVersion;
/* Define the skin elements that should not be colorized.
For panel, border and title background are skinned, but the content area, background, border, and title text are not. */
static private const exclusions:Array = ["background", "titleDisplay", "contentGroup", "controlBarGroup", "border"];
/* exclusions before Flex 4.5 for backwards-compatibility purposes */
static private const exclusions_4_0:Array = ["background", "titleDisplay", "contentGroup", "controlBarGroup"];
/**
* #private
*/
override public function get colorizeExclusions():Array
{
// Since border is styleable via borderColor, no need to allow chromeColor to affect
// the border. This is wrapped in a compatibility flag since this change was added
// in Flex 4.5
if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5)
{
return exclusions_4_0;
}
return exclusions;
}
/**
* #private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
if (getStyle("borderVisible") == true)
{
border.visible = true;
background.left = background.top = background.right = background.bottom = 1;
contents.left = contents.top = contents.right = contents.bottom = 1;
}
else
{
border.visible = false;
background.left = background.top = background.right = background.bottom = 0;
contents.left = contents.top = contents.right = contents.bottom = 0;
}
dropShadow.visible = getStyle("dropShadowVisible");
var cr:Number = getStyle("cornerRadius");
var withControls:Boolean =
(currentState == "disabledWithControlBar" ||
currentState == "normalWithControlBar");
if (cornerRadius != cr)
{
cornerRadius = cr;
dropShadow.tlRadius = cornerRadius;
dropShadow.trRadius = cornerRadius;
dropShadow.blRadius = withControls ? cornerRadius : 0;
dropShadow.brRadius = withControls ? cornerRadius : 0;
setPartCornerRadii(topMaskRect, withControls);
setPartCornerRadii(border, withControls);
setPartCornerRadii(background, withControls);
}
if (bottomMaskRect) setPartCornerRadii(bottomMaskRect, withControls);
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
backgroundFill.color = getStyle("backgroundColor");
backgroundFill.alpha = getStyle("backgroundAlpha");
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
/**
* #private
*/
private function setPartCornerRadii(target:Rect, includeBottom:Boolean):void
{
target.topLeftRadiusX = cornerRadius;
target.topRightRadiusX = cornerRadius;
target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0;
target.bottomRightRadiusX = includeBottom ? cornerRadius : 0;
}
private var cornerRadius:Number;
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="normalWithControlBar" stateGroups="withControls" />
<s:State name="disabledWithControlBar" stateGroups="withControls" />
</s:states>
<!-- drop shadow can't be hittable so it stays sibling of other graphics -->
<!--- #private -->
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.32" distance="11"
angle="90" color="#000000" left="0" top="0" right="0" bottom="0"/>
<!-- drop shadow can't be hittable so all other graphics go in this group -->
<s:Group left="0" right="0" top="0" bottom="0">
<!-- top group mask -->
<!--- #private -->
<s:Group left="1" top="1" right="1" bottom="1" id="topGroupMask" >
<!--- #private -->
<s:Rect id="topMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!-- bottom group mask -->
<!--- #private -->
<s:Group left="1" top="1" right="1" bottom="1" id="bottomGroupMask"
includeIn="normalWithControlBar, disabledWithControlBar">
<!--- #private -->
<s:Rect id="bottomMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!-- layer 1: border -->
<!--- #private -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0" >
<s:stroke>
<!--- #private -->
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
<!-- layer 2: background fill -->
<!--- Defines the appearance of the PanelSkin class's background. -->
<s:Rect id="background" left="1" top="1" right="1" bottom="1">
<s:fill>
<!--- #private
Defines the PanelSkin class's background fill. The default color is 0xFFFFFF. -->
<s:SolidColor id="backgroundFill" color="#FFFFFF"/>
</s:fill>
</s:Rect>
<!-- layer 3: contents -->
<!--- Contains the vertical stack of titlebar content and controlbar. -->
<s:Group left="1" right="1" top="1" bottom="1" id="contents">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<!--- #private -->
<!-- <s:Group id="topGroup" mask="{topGroupMask}">
-->
<!-- layer 0: title bar fill -->
<!--- #private -->
<!-- <s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xE2E2E2" />
<s:GradientEntry color="0xD9D9D9" />
</s:LinearGradient>
</s:fill>
</s:Rect>
-->
<!-- layer 1: title bar highlight -->
<!--- #private -->
<!-- <s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xEAEAEA" />
<s:GradientEntry color="0xD9D9D9" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
-->
<!-- layer 2: title bar divider -->
<!--- #private -->
<!-- <s:Rect id="tbDiv" left="0" right="0" height="1" bottom="0">
<s:fill>
<s:SolidColor color="0xC0C0C0" />
</s:fill>
</s:Rect>
-->
<!-- layer 3: text -->
<!--- #copy spark.components.Panel#titleDisplay -->
<!-- <s:Label id="titleDisplay" maxDisplayedLines="1"
left="9" right="3" top="1" bottom="0" minHeight="30"
verticalAlign="middle" textAlign="start" fontWeight="bold">
</s:Label>
-->
<!-- </s:Group>
-->
<!--
Note: setting the minimum size to 0 here so that changes to the host component's
size will not be thwarted by this skin part's minimum size. This is a compromise,
more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
-->
<!--- #copy spark.components.SkinnableContainer#contentGroup -->
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0">
</s:Group>
<!--- #private -->
<s:Group id="bottomGroup" minWidth="0" minHeight="0"
includeIn="normalWithControlBar, disabledWithControlBar" >
<s:Group left="0" right="0" top="0" bottom="0" mask="{bottomGroupMask}">
<!-- layer 0: control bar divider line -->
<s:Rect left="0" right="0" top="0" height="1" alpha="0.22">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<!-- layer 1: control bar highlight -->
<s:Rect left="0" right="0" top="1" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xE5E5E5" />
<s:GradientEntry color="0xD8D8D8" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 2: control bar fill -->
<s:Rect left="1" right="1" top="2" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xDADADA" />
<s:GradientEntry color="0xC5C5C5" />
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:Group>
<!-- layer 3: control bar -->
<!--- #copy spark.components.Panel#controlBarGroup -->
<s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" minWidth="0" minHeight="0">
<s:layout>
<s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="7" paddingBottom="7" gap="10" />
</s:layout>
</s:Group>
</s:Group>
</s:Group>
</s:Group>
</s:SparkSkin>
And this is the app:
<?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">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup>
<s:Panel />
<s:Panel skinClass="PanelNoTitleBar"/>
</s:VGroup>
</s:WindowedApplication>
The first panel will display the original skin; the second panel displays the custom skin; with no title bar.
Skinning is the common advice, and apparently that is the intended design. The other answer does a fine job of showing this method.
However, there is also a nice subclassing solution on a related question: Flex 4 spark Panel has an ugly gray top part. That may be enough if you only want to remove the title bar.

Flex 4.5 - Spark DropDownList - DropDown's minimum width is the anchor's width

I am using spark DropDownLists and I don't want to see any horizontal scrollbars in the dropdown. I'm OK with the dropdown being wider than the anchor, so I have a custom skin that sets popUpWidthMatchesAnchorWidth to false. But I don't want the dropdown to ever be smaller than the anchor. This is my dilemma.
I came up with a solution that sometimes works, but there is something wrong with it. My DropDownList skin is as follows:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled=".5" minHeight="25">
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.DropDownList")]
]]>
</fx:Metadata>
<fx:Script>
<![CDATA[
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
// anchor width is the min width of the dropdown
if (dropDown && openButton && popUp && dropDown.getExplicitOrMeasuredWidth() < openButton.getExplicitOrMeasuredWidth())
popUp.popUpWidthMatchesAnchorWidth = true;
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" stateGroups="closed" />
<s:State name="open" />
<s:State name="disabled" stateGroups="closed" />
</s:states>
<s:PopUpAnchor id="popUp" displayPopUp.normal="false" displayPopUp.open="true" includeIn="open"
left="0" right="0" top="0" bottom="0" itemDestructionPolicy="auto"
popUpPosition="below" popUpWidthMatchesAnchorWidth="false">
<s:Group id="dropDown" maxHeight="134" minHeight="22" >
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.45" distance="7"
angle="90" color="#000000" left="0" top="0" right="0" bottom="0"/>
<s:Rect id="border" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1"/>
</s:stroke>
</s:Rect>
<s:Rect id="background" left="1" right="1" top="1" bottom="1" >
<s:fill>
<s:SolidColor color="#222222"/>
</s:fill>
</s:Rect>
<s:Scroller id="scroller" left="0" top="0" right="0" bottom="0" hasFocusableChildren="false" minViewportInset="1">
<s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="contentJustify"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
</s:Group>
</s:PopUpAnchor>
<s:Button id="openButton" left="0" right="0" top="0" bottom="0" focusEnabled="false" alpha.disabled="0.5"
skinClass.closed="assets.skins.dropDownList.dropDownListNormalButtonSkin"
skinClass.open="assets.skins.dropDownList.dropDownListOpenButtonSkin"/>
<s:Label id="labelDisplay" verticalAlign="middle" maxDisplayedLines="1"
mouseEnabled="false" mouseChildren="false"
left="7" right="30" top="2" bottom="2" width="75" verticalCenter="1" />
</s:SparkSkin>
This works as expected when the contents of the dropdown are either wider than the anchor or smaller than about 100px, but if I explicitly set the width in the instance of the DropDownList to be something like 200px and the contents of the dropdown are around 150px wide, the dropdown is smaller than the anchor.
Basically, it looks like openButton.getExplicitOrMeasuredWidth() returns about 100, regardless of what I set the DropDownList's width to be.
How can I change this so that I can have multiple DropDownLists with different widths, but always making sure that the dropdown's width is either greater than or equal to the anchor's width?
You Said:
"but if I explicitly set the width in the instance of the DropDownList to be something like 200px and the contents of the dropdown are around 150px wide, the dropdown is smaller than the anchor."
So if you explicitly set the width, then this.width is always reliable. Simply replace the button.getExplicitOrMeasuredWidth() with this.width, problem solved.
if (dropDown && openButton && popUp && dropDown.getExplicitOrMeasuredWidth() < this.width)
popUp.popUpWidthMatchesAnchorWidth = true;
I suggest you using openButton.width instead of openButton.getExplicitOrMeasuredWidth().

Resources