Guide To Create Orientation Awareness In Sencha Touch Apache Cordova App - Part One

I have been writing about Sencha Touch and Cordova for some time now. In a way, it is the documentation of my learning of these two platforms in the last couple of months, which might help somebody out there struggling with the same issues, which I once had. I had never used Sencha Architect for my development environment. I am using Visual Studio as a Text Editor as well as Packager for Cordova Applications with TACO extension.

In my path of mastering Cordova and Sencha Touch, I have stumbled upon building the orientation aware Applications, using these frameworks and this is the part 1 of a multi-part tutorial about how to create orientation aware, cross-platform Application, using these two frameworks.

For any orientation aware Application, there are two things, which the developer should take care of:

  1. Device orientation at the start of the Application.
  2. Orientation change events.

We need to look into the Application architecture to decide, how to incorporate the orientation change in the Application. As you know, Sencha Touch framework works on MVC architecture with a slight twist of Stores and Profiles. If you are interested in Sencha Touch architecture and how profiles work in Sencha Touch, this post might be useful for you. Right now, our focus is not on Models, Controllers, and Stores but purely on Views of the Application as the orientation will only affect the views of the Application. In the context of Sencha Touch, profiles also play a crucial role, while designing an orientation awareness. A lot of times, your views are different for the different profiles of the Application. For the simplicity of the tutorial, I am going to take two profiles - one tablet and one phone and build orientation awareness for both of them.

Here are the steps, which we are going to follow, while building orientation aware Applications:

  1. Create a sample Application with the two profiles – Tablet and Mobile.
  2. Install Orientation Plugin from Cordova plugin manager.
  3. Create views and controller.
  4. Add views to the viewport, based on the orientation of the device at the start of the Application.
  5. Handle the orientation change event.
  6. Take care of the stylesheets.

To start with, I created a sample Cordova Application in Visual Studio 2015, named OrientationTutorial. I added Sencha-Touch-Debug.js and Sencha-Touch.css files to my Application’s root folder and loaded them in index.html. Pretty normal stuff, isn’t it? The tricky part is, unlike Sencha Architect, Visual Studio doesn’t have the desired visual builder for Sencha Touch, which can let you build your views, controllers, models, stores, profiles in the different folders and build a nice app.js for you in the end. Thus, we have to do it ourselves.

In app.js, I created the Application while in View, Profile and Controller folders, I created respective Views, profiles and the controllers. I load all the files in index.html body and pray to God that everything works fine. (Kidding, when Sencha Touch breaks, even God cannot fix it). Solution Explorer looks like:

solution explorer

Main View is basically just the toolbar on the top of the Application. Home View has some example buttons, which does nothing basically. (At least for now). Thus, here is how, we are going to do it. We create Main View, which is a container with a toolbar on the top and stick it to the Application forever. Based on the orientation of the application we change, add the appropriate Home View to the application.

Go to config.xml, open plugin tab, and add orientation plugin to your application. It should look something like this:


I have created the Main View at the launch of the respective profile. That means the Main View is added when the phone/tablet profile is launched.

All the default Views, such as homePhone and homeTablet are by default landscape Views. We will create portrait View differently. For that, add the folder to the View folder called ‘portrait’. Inside this, create homePortrait View.

Now, some important things. In our design architecture, we are going to create Views, based on their aliases. Sencha Touch creates aliases, based on xtypes in the background, which means we cannot use the same xtype for the Views, which are essentially the same , but are designed differently for the different profiles and orientation. For example, Home View has 5 buttons and all works in the similar fashion but, based on whether the view is rendered on a tablet or a phone and whether the orientation is a portrait or a landscape, the position of these buttons change. Thus, for these different renderings, we have different Views but we might need the same xtype in the Controller for these Views to tie these to some Model or load the data from the Store.

To overcome this problem, we use two approaches. We tie different profile Views to the same widget by inserting the profile name between them explicitly at the initialization of the profile. This way, the Views can share same xtype but are rendered, based on their profile names. This works for the profiles because on one device, only one profile is activated. The code looks something like this :
  1. Ext.ClassManager.setAlias('OrientationTutorialApp.view.tablet.Home''widget.homeView');  
However, what about orientation? Orientation can change multiple times, while using the Application. Thus, we cannot even explicitly tie the orientation View to the alias. To fix this, we need to simply create the View by adding widget.portrait.* to the item ID of the View, whenever the portrait view is to be created and for landscape view, we just use normal alias. Also, inside the Controller, we avoid using alias in the configuration refs. This is because, when you use alias in config refs and you have to use the Views inside controllers, you have to invoke them twice with the two different aliases. This increases the duplicate code. Instead, one can either use IDs or Ref. IDs are advised against by Sencha Developer Team and rightfully so IDs add a lot of confusion, as well as, if you don’t destroy the Views with same ID's, you are in  deep trouble with the multiple hours of debugging of one line of the code. Ref however, in my opinion, is the best approach to tackle this issue. The configuration inside the Controller should look like:


Notice the refs in the Config.

Here is how the landscape view of the home looks:

landscape view

I have created five sample buttons and arranged them in a bit vbox container and then smaller hbox containers. The arrangement has been handled in the Sencha View while positioning and sizes are configured in CSS.

When the application is launched, the showTab function is launched with the ID of homeView. ShowTab function checks the current orientation of the device and accordingly, adds the prefix to the ID in order to create the correct widget with alias.

The code snippet is as follows:


Now, without creating portrait view of home, if we just apply an orientation change event, this happens:


As you can see, the View is totally distorted, buttons cannot be seen and Title bar cannot hold the complete text. Some of this can be handled by CSS (Which I will cover in the next part of this tutorial), however, in order to give seamless experience to the end user, one needs to design a different view altogether.

Thus, I created a portrait version of the Home View. Notice, it has the same ID and same ref, but not-same xtype. This is very important. You cannot have two Views with the same xtype. It creates a hell of a confusion inside the framework and more often than not, the framework gives you the wrong View for the wrong orientation.


The View looks like:


As you can see, the View is still not perfect. Background is not exactly in the center nor is it visible, as well as buttons need better alignment and title bar can do with a smaller font to accommodate complete text. However, we will take care of that with CSS.

Now, the only thing that remains is handling the orientation change event. For that, we add an orientation change event to viewport, and handle it in onOrientationChange function. Well, there is actually nothing much to handle. Just get the active items id which in this case is homeView. Destroy the landscape component and add the portrait with the help of showTab function which I have already described above.

In Main Controller, I added control to viewport inside config and the function on OrientationChange is created in Main Controller as, given below:


That’s all. The basic orientation awareness is implemented. In the next part, I will talk about creating the different classes for the different orientations and handling the multiple views.