65.9K
CodeProject 正在变化。 阅读更多。
Home

PlayBook 组件的皮肤定制

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2011 年 4 月 18 日

CPOL

3分钟阅读

viewsIcon

12890

如何定制 PlayBook 组件的皮肤

Skinning-PlayBook/components_closeup.png

引言

我一直在使用 PlayBook 玩得很开心。 用 ActionScript 3 编写一个“原生”应用程序真的很棒,而且 QNX 组件也非常好。 我想立即做的事情之一是给它们换肤,以便为我正在构建的 Pintley 应用程序定制它们。 幸运的是,如果你花时间做 Flash,它非常简单。 主要问题是 SDK 仍然相当新,所以我必须弄清楚一些小问题。

使用图像换肤

我想做的是为我的登录页面给 TextInputButton 换肤。 PlayBook SDK 有一些专门用于换肤的类,我可以通过 文档查看它们。 整个包 qnx.ui.skins 都有用于换肤的类。 看起来,根据此页面,大多数默认皮肤都是图像。 所以我首先尝试了那个。 我觉得有帮助的是获取那些库存图像,将它们带入 Photoshop,然后开始调整它们。

我为 TextInput 的每个状态创建了三个不同的 PNG:向上、向下和焦点。 一旦我有了这些,我就将它们嵌入到我的自定义皮肤类中,并使用特定的 QNX API 来设置外观和感觉。 该类扩展了 qnx.ui.skins.text.TextInputSkin 类,该类是创建 TextInputSkin 的基类。 使用 Embed 标签上的属性,您可以设置数字以使九宫格缩放适用于您的图像。

要覆盖的方法是 initializeStates 方法。 这是使用 QNX 组件模型注册状态属性的最佳位置。 然后,在该方法中使用另外两种方法。 第一种,setSkinState,只是将特定的皮肤与特定的状态关联起来。 最后一行代码,showSkin,接受一个皮肤类,这就是组件将用作默认皮肤的内容。

Skinning-PlayBook/pintely_app.png

基本上就是这样。 这是该类

package com.pintley.skins
{
     import flash.display.Sprite;
 
     import qnx.ui.skins.SkinStates;
     import qnx.ui.skins.text.TextInputSkin;
 
     public class PintleyImageTextInputSkin extends TextInputSkin
     {
          protected var upSkin:Sprite;
          protected var downSkin:Sprite;
          protected var focusSkin:Sprite;
 
          [Embed(source="/assets/skins/TextInputUp.png",
               scaleGridLeft="22",scaleGridRight="350",
               scaleGridTop="18",scaleGridBottom="38")]
          private var UpGraphic:Class;
 
          [Embed(source="/assets/skins/TextInputDown.png",
               scaleGridLeft="22",scaleGridRight="350",
               scaleGridTop="18",scaleGridBottom="38")]
          private var DownGraphic:Class;
 
          [Embed(source="/assets/skins/TextInputFocus.png",
               scaleGridLeft="22",scaleGridRight="350",
               scaleGridTop="18",scaleGridBottom="38")]
          private var FocusGraphic:Class;
 
          public function PintleyImageTextInputSkin()
          {
               super();
          }
 
          override protected function initializeStates():void
          {
               super.initializeStates();
 
               // Up State
               upSkin = new UpGraphic();
               setSkinState(SkinStates.UP,upSkin);
 
               // Down State
               downSkin = new DownGraphic();
               setSkinState(SkinStates.DOWN,downSkin);
 
               // Focus Skin
               focusSkin = new FocusGraphic();
               setSkinState(SkinStates.FOCUS,focusSkin);
 
               showSkin(upSkin);
          }
     }
}

使用绘图 API 换肤

换肤组件的另一种方法是使用绘图 API。 这个方法与使用图像大致相似,但有一些小的改动。 以相同的方式创建变量,并覆盖 initializeStates 函数。 使用绘图 API 换肤也使用与图像相同的方法。 setSkinState 的工作方式相同,showSkin 设置默认皮肤。

主要区别在于,在这个例子中有一个外部函数,它是在那里进行绘图的地方。 由于组件的不同状态通常看起来相同,因此我传入一些变量来根据为其绘制的状态更改外观。 该方法在初始化皮肤精灵后在 initializeStates 函数中被调用。 您也可以只在 initializeStates 方法中进行绘图,但就代码重用而言,这更好一些。

