Flex Mobile Development – Callout Component Sample (with source)

Flash Builder 4.6 and Flex 4.6 are currently in pre-release and this is the first of a series of posts highlighting the new features with sample code. Most of the new Flex 4.6 components were created for tablet application development where more screen real estate is available to work with.

The first component I’ll highlight in this series is the new Spark Callout component. The Callout is used to define a pop-up container for your mobile application where you may want to show actions to take, accept input or simply display some information. You can use any of the current UI components supported for mobile within a Callout, including even a mobile ViewNavigator. The component features an arrow that points to the owner of the Callout (the component that called open() on it). If you’ve done any Objective-C programming for iPad, you may know this as the Popover component.

Here’s an example of it in use in a tablet application Christophe and I will be working with at RIA Unleashed in Boston next week:

I created a sample tabbed application that I’m making available here so you can check out some different ways to use Callout‘s in your applications. I also included some explanatory text below. It’s nothing fancy but should be useful in your mobile application development!

Expanding Callout initially
In the first tab of the sample code I show an example of opening the callout from the CalloutButton on creationComplete, in case there’s informational text you want to have immediately available. Here’s a screenshot:

Here’s the code snippet for the above:

<s:CalloutButton id="cb2" icon="{addIcon}" verticalPosition="after" creationComplete="cb2.openDropDown()">
	<s:calloutContent>
		<s:BorderContainer backgroundColor="blue" color="0xFFFFFF" borderWeight="2" width="280" height="150" cornerRadius="5">
			<s:layout>
				<s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="5"/>
			</s:layout>
			<s:HGroup verticalAlign="middle" horizontalAlign="left">
				<s:Image source="@Embed(source='help.png')" id="helpIcon"/>
				<s:Label text="Getting Started"/>
			</s:HGroup>
			<s:TextArea text="Tap this button to get started adding buddies to your buddy list immediately." color="0x000000" width="100%"
					skinClass="spark.skins.mobile.TextAreaSkin" editable="false"/>
		</s:BorderContainer>
	</s:calloutContent>
</s:CalloutButton>

Positioning the Callout
There are two properties to position the Callout component relative to it’s owner, horizontalPosition and verticalPosition. You can leave the defaults of auto by not setting them at all and the position be set based on the aspect ratio of the screen (portrait or landscape) for the Callout to fit with minimal owner overlap and screen bounds adjustments. Besides auto, you can manually set the horizontal and vertical position to before, start, middle, end, and after as desired.

Tab 3 in the sample application shows how setting the different positions will affect the Callout, try out the different settings in the SpinnerList controls (also new to 4.6):

Closing the Callout
When using the CalloutButton, clicking outside of the Callout container will always close it, since it’s non-modal. Otherwise, you need to call the closeDropDown() method to close it though, as shown in the code snippet from the sample:

<fx:Script>
    <![CDATA[
	import spark.events.ViewNavigatorEvent;
	protected function button1_clickHandler(event:MouseEvent):void
	{
		trace(event.target.label + " clicked! " + cb.isPopUp);
		cb.closeDropDown();
	}
    ]]>
</fx:Script>
<s:CalloutButton id="cb" label="Action Callout" verticalPosition="after" calloutDestructionPolicy="never">
	<!-- layout the callout content here -->
	<s:calloutLayout>
		<s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" horizontalAlign="center" gap="5"/>
	</s:calloutLayout>
	<s:calloutContent>
		<s:Button label="Search" width="{btn.width}" click="button1_clickHandler(event)"/>
		<s:Button label="Followers" width="{btn.width}" click="button1_clickHandler(event)"/>
		<s:Button label="Following" width="{btn.width}" click="button1_clickHandler(event)"/>
		<s:Button id="btn" label="Direct Messages" click="button1_clickHandler(event)"/>
	</s:calloutContent>
</s:CalloutButton>

This screenshot from Tab 1 shows the above code with the expanded Callout container:

When using the Callout component itself (rather than the CalloutButton), you can call a close() method to close the Callout and listen for the event to get the data from the selection. See the next section on passing data for a code snippet. The list calls the close() method of the callout passing the selectedItem.

NOTE: In my sample code I added code to close the Callout programmatically upon viewDeactivate so it would close when a different tab is selected.

Passing Data from Callout
Since the Callout component extends SkinnablePopUpContainer, we can use the close() method to pass back data setting the commit property to true in the first parameter and the data to pass back in the second parameter.


Here’s the source code for MyCallout.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:Callout xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark">

	<fx:Declarations>
		<s:ArrayCollection id="ac">
			<fx:String>Boston, MA</fx:String>
			<fx:String>Chicago, IL</fx:String>
			<fx:String>Honolulu, HI</fx:String>
			<fx:String>New York, NY</fx:String>
			<fx:String>San Francisco, CA</fx:String>
			<fx:String>San Jose, CA</fx:String>
			<fx:String>Washington, DC</fx:String>
		</s:ArrayCollection>
	</fx:Declarations>

	<s:VGroup paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" horizontalAlign="center">
		<s:List id="list" dataProvider="{ac}" width="240" change="close(true, list.selectedItem)"/>
	</s:VGroup>
