【flex手机项目】教你美化ActionBar

本文详细介绍了ActionBar组件在移动应用开发中的重要性,包括其在不同视图中的配置方法、如何自定义外观及布局,并通过实例展示了如何使用CSS和自定义皮肤来实现个性化外观。
One of the important pieces of the Flex framework for mobile development is the  ActionBar  class. This class lets you create an application title bar with three distinct areas. Starting from left to right you can have a navigation area, a title area, and an actions area. Of course you are not forced to use all these areas.
Why would you want to use this component? There are many reasons for using it but probably the most important is that it is an established user interaction design pattern on Android and iOS. This is how you usually add things like an application or section title, navigation buttons, search input texts, or action buttons.

Here are two screen shots of the Facebook application running on Android and iOS that illustrates this idea:
 
Using the ActionBar component Using the  ActionBar  component is quite easy. First, you’ll need to create a Flex mobile project that uses either  ViewNavigatorApplication  or  TabbedViewNavigatorApplication . Then, you can define the components you want to add to the  ActionBar  either globally (for all the  Views)  or individually (for each  View) .
If you want to add them inside of a  View  here is how you do it:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:View xmlns:fx="http://ns.adobe.com/mxml/2009"      xmlns:s="library://ns.adobe.com/flex/spark"> <s:navigationContent>
  3.      <s:Button label="Back"/>
  4. </s:navigationContent> 
  5. <s:titleContent>
  6.      <s:TextInput prompt="type to search" width="100%"/>
  7. </s:titleContent>
  8. <s:actionContent>
  9.      <s:Button label="+"/> 
  10. </s:actionContent>
  11. </s:View>
复制代码

This code produces the following  ActionBar :

If you want to set it globally then the method differe slightly depending on what Application root tag you chose when creating the project ( ViewNavigatorApplication  or  TabbedViewNavigatorApplication ). For  ViewNavigatorApplication  you’d do something like this:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"       xmlns:s="library://ns.adobe.com/flex/spark"       firstView="views.ActionBarHomeView"> <s:navigationContent>
  3.       <s:Button label="Back"/>
  4. </s:navigationContent> 
  5. <s:titleContent>
  6.       <s:TextInput prompt="type to search" width="100%"/>
  7. </s:titleContent> 
  8. <s:actionContent> 
  9.      <s:Button label="+"/>
  10. </s:actionContent>
  11. </s:ViewNavigatorApplication>

  12. And for TabbedViewNavigatorApplication you’d add one for each tab you have in your application. For example:

  13. <?xml version="1.0" encoding="utf-8"?>
  14. <s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"       xmlns:s="library://ns.adobe.com/flex/spark">
  15. <s:ViewNavigator label="Tab 1" width="100%" height="100%" firstView="views.Tab1View">
  16.       <s:navigationContent>
  17.            <s:Button label="Back"/>
  18.       </s:navigationContent>
  19.       <s:titleContent>
  20.            <s:TextInput prompt="type to search" width="100%"/>
  21.       </s:titleContent>
  22.       <s:actionContent> 
  23.           <s:Button label="+"/>
  24.       </s:actionContent>
  25. </s:ViewNavigator>
  26. <s:ViewNavigator label="Tab 2" width="100%" height="100%" firstView="views.Tab2View">
  27. </s:ViewNavigator>
  28. </s:TabbedViewNavigatorApplication>
复制代码

And here is how this code looks like at runtime:

