Quick Tip: Changing Spark DragScroll Parameters

Say you have a Spark List in your application with a TileLayout and drag options toggled on:

1
2
3
4
5
<s:List itemRenderer="ThumbRenderer" dragEnabled="true" dragMoveEnabled="true" dropEnabled="true">
	<s:layout>
		<s:TileLayout id="GalleryLayout"/>
	</s:layout>
</s:List>

But when you drag item up the list, depending upon your itemRenderer, it may take forever for the list to scroll… and the areas which trigger scroll up and down the list view are tiny in comparison.

You need to increase both the dragScrollRegionSizeVertical and dragScrollSpeed of spark.layouts.supportClasses.LayoutBase exposed through the Layout when given an id of “GalleryLayout”, in this case:

1
2
3
4
private function adjustDragScroll():void {
	GalleryLayout.dragScrollRegionSizeVertical = 80;
	GalleryLayout.dragScrollSpeed = 100;
}

Those properties are kinda hidden, but now it’ll drag-scroll nice and quick! Modify to suit your own application, of course.

Parsing Tweets with the TwitterString Class

While building a little Twitter aggregator for an upcoming conference, I found myself in need of a set of methods to create hyperlinks from three distinct elements that can be included within a tweet; links, usernames, and hashtags.

I was able to find regular expressions to do all the heavy lifting from various sources on the Web and have created a class which pretty much does all the processing with one method call. Here’s an example of the thing working, followed by example code, and the class itself.

Example SWF

Flash Player 10.2 or greater is required!


Example MXML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<s:Application 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="init()" width="300" height="100" 
			   backgroundColor="#1E1E1E" preloaderBaseColor="#989898">
 
	<fx:Script>
		<![CDATA[
			import flashx.textLayout.elements.Configuration;
			import flashx.textLayout.elements.TextFlow;
			import flashx.textLayout.conversion.TextConverter;
			import flashx.textLayout.formats.TextLayoutFormat;
			import com.fracturedvisionmedia.utils.TwitterString;
 
			private var myTxt:String = "Everyone should follow @josephlabrecque (http://bit.ly/7NkqrB) - really cool stuff and super-informative insights! #Awesome #Super #LOL";
 
			private function init():void {
				// Configure styling the TextFlow links to match richTxt
				var cfg:Configuration = TextFlow.defaultConfiguration;
				var normalTLF:TextLayoutFormat = new TextLayoutFormat(cfg.defaultLinkNormalFormat);
				normalTLF.color = 0xDCD9D9;
				cfg.defaultLinkNormalFormat = normalTLF;
				TextFlow.defaultConfiguration = cfg;
 
				// Import tweet as HTML
				richTxt.textFlow = TextConverter.importToFlow(TwitterString.instance.parseTweet(myTxt), TextConverter.TEXT_FIELD_HTML_FORMAT);
			}
		]]>
	</fx:Script>
 
	<s:RichEditableText id="richTxt" selectable="false" editable="false" right="10" top="10" bottom="10" color="#DCD9D9" left="10"/>
 
</s:Application>

