Question

I am writing an application that will run on Android and iOS tablets, supporting multiple screen sizes on both platforms, and both landscape and portrait orientations.

The application uses a ListView, and I would like to make changes to the content in the ListView row depending on the tablet orientation.

Using landscape orientation, the ListView row should include text and graphics next to each other. Portrait orientation, the graphics should appear below the text.

I was able to pull this off on iOS by creating two views that contain different ListViews, showing the appropriate view based on the orientation. Unfortunately, I'm not able to duplicate these results on Android. I used a similar view by orientation method in other areas of the app and both platforms supported it, so it appears the ListView is causing the issue.

I've included a small demo app below that mirrors these symptoms (text color green on portrait and red on landscape, no images for simplicity):

var win = Ti.UI.createWindow({backgroundColor: 'white'});

var viewPortrait = Ti.UI.createView({
  top: '20%',
  bottom: '20%',
  left: '10%',
  right: '10%'
});
var templatePortrait = {
  childTemplates: [{ 
    type: 'Ti.UI.Label', 
    bindId: 'info',
    properties: {
     color: 'green',
     left: '5%', width: '200dip', height: '200dip',
     textAlign: 'right'
    },
  }]
};
var listViewPortrait = Ti.UI.createListView({
  templates: { 'templatep': templatePortrait },
  defaultItemTemplate: 'templatep'
});

var viewLandscape = Ti.UI.createView({
  top: '20%',
  bottom: '20%',
  left: '10%',
  right: '10%'
});
var templateLandscape = {
  childTemplates: [{ 
    type: 'Ti.UI.Label', 
    bindId: 'info',
    properties: {
      color: 'red',
      left: '5%', width: '200dip', height: '200dip',
      textAlign: 'right' 
    }
  }]
};
var listViewLandscape = Ti.UI.createListView({
  templates: { 'templatel': templateLandscape },
  defaultItemTemplate: 'templatel'
});

var sections = [];
var section = Ti.UI.createListSection();
var data = [
  { properties:{height: '160dip'}, info: {text: 'Line text number 1'}},
  { properties:{height: '160dip'}, info: {text: 'Line text number 2'}},
  { properties:{height: '160dip'}, info: {text: 'Line text number 3'}},
];
section.setItems(data);
sections.push(section);

listViewPortrait.setSections(sections);
viewPortrait.add(listViewPortrait);

listViewLandscape.setSections(sections);
viewLandscape.add(listViewLandscape);

win.add(viewPortrait);
win.add(viewLandscape);
win.open();

Ti.Gesture.addEventListener('orientationchange', function () { 
  if (Ti.Gesture.isLandscape() === true) {
    viewPortrait.hide();
    viewLandscape.show();
  } else {
    viewPortrait.show();
    viewLandscape.hide();
  }
}); 

On Android, the text color never turns red. When I remark out viewLandscape.show() in the orientationchange listener, the ListView disappears entirely (because viewPortrait.hide(), also proving the listener is running).

I understand the initial view (showing both viewPortrait and viewLandscape) is not ideal, but this is only a test & I would expect that as the orientation changes the orientationchange event listener would clean that up. It appears to work as I would expect on iOS.

I have two questions.

  1. Why doesn't the .show() method work as I would expect on Android with a ListView?

  2. Is there a better way to handle orientation changes overall? I have read the "Reacting to orientation changes" section of Titanium's Orientation documentation, but am unclear on how I could fire an event that would actually change the ListView after the template has already been loaded (apparently templates cannot be changed after a ListView is created, and a setTemplate method does not exist).

Thanks for any help!

Was it helpful?

Solution

I was able to solve the problem by using multiple templates (which is cleaner code anyway).

var listView = Ti.UI.createListView({
  templates: { 
    'templatePortrait': templatePortrait,
    'templateLandscape': templateLandscape
  },
  defaultItemTemplate: 'templatePortrait'
});

.... snip ....

Ti.Gesture.addEventListener('orientationchange', function () { 
    if (Ti.Gesture.isLandscape() === true) {
        // Landscape
        listView.defaultItemTemplate = 'templateLandscape';
    } else {
        // Portrait
        listView.defaultItemTemplate = 'templatePortrait';
    }
}); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top