Titanium TableView to ListView: A Retrospective

Titanium TableView to ListView: A Retrospective

I recently had the opportunity to switch a client app over to making use of the (relatively) new Titanium ListView.  The ListView is a high-performance UI element designed to display templated sets of data in an ordered fashion, making use of some arcane optimizations that I can only assume involves black magic to beat out the performance of a table view by an order of magnitude.  Coming from TableViews, the switch over to ListViews was somewhat jarring, differences in view structure, event structure, and the unique quirks of these view elements made the transition a somewhat challenging process.  Here are a few interesting things I learned in the process.

Everything is structured.

Everyone has a few guilty little lapses in structure when making an app.  Why bother redesigning a view for one specific case when I can just add the new view elements at run time?  ListViews will have no part of that. Each template has a static set of views, and after creation, the elements in a given row are unchanging.  The only way to change the information contained in a row is to push a new data object to the row, and the only way to add another view element is to modify the template.  This requires a rather significant shift in how you develop for list views, as ad-hoc development and spaghetti code just doesn’t work with list views.

There are no row events.  Only list events.

This was one of the most distinct differences in developing for ListViews as opposed to TableViews.  Where Table views expose all of the events available to their child elements to you, ListViews expose a solitary ‘itemclick’ event.  As the name suggests, this event is triggered when the user clicks on an individual list item.  From there, you need to sort out what to do with the individual item, figure out which subview triggered the event, and proceed from there as you would with any click event.

Quirks, limitations, and tradeoffs

One major consideration with using a ListView is that they are in active development, and as such have a number of quirks and limitations, not all of which are documented.  At one point, I had been debugging an app crash that produced no error messages and realized that simply changing the bindId of one of the subviews of a template fixed it completely.  Additionally, there are a number of little styling quirks (for instance, you can’t presently style the separator color or the section header/footer), and an I mentioned earlier you cannot change the contents of a row without rebuilding and replacing it.  As with all new view elements, you need to weigh these drawbacks against the benefits before you’ve spent the better part of a week developing with a view element that just won’t work.

The benefits

The core benefits of list views are, as I see it, performance and maintainability.  The forced structure of list views require you to declare all of your view elements upfront, to run all of your events through the same functions, and structure all of your data in the same way, making a well designed ListView much easier to understand and maintain than an equally well designed TableView.  Additionally, the performance isn’t even comparable.  Before switching over to ListViews, we were lucky to get twenty items into our lists.  Now, we can easily load more than 500 at a time.  That kind of performance difference speaks for itself.

Titanium Conference 2013 – TiConf.US

Titanium Conference 2013 – TiConf.US

America’s first and premier community-run mobile development conference

Update: For a limited time, receive $70 off, when you register using code SHOCKOE70

Shockoe is a proud sponsor of the next mobile development conference primarily based around JavaScript and Appcelerator Titanium. It’s a community-run event featuring some of the best JavaScript and Titanium Mobile developers from the US and abroad.

Titanium Conference 2013 takes place between the 28th-29th of June 2013 – open to all regardless of your skill level. Come and meet us there, we would love to talk to you.

 

Beginner’s Titanium: Titanium DisplayCaps on iOS

There are now a multitude of device resolutions and densities running iOS, how can you make sure your content appears how you want it to appear regardless of which device your users have? This is, of course, one of the trickier areas for mobile applications. Fortunately, Titanium Studio has tools to help us attack this problem. Initially I thought that the DisplayCaps properties I could access through the Titanium API would produce the exact pixel dimensions of the device my App was running on. Upon a more careful inspection of the Titanium documentation these properties will produce values of “density-independent pixels (dip) on iOS”. I went ahead and ran a few tests on the simulator to determine what values I would receive on each device:

[cc]
Ti.API.info(“height: ” + Ti.Platform.displayCaps.platformHeight);
Ti.API.info(“width: ” + Ti.Platform.displayCaps.platformWidth);
[/cc]

iPad (non-retina): height: 1024 width: 768
iPad (retina): height: 1024 width: 768
iPhone (non-retina): height: 480 width: 320
iPhone (3.5 inch retina): height: 480 width: 320
iPhone (4 inch retina): height: 568 width: 320

Also keep in mind that the values are relative the the orientation of the UI (not necessarily the physical orientation of the device). Another useful property of Ti.Platform is the dpi property which can provide useful information about whether the device has a retina display or not. This information helped clear up some issues for me and enabled me to better plan layouts for multiple devices, I hope the information was helpful for your App Development as well!

Beginner’s Titanium: Working With Map Annotations on iOS

With the release of Apple’s iOS 6 the device’s maps have changed from the usage of Google maps to using Apple’s own mapping service.  Fortunately, very little has changed when working with map annotations across iOS versions 5 and 6.