</s:Callout>

Then we can listen for the close event on the callout that uses it and get the data back to use as desired, such as:

<components:MyCalloutComp id="callout" height="300" close="location.text=event.data" verticalPosition="after"/>

The result is that the location text is populated with the selected list item from the Callout:

Skinning
The Callout component extends from SkinnablePopUpContainer and is therefore skinnable. Take a look at the CalloutSkin.as file in your Flex 4.6 SDK for starters. Mine is located on my Mac at: /Applications/Adobe Flash Builder 4.6/sdks/4.6.0/frameworks/projects/mobiletheme/src/spark/skins/mobile. The last tab in the sample code shows some changes to the Callout skin by using a custom skin. You could even customize the arrow further by looking into the CalloutArrow.as code, which is what is currently used by the skin for drawing the arrow. CalloutArrow actually extends UIComponent so you have a lot of flexibility to customizing your arrow if desired. In my simple example, I showed how you could change the width and height of the arrow in the skin as well as the frame and border width etc to create a different look (keep in mind I am clearly no designer, just giving you some options to play with ;) )!!

Here’s the code for the custom Callout skin:

package skins
{
	import mx.core.DPIClassification;
	import spark.skins.mobile.CalloutSkin;
	import spark.skins.mobile.supportClasses.CalloutArrow;

	public class MyCalloutSkin extends CalloutSkin
	{
		public function MyCalloutSkin()
		{
			switch (applicationDPI)
			{
				// add in other cases for 240 and 320 DPI above if needed
				// right now most tablets are 160
				case DPIClassification.DPI_160:
				{
					backgroundCornerRadius = 8;
					frameThickness = 8;
					arrowWidth = 82; //default is 52 at 160 DPI
					arrowHeight = 46; // default is 26 at 160 DPI
					borderColor=0xAA0D0A;
					borderThickness=5;
					frameThickness=9;
					contentCornerRadius = 40;
					break;
				}
			}
		}
	}
}

The Tab 4 View class code is shown below with the custom skin applied. You can also see that it uses an inline Callout component rather than a separate MXML file:

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark" title="Inline Callout with Skin"  xmlns:components="components.*"
		viewActivate="view1_viewActivateHandler(event)" viewDeactivate="callout.close()">
	<fx:Script>
		<![CDATA[
			import components.MyCalloutComp;

			import spark.events.ViewNavigatorEvent;
			protected var callout:Callout1;

			protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
			{
				callout=new Callout1();
			}
		]]>
	</fx:Script>

	<fx:Declarations>
		<fx:Component className="Callout1">
			<s:Callout xmlns:fx="http://ns.adobe.com/mxml/2009"
			           xmlns:s="library://ns.adobe.com/flex/spark" skinClass="skins.MyCalloutSkin" verticalPosition="after">
				<s:VGroup paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" horizontalAlign="center">
					<s:Label text="My Story" fontWeight="bold" fontSize="30" color="0xAA0D0A"/>
					<s:TextArea text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur accumsan felis ac tortor aliquam iaculis. Phasellus hendrerit viverra enim, sit amet scelerisque lectus dictum at. Aenean sodales nisi sed leo congue et porttitor ligula vehicula.
Pellentesque turpis massa, suscipit vel fermentum quis, dignissim sed ipsum. Nulla aliquet libero adipiscing risus lobortis eleifend quis at velit. Duis at leo urna.
Praesent facilisis faucibus neque, ut ullamcorper lacus gravida a. Donec vel iaculis sapien." skinClass="spark.skins.mobile.TextAreaSkin" width="90%" editable="false"/>
				</s:VGroup>
			</s:Callout>
		</fx:Component>
	</fx:Declarations>

	<s:layout>
		<s:VerticalLayout paddingTop="40" paddingBottom="8" paddingLeft="8" paddingRight="8" gap="15"
						  horizontalAlign="center"/>
	</s:layout>

	<s:TextArea skinClass="spark.skins.mobile.TextAreaSkin" width="90%"
				text="You can specify a Callout component inline rather than in separate MXML as shown in this sample. You can also apply a custom skin since the Callout
component extends the SkinnablePopUpContainer class. Click the story icon below to invoke a skinned callout."/>
	<s:Image id="img" source="@Embed(source='text48.png')" click="callout.open(img)"/>
</s:View>

Download the source for the sample tabbed application HERE.

Check out this article to find about more features available in Flash Builder 4.6/Flex 4.6 and sign up for the prerelease today if you haven’t already!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值