If you set the  ActionBar  globally and you want to override a section or all sections in a particular  View  all you have to do is to set that section/sections in the  View.
You should also know that you can control the  ActionBar  visibility and rendering mode. For example in any  View  in which you want to hide the  ActionBar  you can set  actionBarVisible = false . By default the  ActionBar  is rendered so it takes up some of the available space for the rest of your application. If you want to have the bar hovering on top of the rest of your application you can set the  overlayControls  to  true  in your  View .
Understanding how the ActionBar component works Let’s see how everything is put together. Each part of the ActionBar  (navigation, title, and action content) is actually a Spark Group object. If you open the  ActionBar  class file you’ll find three properties named:  actionGroup navigationGroup , and  titleGroup . These Groups are populated by calling the setter methods:  actionContent() titleContent() , and  navigationContent() . These methods are called by the  View  class to push the components you set for each section and the argument is an Array (you can set a Button or a number of UI components for each section).
How about the layout used by these three groups? Well you can set a different layout than the default by calling the actionLayout navigationLayout , and  titleLayout  setters.
The  ActionBar  component is a Spark component and this means that the task for laying out the various UI components that you can add to each section is actually implemented by a skin class. And of course the look and feel is implemented by the same skin class. The default skin is  spark.skins.mobile.ActionBarSkin . This class extends the  MobileSkin  class, which in turns extends the  UIComponent .
The interesting parts in the skin class are these three methods:  createChildren() measure() , and  layoutContents() .
If you take a look at the  createChildren()  method you will see that here is where the three groups ( navigationGroup , actionGroup , and  titleGroup ) used for each section are actually created and the default layout is set. Also you can see that the default layout used by each group is  HorizontalLayout . Here is a snippet of the code that creates the  navigationGroup :
  1. navigationGroup = new Group();
  2. var hLayout:HorizontalLayout = new HorizontalLayout();
  3. hLayout.horizontalAlign = HorizontalAlign.LEFT;
  4. hLayout.verticalAlign = VerticalAlign.MIDDLE;
  5. hLayout.gap = 0;
  6. hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight        = hLayout.paddingBottom = 0;
  7. navigationGroup.layout = hLayout;
  8. navigationGroup.id = "navigationGroup";
复制代码

The  measure()  method is executed executed after the  createChildren()  method or when the  invalidateSize()  method is executed. As the name implies, this method measures the width and the height of the  ActionBar  taking into consideration the padding (left, right, top, and bottom) and each group width and height ( navigationGroup titleGroup , and actionGroup ). It is important to note that the height of the  ActionBar  is determined by the highest element you have, if this height is bigger than the default height. In other words if you add a  Button  and set the height of the button to 200, then the  ActionBar  height will be 200 pixels.
And finally the  layoutContent()  method is responsible for positioning and setting the size of each  Group . This method positions each group starting from left to right with the  navigationGroup titleGroup , and  actionGroup . If the total width of the  navigationGroup  and  actionGroup  is equal to or more than the total available width then the  titleGroup  is not displayed (visible = false).
Here is a graphical representation of how these different parts are related:

Skinning the ActionBar component Let’s talk about styling the ActionBar component. Out of the box you can quite easily change the appearance using the CSS properties. For example you can use CSS to transform the default look and feel  of the  ActionBar  presented in a screen shot at the beginning of this article to something like this with a little bit of CSS:

