14 min read

(For more resources related to this topic, see here.)

One window to rule them all

Since we want to give our users the ability to post their messages on multiple social networks at once, it makes perfect sense to keep our whole application in a single window. It will be comprised of the following sections:

  • The top section of the window will contain labels and a text area for message input. The text area will be limited to 140 characters in order to comply with Twitter’s message limitation. As the user types his or her message, a label showing the number of characters will be updated.
  • The bottom section of the window will use an encapsulating view that will contain multiple image views. Each image view will represent a social network to which the application will post the messages (in our case, Twitter and Facebook). But we can easily add more networks that will have their representation in this section. Each image view acts as a toggle button in order to select if the message will be sent to a particular social network or not.
  • Finally, in the middle of those two sections, we will add a single button that will be used to publish the message from the text area.

Code while it is hot!

With our design in hand, we can now move on to create our user interface. Our entire application will be contained in a single window, so this is the first thing we will create. We will give it a title as well as a linear background gradient that changes from purple at the top to black at the bottom of the screen. Since we will add other components to it, we will keep its reference in the win variable:

var win = Ti.UI.createWindow({ title: 'Unified Status', backgroundGradient: { type: 'linear', startPoint: { x: '0%', y: '0%' }, endPoint: { x: '0%', y: '100%' }, colors: [ { color: '#813eba'}, { color: '#000' } ] } });

The top section

We will then add a new white label at the very top of the window. It will span 90% of the window’s width, have a bigger font than other labels, and will have its text aligned to the left. Since this label will never be accessed later on, we will invoke our createLabel function right into the add function of the window object:

win.add(Ti.UI.createLabel({ text: 'Post a message', color: '#fff', top: 4, width: '90%', textAlign: Ti.UI.TEXT_ALIGNMENT_LEFT, font: { fontSize: '22sp' } }));

We will now move on to create our text area where our users will enter their messages. It will be placed right under the label previously created, occupy 90% of the screen’s width, have a slightly bigger font, and have a thick, rounded, dark border. It will also be limited to 140 characters. It is also important that we don’t forget to add this newly created object to our main window:

var txtStatus = Ti.UI.createTextArea({ top: 37, width: '90%', height: 100, color: '#000', maxLength: 140, borderWidth: 3, borderRadius: 4, borderColor: '#401b60', font: { fontSize: '16sp' } }); win.add(txtStatus);

The second label that will complement our text area will be used to indicate how many characters are currently present in the user’s message. So, we will now create a label just underneath the text area and assign it a default text value. It will span 90% of the screen’s width and have its text aligned to the right. Since this label will be updated dynamically when the text area’s value changes, we will keep its reference in a variable named lblCount. As we did with our previous UI components, we will add our label to our main window using the following code:

var lblCount = Ti.UI.createLabel({ text: '0/140', top: 134, width: '90%', color: '#fff', textAlign: Ti.UI.TEXT_ALIGNMENT_RIGHT }); win.add(lblCount);

The last control from the top section will be our Post button. It will be placed right under the text area and centered horizontally using the following code:

var btnPost = Ti.UI.createButton({ title: 'Post', top: 140, width: 150 }); win.add(btnPost);

By not specifying any left or right property, the component is automatically centered. This is pretty useful to keep in mind while designing our user interfaces, as it frees us from having to do calculations in order to center something on the screen.

Staying within the limits

Even though the text area’s maxLength property will ensure that the message length will not exceed the limitation we have set, we need to give our users feedback as they are typing their message. To achieve this, we will add an event listener on the change event of our text area. Every time; the text area’s content changes, we will update the lblCount label with the number of characters our message contains:

txtStatus.addEventListener('change', function(e) { lblCount.text = e.value.length + '/140';

We will also add a condition to check if our user’s message is close to reaching its limit. If that is the case, we will change the label’s color to red, if not, it will return to its original color:

if (e.value.length > 120) { lblCount.color = 'red'; } else { lblCount.color = 'white' }

Our last conditional check will be enabling the Post button only if there is actually a message to be posted. This will prevent our users from posting empty messages:

btnPost.enabled = !(e.value.length === 0); });

Setting up our Post button

Probably the most essential component in our application would be the Post button. We won’t be able to post anything online (yet) by clicking on it, as there are things we will still need to add.

We will add an event listener for the click event on the Post button. If the on-screen keyboard is displayed, we will call the blur function of the text area in order to hide it:

