I've written a small javafx app that animates a square moving from the top-left corner to bottom-right. It then reverses the animation and runs it continuously. On my pixel 4 (xxhdpi) the square leaves behind a trail of edges on the return trip. This does not happen on on my Nexus 7 2013 (xhdpi) or on my desktop.
Tried both the gluon plugin and also the gluon-vm plugin.
Seems related to screen pixel density . . . how do you prevent the ghosting artifacts on dense screens? Image and code below.
Pixel 4 screenshot:
Nexus 2013 Screenshot:
And the app:
public class StockJavaFx extends Application {
#Override
public void start(Stage primaryStage) {
Dimension2D dimension = Services.get(DisplayService.class)
.map(DisplayService::getDefaultDimensions)
.orElseThrow(() -> new NullPointerException("DisplayService"));
Rectangle rectangle = new Rectangle(75, 75);
Pane container = new Pane();
container.getChildren().add(new Rectangle(dimension.getWidth(), dimension.getHeight(), Color.DARKSLATEGRAY));
container.getChildren().add(rectangle);
Scene scene = new Scene(container);
primaryStage.setScene(scene);
TranslateTransition tt = new TranslateTransition(Duration.millis(750), rectangle);
tt.setFromX(0);
tt.setToX(dimension.getWidth() - 75);
tt.setFromY(0);
tt.setToY(dimension.getHeight() - 75);
tt.setCycleCount(Animation.INDEFINITE);
tt.setAutoReverse(true);
FillTransition ft = new FillTransition(Duration.millis(750), rectangle);
ft.setFromValue(Color.ORANGERED);
ft.setToValue(Color.CADETBLUE);
ft.setCycleCount(Animation.INDEFINITE);
ft.setAutoReverse(true);
tt.play();
ft.play();
primaryStage.show();
}
}
The old Gluon jfxmobile plugin is more or less EOL, and it's being replaced by the new Gluon Client plugin. More details can be found here and here. Detailed documentation can be found here.
This is how you can try creating an Android app that will solve the "ghosting" issue, with some extra "small" benefits, like using Java and JavaFX 11+, GraalVM, and getting a much more performant app.
Note that the client plugin for Android is still under heavy development and it's not ready for production yet.
Before you get started, please check that you follow the prerequisites here:
Use a Linux machine
Download and extract this version of GraalVM.
Set GRAALVM_HOME environment variable to the GraalVM installation directory, like:
export GRAALVM_HOME=/opt/graalvm-svm-linux-20.1.0-ea+28
Use Java 11, or set export JAVA_HOME=$GRAALVM_HOME
You can modify one of the existing samples, like HelloGluon.
You can modify the pom to use the latest versions like:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gluonhq.hello</groupId>
<artifactId>hellogluon</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hellogluon</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>11</maven.compiler.release>
<javafx.version>14.0.1</javafx.version>
<attach.version>4.0.7</attach.version>
<client.plugin.version>0.1.22</client.plugin.version>
<mainClassName>com.gluonhq.hello.HelloGluon</mainClassName>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>com.gluonhq</groupId>
<artifactId>charm-glisten</artifactId>
<version>6.0.4</version>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>display</artifactId>
<version>${attach.version}</version>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>lifecycle</artifactId>
<version>${attach.version}</version>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>statusbar</artifactId>
<version>${attach.version}</version>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>storage</artifactId>
<version>${attach.version}</version>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>util</artifactId>
<version>${attach.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>Gluon</id>
<url>https://nexus.gluonhq.com/nexus/content/repositories/releases</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.4</version>
<configuration>
<mainClass>${mainClassName}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.gluonhq</groupId>
<artifactId>client-maven-plugin</artifactId>
<version>${client.plugin.version}</version>
<configuration>
<target>${client.target}</target>
<attachList>
<list>display</list>
<list>lifecycle</list>
<list>statusbar</list>
<list>storage</list>
</attachList>
<mainClass>${mainClassName}</mainClass>
</configuration>
</plugin>
</plugins>
<profiles>
<profile>
<id>desktop</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<client.target>host</client.target>
</properties>
<dependencies>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>display</artifactId>
<version>${attach.version}</version>
<classifier>desktop</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>lifecycle</artifactId>
<version>${attach.version}</version>
<classifier>desktop</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>storage</artifactId>
<version>${attach.version}</version>
<classifier>desktop</classifier>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>ios</id>
<properties>
<client.target>ios</client.target>
</properties>
</profile>
<profile>
<id>android</id>
<properties>
<client.target>android</client.target>
</properties>
</profile>
</profiles>
</build>
</project>
Now you can modify the main view to add your transition:
public class HelloGluon extends MobileApplication {
#Override
public void init() {
addViewFactory(HOME_VIEW, () -> {
Rectangle rectangle = new Rectangle(75, 75, Color.DARKSLATEGRAY);
Pane container = new Pane(rectangle);
container.setStyle("-fx-background-color: darkslategray");
return new View(container) {
#Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu")));
appBar.setTitleText("Gluon Mobile");
appBar.getActionItems().add(MaterialDesignIcon.PLAY_ARROW.button(e -> {
TranslateTransition tt = new TranslateTransition(Duration.millis(750), rectangle);
tt.setFromX(0);
tt.setToX(getWidth() - 75);
tt.setFromY(0);
tt.setToY(getHeight() - 75);
tt.setCycleCount(Animation.INDEFINITE);
tt.setAutoReverse(true);
FillTransition ft = new FillTransition(Duration.millis(750), rectangle);
ft.setFromValue(Color.ORANGERED);
ft.setToValue(Color.CADETBLUE);
ft.setCycleCount(Animation.INDEFINITE);
ft.setAutoReverse(true);
tt.play();
ft.play();
}));
}
};
});
}
#Override
public void postInit(Scene scene) {
Swatch.TEAL.assignTo(scene);
scene.getStylesheets().add(HelloGluon.class.getResource("styles.css").toExternalForm());
if (Platform.isDesktop()) {
Dimension2D dimension2D = DisplayService.create()
.map(DisplayService::getDefaultDimensions)
.orElse(new Dimension2D(640, 480));
scene.getWindow().setWidth(dimension2D.getWidth());
scene.getWindow().setHeight(dimension2D.getHeight());
}
}
public static void main(String[] args) {
launch();
}
}
You can now run with your regular JDK on your machine:
mvn clean javafx:run
and verify that works fine.
If that is the case, you can now create a native image with GraalVM, also on your machine:
mvn clean client:build
This is a lengthy process, that requires usually 16 GB RAM, and a few minutes.
Once finished successfully, you can run it:
mvn client:run
It should work as expected:
Finally, you can try to build an Android native image:
mvn -Pandroid client:build
When finished, create the apk:
mvn -Pandroid client:package
It will create an apk under target/client/aarch64-android/gvm/apk/bin/hellogluon.apk.
Plug a device, to install and run:
mvn -Pandroid client:install client:run
Note: by default, icon assets and AndroidManifest are generated at target/client/aarch64-android/gensrc/android. If you want to modify either of them, you have to copy the content of this folder to src/android.
Related
we have a few apps where we support android from Version 6 min to 10.
Now I have a bottom Navigation bar (tabbedpage) 5 tabs and when tapping on it , the title gets cut off.
In android 9 I have implemented as recommended https://montemagno.com/control-text-size-on-android-bottom-navigation/
and works ,but it does not work on android 7 as it clearly says "android 9"
<resources xmlns:tools="http://schemas.android.com/tools">
<dimen name="design_bottom_navigation_text_size" tools:override="true">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>
</resources>
Can the size of the text be changed on android 7 and how? I am using the latest xamarin.forms
You could set the font size in code behind .
in Resource-> Menu
define the tab item
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#+id/action_settings_1"
android:orderInCategory="100"
android:title="111"
app:showAsAction="never" />
<item
android:id="#+id/action_settings_2"
android:orderInCategory="100"
android:title="222"
app:showAsAction="never" />
<item
android:id="#+id/action_settings_3"
android:orderInCategory="100"
android:title="333"
app:showAsAction="never" />
</menu>
in Resource-> Layout
Add the following code in content_main.xml
<android.support.design.widget.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bottomNavigationView"
//... other property
app:menu="#menu/menu_main" />
in MainActivity
BottomNavigationView bottomNavigationView = FindViewById<BottomNavigationView>(Resource.Id.bottomNavigationView);
TextView textView = (TextView)bottomNavigationView.FindViewById(Resource.Id.action_settings).FindViewById(Resource.Id.largeLabel);
textView.TextSize=12;
I'm trying to create PDF from HTML(String) using iText 7.1.7. When I copy the HTML in W3Schools (https://www.w3schools.com/html/tryit.asp?filename=tryhtml_default), I see the css[display:inline !important;] works fine and displays the 3 div sections inline. But, when I generate the PDF with my sample java program using the same HTML through iText7, it is displaying the 3 div sections as block. Does iText7 have issues with CSS? If not, can you please let me know what am I doing wrong here?
Note: You might want to replace all \" with " in HTML before you test it in W3Schools
<dependencies>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.7</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>7.1.7</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.1.7</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.1.7</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>pdfa</artifactId>
<version>7.1.7</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
Sample Java program:
private static final String SAMPLE_HTML = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"> <html> <head></head> <body><!DOCTYPE html><html><head> <style> div.fp-soft-merge, p.fp-soft-merge { display: inline !important; }</style></head><body><div class=\"fp deletable free-tag fp-hard-ln-init fp-soft-merge\" data-fp=\"FREE\" data-paragraph-timestamp=\"2014-08-01\" data-paragraph-type=\"FREE\"><p class=\"fp-hard-ln-init\" style=\"text-align:justify\"><br></p><p class=\"fp-hard-ln-init fp-soft-merge\" style=\"text-align:justify\">The applied-for mark MARK1 and the registered mark MARK2 are similar because they would be pronounced in the same manner. Some other sample content for Testing purpose. Specifically, both have a \"ock\" first syllable followed by a \"ee\" syllable. </p></div><div append-br=\"true\" class=\"fp deletable fp-soft-merge fp-hard-ln-init\" data-delete-selector=\"[data-fp=Q29-34]\" data-fp=\"Q29-34\" data-paragraph-timestamp=\"2011-05-13T03:00:52.000-04:00\" data-paragraph-type=\"FREE\"><p class=\"fp-soft-merge fp-hard-ln-init\" style=\"text-align:justify\"><span>The marks are essentially phonetic equivalents and thus sound similar. Similarity in sound alone may be sufficient to support a finding that the marks are confusingly similar. </span><i>In re Hand Wine Ltd.</i><span>, 4 XYPQ5e 1400, 1300 (XBAB 1966); </span><i>see In re 1st USA Some other, Inc.</i><span>, 89 XYZQ8j 1500, 1466 (ABAB 5607); TMEP ยง1677.05(b)(iv).</span></p></div><div class=\"fp deletable free-tag fp-hard-ln-init fp-hard-ln fp-soft-merge\" data-fp=\"FREE\" data-paragraph-timestamp=\"2014-08-01\" data-paragraph-type=\"FREE\"><p class=\"fp-hard-ln fp-hard-ln-init fp-soft-merge\" style=\"text-align:justify; margin-top:0; margin-bottom:0\"><span> The marks are likely to be confused because they sound the same.</span><br></p><p class=\"fp-hard-ln-init\" style=\"text-align:justify\"><br></p></div></body></html>";
public static void main(String[] args) {
ByteArrayInputStream byteArrayInputStream;
try {
byteArrayInputStream = convertToPDF(SAMPLE_HTML.getBytes());
IOUtils.copy(byteArrayInputStream, new FileOutputStream("./src/test/resources/PDF_HTML_0.pdf"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static ByteArrayInputStream convertToPDF(byte[] htmlContent) throws IOException {
if(htmlContent != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(baos, getDefaultWriterProperties());
PdfDocument pdfDocument = new PdfDocument(writer);
pdfDocument.setDefaultPageSize(PageSize.LETTER);
HtmlConverter.convertToPdf(new ByteArrayInputStream(htmlContent), pdfDocument);
return new ByteArrayInputStream(baos.toByteArray());
} else {
return null;
}
}
private static WriterProperties getDefaultWriterProperties() {
WriterProperties writerProperties = new WriterProperties();
writerProperties.setCompressionLevel(CompressionConstants.BEST_COMPRESSION);
return writerProperties;
}
I've been trying to render a webpage using the Adobe Flex / Flash builder StageWebView but it's not scaling the webpage to fit the phones screen dimension and basically cutting the right side of the webpage off. I've tried using
<meta name="viewPort" content="width=device-width; initial-scale=1.0;
maximum-scale=1.0; user-scalable=no;" />
This has not worked. Below is the Flex code I'm currently using.
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import flash.media.StageWebView;
import flash.net.URLRequest;
import spark.events.ViewNavigatorEvent;
protected var webView:StageWebView = new StageWebView();
protected var openBrowser:Boolean = false;
protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
{
if (StageWebView.isSupported)
{
currentState = "normal";
webView.stage = stage;
webView.viewPort = new Rectangle(0,75,stage.stageWidth,stage.stageHeight);
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGE,onURLChange);
webView.loadURL("http://nealdrake.com/mls.html");
addEventListener(ViewNavigatorEvent.REMOVING,onRemove);
}
else {
currentState = "unsupported";
lblSupport.text = "StageWebView feature not supported";
}
}
protected function onURLChange(event:LocationChangeEvent):void
{
trace("URL change");
// Uncomment the following line to load in the default browser instead...
//navigateToURL(new URLRequest(event.location));
}
protected function onRemove(event:ViewNavigatorEvent):void
{
this.webView.dispose();
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="unsupported"/>
</s:states>
<s:Label id="lblSupport" includeIn="unsupported" width="95%" horizontalCenter="0" verticalCenter="0"/>
Any help would greatly be appreciated!
I'm surprised it's cutting off the right hand side rather than the bottom, since that's what I'd expect from this:
webView.viewPort = new Rectangle(0,75,stage.stageWidth,stage.stageHeight);
You need to count for any X or Y offset in your width and height, like this:
webView.viewPort = new Rectangle(0,75,stage.stageWidth,stage.stageHeight - 75);
It might be that your StageWebView is being initialised before your app's size is correct. Try adding a resize handler (listen for Event.RESIZE events on whatever component your code above is taken from) that sets the viewport again.
This application is a much simplified version of what I am trying to accomplish, some smoothing of some motion on the screen by using a composite animation and rerunning it as things change, and using bindings to set some of the values of the animation. The animation is periodically stopped, and then restarted. valueFrom is not set so a property value just continues from where it was towards a new goal. In this example, I'm animating a Rect's left/top towards mouse's X/Y to make it chase the mouse.
Problem is the memory of this application continues to grow if you wait a little while and continue to move the mouse. So what should I be doing that I am not?
<?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"
creationComplete="creationCompleteHandler(event)"
mouseMove="mouseMoveHandler(event)"
mouseOut="mouseOutHandler(event)"
>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
private static const RECT_HALF_SIZE:int = 5;
private static const NO_CHASE:int = -1000;
[Bindable]
private var lastMouseX:int = NO_CHASE;
[Bindable]
private var lastMouseY:int = NO_CHASE;
private var evalTimer:Timer = new Timer(100);
protected function creationCompleteHandler(event:FlexEvent):void
{
evalTimer.addEventListener(TimerEvent.TIMER, function(event:TimerEvent):void { evalChase(); });
evalTimer.start();
}
protected function mouseOutHandler(event:MouseEvent):void
{
lastMouseX = lastMouseY = NO_CHASE;
evalChase();
}
protected function mouseMoveHandler(event:MouseEvent):void
{
const reStart:Boolean = (lastMouseX == NO_CHASE);
lastMouseX = event.localX;
lastMouseY = event.localY;
if(reStart)
evalChase();
}
private function evalChase():void
{
doChase.stop();
doChase.end();
if(lastMouseX == NO_CHASE)
return;
doChase.play();
}
]]>
</fx:Script>
<fx:Declarations>
<s:Linear id="linearEaser" />
<s:Parallel
id="doChase"
duration="2000"
>
<s:Animate target="{chaser}" easer="{linearEaser}" >
<s:SimpleMotionPath property="left" valueTo="{lastMouseX-RECT_HALF_SIZE}" />
</s:Animate>
<s:Animate target="{chaser}" easer="{linearEaser}" >
<s:SimpleMotionPath property="top" valueTo="{lastMouseY-RECT_HALF_SIZE}" />
</s:Animate>
</s:Parallel>
</fx:Declarations>
<s:Rect
id="chaser"
top="0" left="0"
width="{2*RECT_HALF_SIZE}" height="{2*RECT_HALF_SIZE}"
>
<s:fill>
<s:SolidColor color="red" />
</s:fill>
</s:Rect>
</s:WindowedApplication>
Don't think you're actually doing anything wrong in this code, I copied into a new Flex 4.6 project and ran it, I could see what you're saying with regard to the ADL process itself increasing slightly in memory consumption over time, particularly after it stops motion then begins again, however I tried running this in Flash Builder with the profiler and it seems the swf itself isn't really leaking any memory, it stayed right around 1.1 MB for me (up to about 1.4, but then back down) it seems it had a fair amount of Vector.<*> objects in memory though I'm not clear on what is being stored in those objects.
Degrafa newbie here :-).
I was able to get "com.degrafa.skins.CSSSkin" to create linear gradient backgrounds. Now I'm getting into more advanced stuff as I try to figure out radial gradients...
I figured this out by watching Flex-skinning-with-degrafa-screencast but my code isn't working for me and I'm getting a white background on my canvas.
Here is the code I have so far:
I have a MXML component ThreeWayGrad.mxml which extends Canvas and has a styleName for ThreeWayGradient:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas
xmlns:mx="http://www.adobe.com/2006/mxml"
styleName="ThreeWayGradient"/>
I have a CSS style entry for ThreeWayGradient with a skin tag for the class RadialGradient:
Canvas.ThreeWayGradient
{
borderSkin: ClassReference("assets.skins.RadialGradient");
}
And finally here is the RadialGradient.mxml component:
<?xml version="1.0" encoding="utf-8"?>
<GraphicBorderSkin
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="http://www.degrafa.com/2007">
<mx:Script>
<![CDATA[
[Bindable] private var _height:Number = 0;
[Bindable] private var _width:Number = 0;
override protected
function updateDisplayList(w:Number, h:Number):void
{
super.updateDisplayList(w, h);
_height = h;
_width = w;
trace("INFO: displaylist updated --" + _height + " : " + _width );
}
]]>
</mx:Script>
<strokes>
<SolidStroke id="mainStroke" color="#333333" weight="3"/>
</strokes>
<fills>
<RadialGradientFill
id="blueGradient"
angle="45"
focalPointRatio="0">
<GradientStop
alpha="1"
ratio=".25"
color="#ffffff"/>
<GradientStop
alpha="1"
ratio=".70"
color="#003355"/>
<GradientStop
alpha="1"
ratio="1"
color="#111111"/>
</RadialGradientFill>
</fills>
<!-- Creating the background -->
<geometry>
<GeometryComposition>
<!-- Creating a Rectangle to draw the gradient to and
moving the center of the gradient to the lower left corner -->
<RegularRectangle
fill="{blueGradient}"
stroke="{mainStroke}"
height="{_height}"
width="{_width}"
/>
</GeometryComposition>
</geometry>
</GraphicBorderSkin>
Does anyone know why this isn't working? I see the trace output with the correct sizes, so I know the class is getting called.
I also copied this code into a new Application using a Surface instead of GraphicBorderSkin element and GeometryGroup instead of GeometryComposition, and it works. Anyway I'm sure I'm missing something simple and thanks in advance!!!
You should be able to use skin code like this (skinWidth and skinHeight are exposed inside the GraphicBorderSkin so you don't need to override updateDisplayList and specify additional local variables for width and height):
<?xml version="1.0" encoding="utf-8"?>
<GraphicBorderSkin
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="http://www.degrafa.com/2007">
<strokes>
<SolidStroke id="mainStroke" color="#333333" weight="3"/>
</strokes>
<fills>
<RadialGradientFill
id="blueGradient"
angle="0"
focalPointRatio="0">
<GradientStop
alpha="1"
ratio=".25"
color="#ffffff"/>
<GradientStop
alpha="1"
ratio=".70"
color="#003355"/>
<GradientStop
alpha="1"
ratio="1"
color="#111111"/>
</RadialGradientFill>
</fills>
<!-- Creating the background -->
<geometry>
<!-- Creating a Rectangle to draw the gradient to and
moving the center of the gradient to the lower left corner -->
<RegularRectangle id="rect"
fill="{blueGradient}"
stroke="{mainStroke}"
height="{skinHeight}"
width="{skinWidth}"
/>
<!-- Alernative: <RegularRectangle fill="{blueGradient}" stroke="{mainStroke}" height="100%" width="100%"/> -->
</geometry>
</GraphicBorderSkin>
In this case, you don't need a GeometryComposition enclosing the RegularRectangle. I also discussed this with Jason Hawryluk (Degrafa architect) and he pointed out the alternative way to specify via Geometry's layout support - see the commented markup "Alternative" for the layout driven example.
And for the Canvas, you need to specify a width and height setting for it to draw:
<mx:Canvas
xmlns:mx="http://www.adobe.com/2006/mxml" width="50%" height="50%"
styleName="ThreeWayGradient"/>