And the CSS code that does this is this (please note that you have to include the CSS code or file in the main application file and not in the  Views ):
  1. <fx:Style>@namespace s "library://ns.adobe.com/flex/spark";s|ActionBar {      chromeColor: #484877;      defaultButtonAppearance: beveled;}</fx:Style>
复制代码

The second CSS property in the code above (defaultButtonAppearance) is responsible for rendering the buttons in iOS style. If you inspect the  ActionBar  class you will find all the important CSS properties that you can play with.
If you want to go beyond background and font colors, sizes, and so forth you have to go down the road of creating a custom skin. And the easiest way to do this is to extend the  ActionBarSkin  class.
Here are the important parts of the  ActionBarSkin  class from a skinning perspective:


  • border and borderClass properties. Border represents the first child of the ActionBarSkin (take a look at thecreateChildren() method).BorderClass is a reference to an FXG file that is set in the class constructor depending on the applicationDPI value. The borderClass is used for creating the borders of the ActionBar and the shadow at the bottom. Here is a screen shot of what this looks like (I placed a pinkish background behind the graphics to provide some contrast for the highlights you can notice on the left/right side):



  • drawBackground() method. This method is responsible for drawing the background. In the previous screen shots this is where the black or dark blue color is coming from. If you take a look at this method you will notice that it uses CSS properties (default or set by the programmer) to draw a gradient.
I think that in the most of cases, when you want to skin an  ActionBar  component you’ll likely modify the  drawBackground() method and create a different  borderClass  FXG file.
Let me show you an example of a custom skinning. There are three steps involved in this.
First, I created a new FXG file to be used for the background. To do this I opened up the FXG file used by default by the ActionBarSkin  in Adobe Illustrator (you can find the path for this FXG in the  ActionBarSkin  constructor). And I added three green rectangles (some with a solid color, others with a transparent gradient). Here is the result in Illustrator:

Then, I exported the FXG file as an FXG. And I opened this file in a text editor to remove some of the tags and attributes introduced by Illustrator. Finally, I add the FXG file to the Flex mobile project.



    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008"
    3.     scaleGridLeft="2" scaleGridTop="3" scaleGridRight="88" scaleGridBottom="61">

    4.     <Rect y="2" width="89.8335" height="60">
    5.         <fill>
    6.           <SolidColor color="#16938D"/>
    7.         </fill>
    8.       </Rect>
    9.       <Rect x="0.0830078" y="35" width="89.8335" height="26.6665" >
    10.         <fill>
    11.           <LinearGradient x="44.9165" y="0" scaleX="26.6665" rotation="90">
    12.             <GradientEntry ratio="0" color="#FFFFFF" alpha="0"/>
    13.             <GradientEntry ratio="0.160132" color="#E2E2E2" alpha="0.126504"/>
    14.             <GradientEntry ratio="0.400165" color="#A9A9A9" alpha="0.31613"/>
    15.             <GradientEntry ratio="1" alpha="0.79"/>
    16.           </LinearGradient>
    17.         </fill>
    18.       </Rect>
    19.       <Rect y="1.89014" width="89.8335" height="21.3774" >
    20.         <fill>
    21.           <LinearGradient x="44.9165" y="21.3774" scaleX="21.3774" rotation="270">
    22.             <GradientEntry ratio="0" color="#FFFFFF" alpha="0"/>
    23.             <GradientEntry ratio="1" color="#FFFFFF"/>
    24.           </LinearGradient>
    25.         </fill>
    26.       </Rect>
    27.       <Rect width="90" height="2">
    28.         <fill>
    29.           <SolidColor alpha="0.75"/>
    30.         </fill>
    31.       </Rect>
    32.       <Rect y="62" width="90" height="2">
    33.         <fill>
    34.           <SolidColor alpha="0.85"/>
    35.         </fill>
    36.       </Rect>
    37.       <Rect y="64" width="90" height="1">
    38.         <fill>
    39.           <SolidColor alpha="0.35"/>
    40.         </fill>
    41.       </Rect>
    42.       <Rect y="65" width="90" height="1">
    43.         <fill>
    44.           <SolidColor alpha="0.25"/>
    45.         </fill>
    46.       </Rect>
    47.       <Rect y="66" width="90" height="1">
    48.         <fill>
    49.           <SolidColor alpha="0.2"/>
    50.         </fill>
    51.       </Rect>
    52.       <Rect y="67" width="90" height="1">
    53.         <fill>
    54.           <SolidColor alpha="0.15"/>
    55.         </fill>
    56.       </Rect>
    57.       <Rect y="68" width="90" height="1">
    58.         <fill>
    59.           <SolidColor alpha="0.1"/>
    60.         </fill>
    61.       </Rect>
    62.       <Rect y="69" width="90" height="1">
    63.         <fill>
    64.           <SolidColor alpha="0.05"/>
    65.         </fill>
    66.       </Rect>
    67.       <Rect x="1" y="2" alpha="0.25" width="88" height="1" >
    68.         <fill>
    69.           <SolidColor color="#FFFFFF"/>
    70.         </fill>
    71.       </Rect>
    72.       <Rect x="1" y="61" alpha="0.1" width="88" height="1">
    73.         <fill>
    74.           <SolidColor color="#FFFFFF"/>
    75.         </fill>
    76.       </Rect>
    77.       <Rect y="2" width="1" height="60">
    78.         <fill>
    79.           <LinearGradient x="0.5" y="0" scaleX="60" rotation="90">
    80.             <GradientEntry ratio="0" color="#FFFFFF" alpha="0.25"/>
    81.             <GradientEntry ratio="1" color="#FFFFFF" alpha="0.1"/>
    82.           </LinearGradient>
    83.         </fill>
    84.       </Rect>
    85.       <Rect x="89" y="2" width="1" height="60">
    86.         <fill>
    87.           <LinearGradient x="0.5" y="0" scaleX="60" rotation="90">
    88.             <GradientEntry ratio="0" color="#FFFFFF" alpha="0.25"/>
    89.             <GradientEntry ratio="1" color="#FFFFFF" alpha="0.1"/>
    90.           </LinearGradient>
    91.         </fill>
    92.       </Rect>
    93.       <Rect width="90" height="70">
    94.         <fill>
    95.           <SolidColor color="#FFFFFF" alpha="0"/>
    96.         </fill>
    97.       </Rect>
    98. </Graphic>
    复制代码





Second, I created a new ActionScript class that extends the  ActionBarkSkin . In the constructor I make sure that the borderClass  uses the FXG file I created in the previous step. And I overrode the  drawBackground()  method because the FXG file does everything I need. Here is the complete listing:



    1. package org.corlan.skins {
    2.         import spark.skins.mobile.ActionBarSkin;
    3.         public class CustomActionBarSkin extends ActionBarSkin {

    4.                 public function CustomActionBarSkin() {
    5.                         super();
    6.                         //backgroundActionBar is the name of the FXG file
    7.                         borderClass = backgroundActionBar;
    8.                 }

    9.                 override protected function drawBackground(unscaledWidth:[url=http://www.google.com/search?q=number%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:number.html]Number[/url], unscaledHeight:[url=http://www.google.com/search?q=number%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:number.html]Number[/url]):void {

    10.                 }
    11.         }

    复制代码





Third, I changed the CSS from the main application file in order to set the new skin class as the  ActionBar  skin class, and the chromeColor used for the buttons. Here is the code:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
  3.    xmlns:s="library://ns.adobe.com/flex/spark" 
  4.    firstView="views.ActionBarHomeView"> 

  5. <fx:Style>
  6.         @namespace s "library://ns.adobe.com/flex/spark";

  7.         s|ActionBar {
  8.                 chromeColor: #16938D;
  9.                 defaultButtonAppearance: beveled;
  10.                 skinClass: ClassReference("org.corlan.skins.CustomActionBarSkin");
  11.         }

  12. </fx:Style>     

  13. </s:ViewNavigatorApplication>
复制代码



Finally, here is how the skinned  ActionBar  at runtime:

In conclusion, if you couple these techniques with skinning of the other components you plan to use inside the  ActionBar then you can really get something that is quite unique.
内容概要:本文围绕微电网群的双层优化与分布式优化问题,提出基于交替方向乘子法(ADMM)的分布式协同优化控制策略,并通过Matlab代码实现仿真验证。研究构建了上层为微电网间能量协调与优化调度、下层为各微电网内部源-荷-储精细化运行管理的双层优化模型。采用ADMM算法将集中式优化问题分解为多个可并行求解的子问题,实现了计算的分布式化与信息隐私保护,显著提升了系统的可扩展性与鲁棒性。文中系统阐述了模型构建原理、ADMM算法设计流程及其收敛性分析,并通过仿真实验验证了该方法在降低系统综合运行成本、提高可再生能源消纳能力以及维持系统稳定运行方面的有效性。; 适合人群:具备电力系统分析、优化理论基础,熟悉Matlab编程,从事微电网、分布式能源系统、智能电网等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 学习和掌握基于ADMM的分布式优化方法在微电网群协同能量管理中的具体应用;② 实现微电网群多主体参与下的经济调度与仿真分析;③ 深入理解双层优化架构的设计理念与分布式求解算法的实现机制。; 阅读建议:建议结合所提供的Matlab代码进行动手实践,重点剖析模型建立与算法实现的关键细节,可通过调整系统参数、改变运行场景等方式,深入探究ADMM算法的收敛特性及其对优化效果的影响。
内容概要:本文聚焦于风电出力不确定性的精确建模问题,提出采用拉丁超立方抽样(LHS)方法生成具有统计代表性的风电场景,并结合先进的场景缩减技术以降低计算复杂度。通过Matlab编程实现了LHS在高维随机变量空间中的均匀采样,有效克服了传统蒙特卡洛方法样本收敛慢、效率低的问题。在此基础上,引入基于聚类分析或概率距离度量的场景缩减算法,对初始大规模场景集进行优化合并,保留关键概率特征与出力趋势,构建出精简且具代表性的典型场景集。该方法显著提升了电力系统随机优化模型(如机组组合、储能调度、微电网能量管理)的求解效率与数值稳定性,同时确保输入场景的合理性与真实性,具备良好的可复现性与工程应用价值。; 适合人群:适用于具备一定电力系统分析基础和Matlab编程能力,从事新能源并网、随机规划、场景生成、电力市场及综合能源系统优化等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握拉丁超立方抽样在风电不确定性建模中的理论原理与Matlab实现技巧;②学习并应用场景生成与缩减技术,提升随机优化问题的建模与求解效率;③为含高比例风电的电力系统调度、风险评估与决策分析提供高质量的输入场景支撑。; 阅读建议:建议读者结合所提供的Matlab代码逐模块调试运行,深入理解抽样策略、距离计算、聚类缩减等核心算法的实现细节,并尝试将其集成到具体的优化模型中进行验证与拓展,以强化科研实践能力与创新思维。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值