导读:
Problem Summary
Creating programmatic skins for buttons on the fly.
为按钮创建可编程的皮肤
Solution Summary
Create programmatic skins on the fly for buttons and other components to save on startup, and download time.
Explanation
Programmatic Skins for Buttons
Here's a little recipe I use for programmatic skinning on buttons in particular on some projects. If you need fast, extendable, easy on the bandwidth buttons, then this one is highly useful.
To start off, I picked buttons because they’re the most generic examples, and probably the most likely target for clean, simple programmatic skins.
下面是我解决这个问题的方法,如果你需要快速的,可扩展的,简单的按钮,那么这个相当有用,首先我选择按钮时因为他们是最通用的组件,也许是最可能的可编程皮肤作用对象了
The Code:
Let's start off with the MXML and the actual buttons. You’ll notice that there’s absolutely nothing tough about this code, you can use any button anywhere and just make sure to set it’s styleName attribute to the CSS class that contains the skin you want to use:
你会发现代码一点也不难懂,也没有什么特别的地方,只是要注意CSS的样式名药和CSS类吻合
Dave Flatley
PXL Designs, LLC - 2007
Free for commercial, or personal use.
-->
styleName="flatColorRectangleSkin" /> styleName="flatColorRectangleSkin" />
cornerRadius="12" styleName="flatColorRoundedRectangleSkin" /> cornerRadius="12" styleName="flatColorRoundedRectangleSkin" />
styleName="gradientRectangleSkin" /> styleName="gradientRectangleSkin" />
The only things to be aware of in your MXML are the reference to the external style sheet and setting your styleNames on the buttons themselves.
接下来要做的事情就是要在代码内引用外部的CSS样式表并将其设置到按钮上
Add a little CSS for flavoring:
In the zip file, you’ll see all the other classes, but here I’ll point out the GradientRectangleSkin CSS selector. In the directory structure laid out in this example, we have our MXML reference the css/styles.css stylesheet which contains 3 class selectors.
For this example, we can see the .gradientRectangleSkin class below. We just set some pretty standard styles on our button, and just make sure to reference the actual classes that will become the programmatic skins for our button “states”(upSkin, downSkin, overSkin, disabledSkin).
在后面的ZIP文件里你可以看见所有的其他类,但是这里我只想指出最重要的GradientRectangleSkin CSS选择器,在文件夹架构里同样的布局CSS文件例如CSS/文件夹包含了三个CSS选择器,对于下面的这个例子我们可以看见我们按钮上的漂亮的标准样式,只要保证我们的样式和代码里的对上就可以了
.gradientRectangleSkin{
fontFamily: Arial;
fontSize: 12;
color: #FFFFFF;
textAlign:left;
width:150;
height:30;
upSkin:ClassReference('programmaticSkinClasses.GradientRectangleSkin');
downSkin:ClassReference('programmaticSkinClasses.GradientRectangleSkin');
overSkin:ClassReference('programmaticSkinClasses.GradientRectangleSkin');
disabledSkin:ClassReference('programmaticSkinClasses.GradientRectangleSkin');
}
Yumm, let that CSS simmer for a while:
Next comes the fun part, where we actually make things happen. The programmatic skin classes contain all the logic we’ll need to draw out our actual skin and add some spice to our buttons. Since we’re using the GradientRectangleSkin, we have a little more going on here than just the run-of-the-mill flat colored button.
下面是有趣的部分,实际上也就是在这里完成了这个问题,可变程的皮肤类包含了我们所有需要的绘制皮肤的逻辑类和代码,因为我们使用GradientRectangleSkin我们还有些事情要做
To give our button a little pazazz, we have our class create a few things:
A Gradient Background
Different gradients for button states
A drop shadow to appear on every state except downSkin
The reason for leaving off the shadow on the downSkin state is to give the appearance of the button being depressed when the user clicks. In our directory structure, our skin classes are stored in the programmaticSkinClasses folder, and this one is called GradientRectangleSkin.as. So here’s what the class looks like:
为了让我们的按钮看其来更炫,我们将做以下的事情,梯度渐变的背景,对不同的按钮状态给出不同的梯度,按钮阴影,至于为什么不在用户按下的时候给出阴影是要让用户注意到这个不明显的变化,这个类保存在XX文件夹,下面就是这个类
package programmaticSkinClasses {
importmx.core.UIComponent;
importflash.filters.DropShadowFilter;
public
classGradientRectangleSkin
extendsUIComponent {
importflash.display.Graphics;
importflash.geom.Rectangle;
importmx.graphics.GradientEntry;
importmx.graphics.LinearGradient;
protected override
functionupdateDisplayList(unscaledWidth:
Number, unscaledHeight:
Number):
void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
varw:
Number= unscaledWidth;
varh:
Number= unscaledHeight;
// hold the values of the gradients depending on button state
varbackgroundFillColor:
Number;
varbackgroundFillColor2:
Number;
varfill:LinearGradient =
newLinearGradient();
// reference the graphics object of this skin class
varg:Graphics = graphics;
g.
clear();
// which skin is the button currently looking for? Which skin to use?
switch(
name){
case
"upSkin":
backgroundFillColor = 0x929292;
backgroundFillColor2 = 0x000000;
break;
case
"overSkin":
backgroundFillColor = 0x696969;
backgroundFillColor2 = 0x504F4F;
break;
case
"downSkin":
backgroundFillColor = 0x888888;
backgroundFillColor2 = 0x777777;
color: 0xFF0000;
break;
case
"disabledSkin":
backgroundFillColor = 0xCCCCCC;
backgroundFillColor2 = 0xCCCCCC;
break;
}
// depending on which state the button's in, we set our color for the
// gradients on the skin
varg1:GradientEntry =
newGradientEntry(backgroundFillColor,.10,100);
varg2:GradientEntry =
newGradientEntry(backgroundFillColor2,.60,100);
fill.entries= [g1,g2];
fill.angle= 90;
// fill the rectangle
g.
moveTo(0,0);
fill.begin(g,
newRectangle(0,0,w,h));
g.
lineTo(w,0);
g.
lineTo(w,h);
g.
lineTo(0,h);
g.
lineTo(0,0);
fill.
end(g);
// if we're not showing the down skin, show the shadow. Otherwise hide it on the "down state" to look like it's being pressed
if(
name!=
"downSkin"){
filters = [
newDropShadowFilter(4, 45,0x000000,.2)];
}
}
}
}
In this class, the first thing we’re doing is extending UIComponent and overriding it’s updateDisplayList() function. At the top, we set 2 empty vars for background colors that will hold our values for this gradient and we create a new LinearGradient to use as our fill.
在这个类里面我们重新扩展了基本组件,并且跟新乐绘制函数,我们将两个空变量设置为背景色,并且保存我们为背景设置的梯度
We make a reference to the UIComponent’s graphics object, and clear it to make sure we don’t get any surprises between button states. Now, we’re going to use a switch statement on the buttons current “state name”. We need to know which “state” is being requested depending on the user’s interactivity.
我们引用组件的G对象,清空它以保证我们在状态切换之间不出意外,下面是使用一个switch语句来对不同的状态来做不同的处理
We’re going to switch on the button’s current “state” to figure out which gradient colors to draw out. If we need the upSkin, we’re going to set the background colors to a nice gray/black gradient look by setting:
case
"upSkin":
backgroundFillColor = 0x929292;
backgroundFillColor2 = 0x000000;
break;
We then break out of the switch and set our actual GradientEntries:
varg1:GradientEntry =
newGradientEntry(backgroundFillColor,.10,100);
varg2:GradientEntry =
newGradientEntry(backgroundFillColor2,.60,100);
The .10 and .60 are to set the location on the skin where that gradient color will actually begin. This combination makes a nice smooth transition for our recipe. Now we know which state we’re going to show and which gradient colors for that state, let’s draw it out with a little butter. Nah, forget the butter, just the code is fine:
fill.entries= [g1,g2];
fill.angle= 90;
// fill the rectangle
g.
moveTo(0,0);
fill.begin(g,
newRectangle(0,0,w,h));
g.
lineTo(w,0);
g.
lineTo(w,h);
g.
lineTo(0,h);
g.
lineTo(0,0);
fill.
end(g);
We’ve just told the Flex compiler to use our gradient colors for the fill, to begin to draw a new Rectangle class using our unscaled height and width, fill it with our gradients and finish up by cleaning any left over paint off the floor.
我们这样便告诉了FLEX编译器使用我们的颜色来填充,绘制矩形
Add a dropshadow for some spice:
Another little addition I like to use in my recipe is to add a drop shadow to each state except the downSkin. If we’re currently using the downSkin state, the user is pressing the button so we’ll remove the drop shadow to make the button appear to be pressed into the background.
另一个要做的事为这个按钮添加一个影子,如果用户按下按钮,那么我们清除这个影子
// if we're not showing the down skin, show the shadow. Otherwise hide it on the "down state" to look like it's being pressed
if(
name!=
"downSkin"){
filters = [
newDropShadowFilter(4, 45,0x000000,.2)];
}
That is one fine looking button:
Winning awards for graphic design merit? Perhaps not, but by using the programmatic skins, you’re open to extending many possibilities, and since they’re vector graphics being drawn on the fly with Flex’s powerful graphics classes, you’re saving a lot of download time. You just put your app on a diet and it’s looking and feeling a lot better.
想要靠这个活的设计大赛的奖杯,大概不行,但是有了这个可变程的按钮之后,借助FLEX的强大功能你肯定能做到你可以自由的修改这里提供的所有代码,
This recipe was short and sweet, but in the near future I’ll add some more programmatic skinning with other cool ideas you can use to create a nice looking interface that’s easy on the startup time.
Full source can be downloaded here:
完整的下载地址http://www.davidflatley.com/?p=22
Related files for download Programmatic button skins - source files
ProgrammaticSkinning.zip
本文转自
http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=2&postId=7042