btnPost.addEventListener('click', function() { txtStatus.blur();

Also, we will reset the value to the text area and the character count on the label, so that the interface is ready to enter a new message:

txtStatus.value = ''; lblCount.text = '0/140'; });

The bottom section

With all our message input mechanisms in place, we will now move on to our bottom section. All components from this section will be contained in a view that will be placed at the bottom of the screen. It will span 90% of the screen’s width, and its height will adapt to its content. We will store its reference in a variable named bottomView for later use:

var bottomView = Ti.UI.createView({ bottom: 4, width: '90%', height: Ti.UI.SIZE });

We will then create our toggle switches for each social network that our application interacts with. Since we want something sexier than regular switch components, we will create our own switch using a regular image view.

Our first image view will be used to toggle the use of Facebook. It will have a dark blue background (similar to Facebook’s logo) and will have a background image representing Facebook’s logo with a gray background, so that it appears disabled. It will be positioned to the left of its parent view, and will have a borderRadius value of 4 in order to give it a rounded aspect. We will keep its reference in the fbView variable and then add this same image view to our bottom view using the following code:

var fbView = Ti.UI.createImageView({ backgroundColor: '#3B5998', image: 'images/fb-logo-disabled.png', borderRadius: 4, width: 100, left: 10, height: 100 }); bottomView.add(fbView);

We will create a similar image view (in almost every way), but this time for Twitter. So the background color and the image will be different. Also, it will be positioned to the right of our container view. We will store its reference in the twitView variable and then add it to our bottom view using the following code:

var twitView = Ti.UI.createImageView({ backgroundColor: '#9AE4E8', image: 'images/twitter-logo-disabled.png', borderRadius: 4, width: 100, right: 10, height: 100 }); bottomView.add(twitView);

Last but not the least, it is imperative that we do not forget to add our bottomView container object into our window. Also, we will open the window so that our users can interact with it using the following code:

win.add(bottomView); win.open();

What if the user rotates the device?

At this stage, if our user were to rotate the device (to landscape), nothing would happen on the screen. The reason behind this is because we have not taken any action to make our application compatible with the landscape mode. In many cases, this would require some changes to how the user interface is created depending on the orientation. But since our application is fairly simple, and most of our layout relies on percentages, we can activate the landscape mode without any modification to our code.

To activate the landscape mode, we will update the orientations section from our tiapp.xml configuration file. It is mandatory to have at least one orientation present in this section (it doesn’t matter which one it is). We want our users to be able to use the application, no matter how they hold their device:

<iphone> <orientations device="iphone"> <orientation>Ti.UI.PORTRAIT</orientation> <orientation>Ti.UI.UPSIDE_PORTRAIT</orientation> <orientation>Ti.UI.LANDSCAPE_LEFT</orientation> <orientation>Ti.UI.LANDSCAPE_RIGHT</orientation> </orientations> </iphone>

By default, no changes are required for Android applications since the default behavior supports orientation changes. There are, of course, ways to limit orientation in the manifest section, but this subject falls out of this article’s scope.

See it in action

We have now implemented all the basic user interface. We can now test it and see if it behaves as we anticipated. We will click on the Run button from the App Explorer tab, as we did many times before.

We now have our text area at the top with our two big images views at the bottom, each with the social network’s logo. We can already test the message entry (with the character counter incrementing) by clicking on the Post button.

Now if we rotate the iOS simulator (or the Android emulator), we can see that our layout adapts well to the landscape mode.

To rotate the iOS simulator, you need to use the Hardware menu or you can use Cmd-Left and Cmd-Right on the keyboard. If you are using the Android emulator, there is no menu, but you can change the orientation using Ctrl + F12.

The reason this all fits so well is because most of our dimensions are done using percentages. That means that our components will adapt and use the available space on the screen. Also, we positioned the bottom view using the bottom property; which meant that it will stick to the bottom of the screen, no matter how tall it is.

There is a module for that

Since we don’t want to interact with the social network through manual asynchronous HTTP requests, we will leverage the Facebook native module provided with Titanium. Since it comes with Titanium SDK, there is no need to download or copy any file.

All we need to do is add a reference (one for each target platform), in the modules section of our tiapp.xml file as follows:

<modules> <module platform="android">facebook</module> <module platform="iphone">facebook</module> </modules>