TwitterString Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.fracturedvisionmedia.utils {
 
	/**
	 * The TwitterString class assists with the parsing of a tweet to add hyperlinks 
	 * around Links, HashTags, and UserNames in a tweet.
	 * @author Joseph Labrecque
	 * v. 0.1.2
	 */ 
 
	public final class TwitterString {
		private static var _instance:TwitterString = new TwitterString();
 
		public function TwitterString(){
			if (_instance != null){
				throw new Error("TwitterString can only be accessed through TwitterString.instance");
			}
		}
 
		public static function get instance():TwitterString {
			return _instance;
		}
 
		public function parseTweet(t:String):String {
			var step1:String = parseHyperlinks(t);
			var step2:String = parseUsernames(step1)
			var step3:String = parseHashtags(step2)
			return step3;
		}
 
		private function parseUsernames(t:String):String {
			var result:String = t.replace(/(^|\s)#(\w+)/g, "$1#<a href='http://search.twitter.com/search?q=$2' target='_blank'>$2</a>");
			return result;
		}
 
		private function parseHashtags(t:String):String {
			var result:String = t.replace(/(^|\s)@(\w+)/g, "$1@<a href='http://www.twitter.com/$2' target='_blank'>$2</a>");
			return result;
		}
 
		private function parseHyperlinks(t:String):String {
			var urlPattern:RegExp = new RegExp("(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)", "g")
			var result:String = t.replace(urlPattern, "<a href='$1' target='_blank'>$1</a>");
			return result;
		}
 
	}
}

Download TwitterString

Skinning a Spark Button in Flex 4

The more I work with Flex 4, the more I understand why certain choices were made regarding the new component architecture, especially in regard to skinning. I stumbled, at first, as the skinning model is quite different and can appear much more cumbersome at first glance. Like most Flex devs, I was used to just modifying the CSS to style Halo components quickly and easily. The Spark model is more complex- but holds a lot more power as demonstrated below.

Example:
How to turn this button…

<s:Button label="Resources"/>

Into This button…

<s:Button label="Resources" skinClass="CustomButton"/>

The only difference being the addition of the CustomButton skin class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?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" 
      minWidth="21" minHeight="21"
      alpha.disabled="0.5">
 
    <fx:Metadata>
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.Button")]
    </fx:Metadata>
 
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>
 
    <!-- background -->
    <s:Rect left="0" right="0" top="0" bottom="0"
          radiusX="0" radiusY="0" topLeftRadiusX="2" topLeftRadiusY="2" topRightRadiusX="20" topRightRadiusY="80" height="30" width="69">
        <s:stroke>
            <s:SolidColorStroke color="0x001a0a" />
        </s:stroke>
        <s:fill>
			<s:LinearGradient rotation="90">
				<s:GradientEntry color="0x00522d" />
				<s:GradientEntry color="0x003019" />
			</s:LinearGradient>
        </s:fill>
    </s:Rect>
 
    <!-- label -->
    <!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay -->
    <s:Label id="labelDisplay"
             textAlign="center"
             verticalAlign="bottom"
			 paddingLeft="5" paddingRight="10" 
             maxDisplayedLines="1" top="2" left="10" bottom="4" right="10" horizontalCenter="0" verticalCenter="0" color.up="#A0BAA6" color.over="#F0FFF0">
    </s:Label>
</s:Skin>

As you can see, you can pretty much use any sort of visual wizardry you like in here: Solids, Gradients, Bitmaps, Strokes, what-ever!


Super easy to get started too, as you can have Flash Builder duplicate an existing skin to get you started. Just rename and recode. Once within the new skin, you can use the Appearance panel to modify things as you would through Halo (CSS styling) in previous versions of Flex, or get into the nitty-gritty as I’ve done here.

Cool.

Migrating AIR Apps from a Self-Signed Certificate

Security CertificateAfter having deployed many AIR apps with self-signed certificates over the past year or so, when I finally got one from a certificate authority I was quite happy to update my apps with it. Not so fast! You can’t update an AIR app that has been signed with a different certificate than a previously installed signature. It will cause AIR to throw an installation error.

This will be my attempt to document the steps taken to get the certificate migration to function correctly. I’m using Flex Builder 3 on Windows Vista.

In many of my AIR apps, I use the AIR Update Framework which allows an app to check for updates to itself. Anytime a user would try and auto-update or even download and install an updated .air file manually (without first performing an uninstall), they would receive a generic installation error. That’s no good.

My first inclination was to place a warning in the updater XML file letting users know to UNINSTALL the app- then REINSTALL because of the cert change. Not very graceful and the update notes are collapsed by default anyway- no one would see them. That’s when I began searching and found this in the LiveDocs:

-migrate

It tells you a lot but fell a few points short for me. ADT (AIR Development Toolkit) was referenced- was this included in the FB3 SDKs or was this an additional download? Where do I find it?

After a bit of digging around, I located it in “C:\Program Files (x86)\Adobe\Flex Builder 3\sdks\3.2.0\bin”. To get it to work properly though, one should set up an environment variable in Windows. On Vista, this is done by going to System Properties, clicking Advanced System Settings, and pressing the “Environment Variables” button. You’ll want to look for the “Path” variable under “System Variables” and append the location of ADT to this. Be sure to separate each Path value item with a semi-colon.

PATH

The proper syntax for performing a certificate migration is “adt –migrate -storetype pkcs12 -keystore cert.p12 myApp.air myApp.air”. So I opened up a command prompt, navigated to the application directory and punched in my command. No good. ADT spit back an error that it couldn’t locate ‘java’. I know that Java is running on my system- so on a hunch, I added another environment variable to point to my Java installation folder- “C:\Program Files (x86)\Java\jre6\bin”.

Running ADT again and I was prompted for my certificate key and upon entering that, ADT was able to successfully migrate my cert!