Home >
ProfilePic Component
In the last article we discussed how components are built with the facebook api in mind. Now it's the time to do something more with it. We know how things need to be set up in order for the components to work. We learned about sessions, about the tow frame time line structure of the components and we talked about the inheritance of the UIComponent class. The previous example leveraged just a small potion of the methods that UIComponent provides. In this article we will take more advantange of the UIComponent class in order to create a component for the profile pic.

Find the rest of this series on the series page.
Here is the structure of the UserStatus component from the previous article:
package facebookUI{
import fl.core.UIComponent;
import flash.text.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.data.friends.*;
import com.facebook.commands.users.*;
import com.facebook.commands.friends.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class UserStatus extends UIComponent{
private var _status_txt:TextField = null;
function UserStatus() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
_status_txt = new TextField();
addChild(_status_txt);
}
public function loadStatus(fbook:Facebook) {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_status_txt.text = user.status.message;
}
}
}
Of course, this is the UserStatus class that works purely with text. There is no resizing, no fonts, nothing special. We need to create a new component that will better demonstrate the capabilities of the UIComponent class. Like above mentioned, we will work on the component that handles the profile pictures of the user. We will use the sizing methods to properly re size the image in the component. The big advantage the will be that it can be visually placed and re sized anywhere on the stage which makes the development of the applications more fun.
Open the fla file we previously worked on. Remove the code from the first frame of the main timeline, also, remove the UserStatus component from the stage.
Next thing we need to do create the MovieClip that will act as the component. Go to insert -> New Symbol and create a MovieClip called ProfilePicDisplay.
Cool, remember the facebookUI package we talked about previously? We discussed that the package should be used as a neat collection of FB component classes. In this example we will place the class file in this package too and link the symbol with the class.
So, let's create the class file. Go to File -> New -> ActionScript file.
Save it as ProfilePicDisplay.as. Here is how the class sceleton of the class is defined:
package facebookUI{
import fl.core.UIComponent;
public class ProfilePicDisplay extends UIComponent{
function ProfilePicDisplay() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
}
}
}
There is nothing strange here. First we import the UIcomponent definition at:
import fl.core.UIComponent;
Then we inherit all the features from the class to the class ProfilePicDisplay:
public class ProfilePicDisplay extends UIComponent
And in the rest of the code, we see the empty constructor and the overridden configUI() method, which we will use later to set up the objects on the stage.
Go back to the fla file. Now we need to recreate the two frame structure that was discussed in the last article. Here is the image of it:
Let's discuss now about the assets that we need to export together with the ProfilePicDisplay component. We will need the UILoader component and like in the last sample, we need the Facebook library SWC from the like in the previous example. Remember that the SWC and UILoader need to be „carried“ together with the component throughout the project.
Click on the second frame of the Assets layer and drag the Facebook SWC to the stage:
After that, drag one instance of the UILoader component to the stage:
Dont forget to uncheck the „Export in first frame“ option for the UIComponent in the library. No need to give any instance names to this objects on the stage. Now let's move on to the first frame of the avatar layer. Again, like in the previous example, use a Hairline stroke to draw a rectangle with no fill on the stage, size 180 x 180:
Approximately this is the size of a standard profile pic on facebook. In fact the size does not matter at all here since the component will resize itself accoring to the size of the image that is loaded.
Now go to the library and right click the ProfilePicDisplay component. Make sure the following class paths are set:
Cool, the component is not finished but we just linked the class with the movieclip and this is a big step forward. To demonstrate that everything works fine place one instance of the ProfilePicDisplay component from the library to the empty stage. When compiled, it should not give any errors. If it does, then please do not read further and try to trace down the errors.
Now, since we created a working movieclip and also created the class structure it's time for us to move on. Lets start by adding some code to the existing class. Here we see the basic class:
package facebookUI{
import fl.core.UIComponent;
public class ProfilePicDisplay extends UIComponent{
function ProfilePicDisplay() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
}
}
}
Let's start with adding objects to the display list. First we need to import facebook specific classes and the UILoader class:
import fl.containers.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.commands.users.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
This code will be pasted directly below the import fl.core.UIComponent; statement.
Next thing we want to do is to declare the variable to hold the UILoader:
private var _picLoader:UILoader = new UILoader();
Then we add it to the stage in the configUI loader:
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
this.addChild(_picLoader);
}
Ok, when compiled, it does not give any errors but also it does not diplay anything. Before making any calls to the facebook api, we need to make sure that the image loading works.
Go to facebook and load your profile page.
If you are in FireFox, right click on your profile image and click „Copy Image location“:
We just copied the profile pic image path to the clipboard. Now, we simply need to republish set the source property of the loader:
_picLoader.source = "http://profile.ak.facebook.com/v224/120/49/n1110516263_7773.jpg";
Publish the swf and you will see the result:
As we can see the result is a bit modest. Now we can play a little bit with the properties. Let's say we set the scaleContent property to false:
_picLoader.scaleContent = false;
Cool, we can now see that the image loads in actual size. You can imagine how many options we have to customize the loader, there are pretty much endless! Try to move the component around the stage and place it in different corners. Try to place multiple ones to see it is working.
We can see now how it is easy to load images from the directly to from facebook. Still we are not finished, we want to make calls to facebook. But it is important how easy it is to work with components once they are properly designed.
Now, finally let's make the facebook call. Until now, our class displays a picture from a constant path and that is something we do not want. We need to add the following method to our class:
public function load(fbook:Facebook):void {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.PIC_BIG]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
I will not go much into detail as the function is very similar to the one before. Let's jump directly to the onInfo callback:
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_picLoader.source = user.pic_big;
}
Here is the overview of the complete class:
package facebookUI{
import fl.core.UIComponent;
import fl.containers.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.commands.users.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class ProfilePicDisplay extends UIComponent{
private var _picLoader:UILoader = new UILoader();
function ProfilePicDisplay() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
this.addChild(_picLoader);
}
public function load(fbook:Facebook):void {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.PIC_BIG]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_picLoader.source = user.pic_big;
}
}
}
Now, let's jump to the main timeline. We add the code similar to the one from yesterday:
import com.facebook.Facebook;
import com.facebook.utils.FacebookSessionUtil;
var fbook:Facebook;
var session:FacebookSessionUtil = new FacebookSessionUtil("YOUR_API_KEY", "YOUR_SECRET", loaderInfo);
fbook = session.facebook;
pic1_mc.load(fbook);
Before we compile the swf, we need to make sure that there is only one component on the stage called pic1_mc. When we run the example, here is the result:
Cool! The component acts now as „independent“. Once we created the facebook session, we passed it to the component and the component loads it. There is still penty of stuff that needs to be added to make a real component out of this. Let's start with resizing.
The resizing in the component is not that easy. Technically, it is not correct to set the width and the heigth property of the component, instead we should use the setSize method. setSize is a method implemented by default in the UIComponent framework. In order to create a solid resizing logic, we should extend the setSize method. The setSize method is called anytime even when the component is initiated with the default size. Here is the proof. Place this overridden setSize method inside the class:
override public function setSize(width:Number, height:Number):void{
trace("Width: " + width);
invalidate();
}
Compile the swf and as the result we will see that the output is 177.5, the default size of the component. Now, let's got back to the main timeline and resize it via the Free Transform tool:
Now let's compile it again, and we will see that there is a different width displayed. This is a simple proof that the setSize method is called even if the component was not resized in the Flash IDE. So, now it's clear that in order to create a fancy resizing for any component (not just this one) we have to stuck to the setSize method.
In the setSize method, we also see the invalidate() call. This call redraws the whole component by calling the draw() method. In the UIComponent architecture it is never recommended to call the draw() method directly, invalidate() should be called instead. So, in order for that to work, we need to override the existing draw method, so place this code into the class file:
override protected function draw():void {
trace("drawing component...");
// always call super.draw() at the end
super.draw();
}
We we run the swf, we see the following in the output window:
See the order how the methods are called? First the setSize() method, then after the invalidate() call, the draw() method is called. Now lets remove the trace statements and add some code direcly to the draw method:
override protected function draw():void {
_picLoader.width = width;
_picLoader.height = height;
// always call super.draw() at the end
super.draw();
}
Also, remove the override setSize method. We dont need is since it was implemented just to demonstrate the order of how the methods are called. The default setSize() method calls the draw() method. So, resize the component randomly on the stage, my sample is much smaller then the original size.
Cool! Thats a big step forward. Let's try to work with resizing directly via ActionScript. At the beginning, we mentioned that the component on the stage should be named pic1_mc. If that's the case, we should place the following script to the main timeline:
pic1_mc.setSize(10, 10);
And the tiny result is:
Wow, we almost have a great small component that will handle all the profile pics.
Here is the complete class code for better overview:
package facebookUI{
import fl.core.UIComponent;
import fl.containers.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.commands.users.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class ProfilePicDisplay extends UIComponent{
private var _picLoader:UILoader = new UILoader();
function ProfilePicDisplay() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
this.addChild(_picLoader);
}
public function load(fbook:Facebook):void {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.PIC_BIG]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_picLoader.source = user.pic_big;
}
override protected function draw():void {
_picLoader.width = width;
_picLoader.height = height;
// always call super.draw() at the end
super.draw();
}
}
}
Now we should move on to make the component capable of loading profile pics of other users. So in that case, we need to provide the user id. We need to implement the method to receive the user id, so here is how it goes.
Go to facebook and browse your friends:
Find the id of one of your friends:
Copy only the uid to the clipboard. Now go to the main timeline and extend the load method like this:
pic1_mc.load(fbook, 1110516263);
Also, extend the load method inside the class file in order to match the new argument count:
public function load(fbook:Facebook, uid:Number):void {
var call:GetInfo = new GetInfo([uid], [GetInfoFieldValues.PIC_BIG]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
Now, when you run the example you will see one friend of you, here my cousin Ajdin:
Cool, now let's place a lot more components with different uids. Here is the fancy result:
Isn't that cool? For now we will leave this untouched. Yes I know that it can be further developed but for now this is ok. We can add preloaders, we can add effects etc. Here is the complete class cod so we dont get confused:
package facebookUI{
import fl.core.UIComponent;
import fl.containers.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.commands.users.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class ProfilePicDisplay extends UIComponent{
private var _picLoader:UILoader = new UILoader();
function ProfilePicDisplay() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
this.addChild(_picLoader);
}
public function load(fbook:Facebook, uid:Number):void {
var call:GetInfo = new GetInfo([uid], [GetInfoFieldValues.PIC_BIG]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_picLoader.source = user.pic_big;
}
override protected function draw():void {
_picLoader.width = width;
_picLoader.height = height;
// always call super.draw() at the end
super.draw();
}
}
}
I hope that this article was not to confusing. In the next one, we will discuss how to implement effects and other extras. There ideas of how to extend this component are pretty much endless. I can only guarantee that the next article will cover only a portion of possible enhancements tha can be built into the profile pic. But before the next article, make sure you work hard to get this component done. It is in fact not so complicated as it seems. Also, it's important to know that the rest of the components will use the same resizing strategies. Once you successfully mastered the resizing, you will be able to create new upcoming components much easier. So, dear readers, until the next article, take care and stay tuned!
To view the entire series please visit http://www.insideria.com/series-facebook-dev.html




Facebook Application Development
v.avtsidis@picasso.com.au