Also, we need to add the following property at the end of our configuration file, and replace the FACEBOOK_APPID parameter with the application ID that was provided when we created our app online.

<property name="ti.facebook.appid">[FACEBOOK_APPID]</property>

Why do we have to reference a module even though it comes bundled with the Titanium framework? Mostly, it is to avoid framework bloat; it is safe to assume that most applications developed using Titanium won’t require interaction with Facebook. This is the reason for having it in a separate module that can be loaded on demand.

Linking our mobile app to our Facebook app

With our Facebook module loaded, we will now populate the necessary properties before making any call to the network. We will need to set the appid property in our code; since we have already defined it as a property in our tiapp.xml file, we can access it through the Properties API. This is a neat way to externalize application parameters, thus preventing us to hardcode them in our JavaScript code:

fb.appid = Ti.App.Properties.getString('ti.facebook.appid');

We will also set the proper permissions that we will need while interacting with the server. (In this case, we only want to publish messages on the user’s wall):

fb.permissions = ['publish_actions'];

It is important to set the appid and permissions properties before calling the authorize function. This makes sense since we want Facebook to authorize our application with a defined set of permissions from the get-go.

Allowing our user to log in and log out at the click of a button

We want our users to be able to connect (and disconnect) at their will from one social network, just by pressing the same view on the screen. To achieve this, we will create a function called toggleFacebook that will have a single parameter:

function toggleFacebook(isActive) {

If we want the function to make the service active, then we will verify if the user is already logged in to Facebook. If not, we will ask Facebook to authorize the application using the function with the same name. If the parameter indicates that we want to make the service inactive, we will log out from Facebook altogether:

if (isActive) { if (!fb.loggedin) { fb.authorize(); } } else { fb.logout(); } }

Now, all that we need to do is create an event listener on the click event for our Facebook image view and simply toggle between the two states depending whether the user is logged in or not:

fbView.addEventListener('click', function() { toggleFacebook(!fb.loggedIn); });

The authorize function prompts the user to log in (if he or she is not already logged in), and authorize his or her application. It kind of makes sense that Facebook requires user validation before delegating the right to post something on his or her behalf.

Handling responses from Facebook

We have now completely implemented the Facebook login/logout mechanism into our application, but we still need to provide some feedback to our users. The Facebook module provides two event listeners that allow us to track when our user will have logged in or out.

In the login event listener, we will check if the user is logged in successfully. If he or she did, we will update the image view’s image property with the colored logo. If there was any error during authentication, or if the operation was simply cancelled, we will show an alert, as given in the following code:

fb.addEventListener('login', function(e) { if (e.success) { fbView.image = 'images/fb-logo.png'; } else if (e.error) { alert(e.error); } else if (e.cancelled) { alert("Canceled"); } });

In the logout event listener, we will update the image view’s image property with the grayed out Facebook logo using the following code:

fb.addEventListener('logout', function(e) { fbView.image = 'images/fb-logo-disabled.png'; });

Posting our message on Facebook

Since we are now connected to Facebook, and our application is authorized to post, we can now post our messages on this particular social network. To do this, we will create a new function named postFacebookMessage, with a single parameter, and that will be the message string to be posted:

function postFacebookMessage(msg) {

Inside this function, we will call the requestWithGraphPath function from the Facebook native module. This function can look fairly complex at first glance, but we will go over each parameter in detail. The parameters are as follows:

  • The Graph API path requested (My feed).
  • A dictionary object containing all of the properties required by the call (just the message).
  • The HTTP method used for this call (POST).
  • The callback function invoked when the request completes (this function simply checks the result from the call. In case of error, an alert is displayed).

    fb.requestWithGraphPath('me/feed', { message: msg }, "POST", function(e) { if (e.success) { Ti.API.info("Success! " + e.result); } else { if (e.error) { alert(e.error); } else { alert("Unknown result"); } } } ); }

We will then update the click event handler for the Post button and call the postFacebookMessage function if the user is logged in to Facebook:

btnPost.addEventListener('click', function() { if (fb.loggedIn) { postFacebookMessage(txtStatus.value); } ... });

With this, our application can post messages on our user’s Facebook wall.

Summary

In this article, we learned how to create server-side applications on two popular social networking websites. We learned how to interact with those networks in terms of API and authentication. We also learned how to handle device rotation as well as use the native platform setting Windows. Finally, we covered Titanium menus and activities.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here