Today we are taking a closer look at some of the features when utilizing map annotations.  A map annotation requires a latitude and longitude value to tell the map where to display the annotation.  Although this is all that is required to display a pin on the map, if you want to detect click events on your map pins, then you will need to add a title to the annotation.
var myannotation = Ti.Map.createAnnotation({

latitude: latitude, //coordinates

longitude: longitude, //coordinates

animate: false,  //it won’t animate the pin

title: “My Title”, // will be required if you need to detect a ‘click’ event

subtitle: “My Subtitle”,

image: ‘images/my_annotation_image.png’ // can be used to replace the default pin

});

The click events are registered to the map view itself and the annotation clicked is specified in the event object.  It is also possible to add subtitles and images to your annotation to customize the display of information.  Another great feature is the ability to use custom images for your map pins.
MyMapView.addEventListener('click', function(e){
if(e.clicksource === 'pin'){
Ti.API.info("The Pin at Latitude: " + e.annotation.latitude + " Longitude: " + e.annotation.longitude + " was clicked.");
}
}

The only caveat being that the center of the image is placed at the specified latitude/longitude values.  Possible workarounds are extending the transparent area around your image so that the base of your pin is centered in the image.

Minimizing the size of your custom image also helps due to there being less error in the offset.  Hopefully, an offset property will be released soon!

Changing the custom pin image of an annotation during runtime is a little trickier.  In order for the appearance to be updated, the annotation must be removed and added back to the map view.

Armed with these features, creating a map-based app can be accomplished efficiently with effective results!

Happy Mapping!

Beginner’s Titanium: UI Layouts Using Nested Views

Making user interface elements display how you want them is not always a simple task. The Titanium 2.0 SDK changed the way the ‘auto’ sizing keyword is handled. These changes may require some existing code to be modified in order to produce the same output. So, we’ve put together a simple iOS example to show the use of nested views with the new values Ti.UI.SIZE and Ti.UI.FILL.

We want to make a layout that looks like this:

 

First, let’s create our window.


var window = Ti.UI.createWindow({
    backgroundColor:'lightgray',
});

Next, we want to create an outer view container for our layout and add it to our window. This container’s layout property is set to horizontal so that our content will be added from left to right.


var outerView = Ti.UI.createView({
backgroundColor: 'blue',
layout: 'horizontal',
height: 100,
width: 300,
});

window.add(outerView);

We’ll create an ImageView, set its photo, and add it to our outer view container.


var photo = Ti.UI.createImageView({
width: 7
height: Ti.UI.FILL,
borderColor: '#444',
borderWidth: 2,
borderRadius: 2,
backgroundColor: 'white',
});

photo.image = 'http://www.shockoe.com/media/shockoelogo_web.png';

outerView.add(photo);

Since we don’t want our labels to go directly next to the photo, we need a small buffer. We’ll create a view to use as a buffer and add it to our outer view container.


//5 pixel buffer between photo and nestedViewContainer

outerView.add(Ti.UI.createView({

width: 15,

height: Ti.UI.FILL,

backgroundColor: 'green',

}));

We want a container with a vertical layout so we can add three rows of labels from top to bottom. We create another nested view and use it as a container for labels.


var nestedViewContainer = Ti.UI.createView({
layout: 'vertical',
height: Ti.UI.FILL, //fill remaining height of parent
width: Ti.UI.FILL, //fil remaining width of parent
backgroundColor: 'yellow',
});

We create our Labels and add them to the nested view container.


var topLabel = Ti.UI.createLabel({
text: 'I am topLabel',
width: Ti.UI.SIZE,
height: '50%', //make the top label taller than the others
backgroundColor: 'cyan'
});

var middleLabel = Ti.UI.createLabel({
text: 'I am middleLabel',
height: Ti.UI.SIZE,
width: Ti.UI.FILL,//make this label as wide as its parent view
textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,//center the text in the width of the label
backgroundColor: 'red'
});

var bottomLabel = Ti.UI.createLabel({
text: 'I am bottomLabel',
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
backgroundColor: 'purple'
});

//add our labels to the nestedViewContainer
nestedViewContainer.add(topLabel);
nestedViewContainer.add(middleLabel);
nestedViewContainer.add(bottomLabel);

Finally, we add our nested view container to the outer view container and open our window.


//add our nestedViewContainer to the outerView

outerView.add(nestedViewContainer);

//open our window

window.open();

The UI views are colored to indicate the output of each element.  Comparing the code to the output should provide some idea of how the properties affect the outcome.  Please let us know in the comments section if this example was helpful!

Extending ti.box2d : Mouse Joints

It is common in physics based games to need to be able to drag bodies around. However, setting the position of a body instantaneously based on the current touch position can introduce excessive forces to the physics simulation, and break it. So we need another way to solve this problem…

Enter Box2D’s mouse joint. In our modifications to the ti.box2d module, we have added the mouse joint for use in Titanium games using Box2D. Creating a mouse joint is simple, as shown in the code below.


var mouseJoint = world.createMouseJoint ( groundBody, draggableBody, {
maxForce : 1000,
dampingRatio : 0.6,
frequencyHz : 1.0,
collideConnected : true
});

In the above code sample , world is the result of a call to ti.box2d’s createWorld function. All joints require 2 bodies, even though we generally think of the mouse joint as really only effecting a single body. When creating mouse joints, that second body (the first parameter in this function) is generally a static ground body. The second parameter in our createMouseJoint function is the body that we want to drag around.

We’ll come back to the other options in a moment. First, let’s actually drag the body around. In order to have the body dragged towards a point, we must call the setTarget function on the mouse joint with the x and y coordinates that we want to drag the body to. You’ll generally want to do this in an update loop or anytime the mouse (touch point) moves.


view.addEventListener('touchmove', function(e)
{
mouseJoint.setTarget(e.x, e.y);
});

That’s all you need to start dragging a body around. Now lets circle back to those other options in the creation of the mouse joint. The maxForce property is the maximum amount of force that will be applied to the body in order to get it to its target point. collideConnected indicates whether the draggableBody should be allowed to collide with the groundBody.

The last two properties, dampingRatio and frequencyHz, are the parameters you will need to tweak the most to get the kind of dragging feel that you want. If you want very tight dragging, you will need a higher frequency and damping ratio. If you want some oscillation after the body reaches it’s target point, you will want a damping ratio less than 1.0. Check out the Box2D Manual to learn more about these options.

Using ADB with multiple devices

Have you ever had multiple emulators or physical devices or a combination of the two attached at once? It’s frustrating to shut off or unplug your devices in order to single out the one that needs to be targeted. Look no further, adb includes a command line switch to choose the specific device you want to target.

Let’s begin by listing our currently attached devices.

$ adb devices
List of devices attached
emulator-5554 device
emulator-5556 device
HT09PR217646 device

As you can see, we have three devices attached to our system. Two emulators and one physical phone. Now let’s logcat our physical device because it’s running our application that we want to debug. Just pass the -d switch to adb to target our device.

$ adb -d logcat

If we had a single emulator instance and one or more physical devices attached we could pass in the -e switch to adb which targets emulator.

$ adb -e logcat

The final switch we can use for device targeting is the -s switch, which stands for serial number.

$ adb -s emulator-5554 logcat
$ adb -s emulator-5556 logcat
$ adb -s HT09PR217646 logcat

March 2018: Mobile News and Trends

We’ve got some hot news: our buddies at Appcelerator won the GSMA Global Mobile 2012 Best Cloud-Based Tech Award in Barcelona last week at the Mobile World Congress in Barcelona. The judge’s comment on the award announcement: “Quintessential cloud, write once, deploy many times drives speed and cost reductions.”

Titanium is indeed a powerful development platform that allows you to build and deploy mobile apps quickly that will work on any platform. We’re proud of Appcelerator’s win since we can bask in the glow ourselves as Titanium developers and trainers. Our CEO, Edwin Huertas, just picked up a Master Certification in Titanium last month, and on the way back home to Richmond, he stopped by Accenture-Austin to teach mobile development and best practices to their developer team.

So that’s the local mobile news, with a global spin. Here are some other trends we’re watching:

iPad 3 launch

Apple is launching the iPad 3 this week (if they want to take advantage of SXSW crowd hype) or next week. We’ll be watching closely to see what changes are really in the tablet after all the pre-launch speculation is either proven or myth-busted. One big question: will it include LTE? GigaOm’s Kevin Fitchard has a great post on what LTE’s inclusion, or exclusion, would mean for the mobile space. Stay tuned for that answer.

Augmented reality for navigation

Texting while driving is a bad idea. There are, however, a few apps in development that use augmented reality to help drivers navigate traffic by using the camera lens on their smartphone. One, in particular, got a lot of attention at Mobile World Congress last month: iOnRoad, an Android app developed by an Israeli company who envisions the technology being integrated into existing vehicle navigation systems.

Are you looking to build a mobile business?

That’s one trend that will continue to grow for the foreseeable future, as more people across the globe get connected via mobile devices even when terrestrial connections aren’t available. If you need help exploring the idea of making your business, your idea, or your cause mobile, we’ve got expertise and the tech-savvy to make it happen. And the training programs to help you build your own mobile developer team.

Got a trend you’re watching? Let us know!