package com.pintley.skins
{
     import flash.display.DisplayObject;
     import flash.display.Sprite;
     import flash.filters.DropShadowFilter;
     import flash.geom.Rectangle;
 
     import qnx.ui.skins.SkinStates;
     import qnx.ui.skins.text.TextInputSkin;
 
     public class PintleyTextInput extends TextInputSkin
     {
          protected var upSkin:Sprite;
          protected var downSkin:Sprite;
          protected var focusSkin:Sprite;
 
          public function PintleyTextInput()
          {    
               super();
          }
 
          protected function drawSprite(item:Sprite,
              lineThickness:int,shadow:Boolean=false):void
          {
               var innerShadow:DropShadowFilter = new DropShadowFilter();
                    innerShadow.distance = 10;
                    innerShadow.angle = 40;
                    innerShadow.strength = .15;
                    innerShadow.blurX = 25;
                    innerShadow.blurY = 25;
                    innerShadow.inner = true;
 
               item.graphics.beginFill(0xffffff,1);
               item.graphics.lineStyle(lineThickness,0x3c2414,1);
               item.graphics.drawRoundRect(0,0,350,30,5);
               item.graphics.endFill();    
               item.filters = [innerShadow];
 
               if(shadow)
               {
                    var dropShadow:DropShadowFilter = new DropShadowFilter();
                         dropShadow.distance = 0;
                         dropShadow.blurX = 21;
                         dropShadow.blurY = 21;
                         dropShadow.angle = 0;
                         dropShadow.strength = 1;
                         dropShadow.color = 0x3c2414;
 
                    item.filters = [innerShadow,dropShadow];
               }
          }
 
          override protected function initializeStates():void
          {
               /**
                * UpSkin
                **/
               upSkin = new Sprite();
               drawSprite(upSkin,2);
               setSkinState(SkinStates.UP, upSkin );
 
               /**
                * DownSkin
                **/
               downSkin = new Sprite();
               drawSprite(downSkin,3);
               setSkinState(SkinStates.DOWN, downSkin );
 
               /**
                * FocusSkin
                **/
               focusSkin = new Sprite();
               drawSprite(focusSkin,3,true);
               setSkinState(SkinStates.FOCUS, focusSkin );
 
               showSkin( upSkin );
          }
     }
}

我拥有的最后一个例子使用了图像方法,但换肤的是一个按钮而不是 TextInput 控件。 我注意到关于 QNX 控件的一件事是,某些组件(如 TextInput)有自己的可以被子类化的皮肤文件,而其他组件(如 Button)的皮肤看起来就像它们只是子类化了 UISkin。 因此,与我对 TextInput 所做的那样调用 super.initializeStates() 不同,对于 Button,我只是覆盖 initializeStates() 并将代码放在那里。

更新:感谢下面的评论,我意识到当您扩展 UISkin 时,换肤对象必须是 DisplayObject 类型,而不是 Sprite 类型。

package com.pintley.skins
{
     import flash.display.DisplayObject;
 
     import qnx.ui.skins.SkinStates;
     import qnx.ui.skins.UISkin;
 
     public class LoginButton extends UISkin
     {
          protected var upSkin:DisplayObject;
          protected var downSkin:DisplayObject;
          protected var selectedSkin:DisplayObject;
          protected var disabledSkin:DisplayObject;
 
          [Embed(source="/assets/skins/LoginButtonUp.png")]
          private var UpGraphic:Class;
 
          [Embed(source="/assets/skins/LoginButtonSelected.png")]
          private var DownGraphic:Class;
 
          [Embed(source="/assets/skins/LoginButtonDisabled.png")]
          private var DisabledGraphic:Class;         
 
          public function LoginButton()
          {
               super();
          }
 
          override protected function initializeStates():void
          { 
               // Up State
               upSkin = new UpGraphic();
               setSkinState(SkinStates.UP,upSkin);
 
               // Down State
               downSkin = new DownGraphic();
               setSkinState(SkinStates.DOWN,downSkin);
 
               // Selected State
               selectedSkin = new DownGraphic();
               setSkinState(SkinStates.SELECTED,selectedSkin);
 
               // Disabled Skin
               disabledSkin = new DisabledGraphic();
               setSkinState(SkinStates.DISABLED,disabledSkin);
 
               showSkin(upSkin);
          }         
     }
}

所以希望这能让您开始换肤。 当我接触到更复杂的组件时,我也会写博客介绍换肤,但基本前提似乎在大多数组件中都相同。

相关文章

  1. 在 Flex 4 中构建自定义组件:SkinParts
  2. 开始使用 BlackBerry PlayBook 和 Adobe AIR
  3. Android 版 AIR 上的摄像头 API 和地理位置 Exif 数据
  4. 使用 Flex 4 换肤和 ToggleButton 的乐趣
  5. 几个使用 Flex 4 换肤的优秀博文

历史

  • 2011 年 4 月 18 日:初始版本
© . All rights reserved.