Created
November 6, 2014 12:57
-
-
Save someguycrafting/e6ec2dfaca44c4511479 to your computer and use it in GitHub Desktop.
Sample implementation of collapsable list view sections in Titanium (Common JS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Sample implementation of collapsable list view sections in Titanium (Common JS) | |
* by Renato Costa (renato (dot) duino (at) gmail (dot) com) | |
*/ | |
var indicatorOpened = '[-]'; | |
var indicatorClosed = '[+]'; | |
var exampleList; | |
//Simple window for demo purposes | |
var window = Titanium.UI.createWindow({ | |
backgroundColor: 'white', | |
fullscreen: true, | |
title : 'Collapsible listview example' | |
}); | |
setupList(); | |
addHeaders(); | |
window.open(); | |
function setupList() { | |
// *** Start by setting up the templates | |
// This will be our fake expandable header | |
var expandableHeaderTemplate = { | |
properties: { | |
accessoryType: Ti.UI.LISTACCESSORYTYPENONE, | |
selectionStyle: Ti.Platform.osname == 'android' ? null : Titanium.UI.iPhone.ListViewCellSelectionStyle.NONE, //setting this will disable listview item from getting selected in iOS | |
height: Ti.UI.SIZE, | |
width: Ti.UI.FILL, | |
isExpanded: false // this is our custom property that will maintain expansion status | |
}, | |
events: { | |
click: headerSelected | |
}, | |
childTemplates: [ | |
{ | |
type: 'Ti.UI.View', | |
properties: { | |
touchEnabled: true, | |
height: Ti.UI.SIZE, | |
width: Ti.UI.FILL, | |
top: '10dp', //Adds some padding between headers | |
layout: 'composite', //Actually this is the default view layout, I'm just putting this for example purposes, | |
backgroundColor: '#f9f9f9' | |
}, | |
childTemplates: [ | |
//Header title | |
{ | |
type: 'Ti.UI.Label', | |
bindId: 'title', | |
properties: { | |
touchEnabled: false, | |
color: '#000000', | |
font: {fontSize: '16sp'}, | |
height: Ti.UI.SIZE, | |
width: Ti.UI.SIZE, | |
top: '10dp', | |
bottom: '10dp', | |
left: '10dp', | |
right: '30dp' //Add some padding to the right so we don't overlap with our expanded indicator | |
} | |
}, | |
//Expand indicator | |
{ | |
type: 'Ti.UI.Label', | |
bindId: 'expand', | |
properties: { | |
touchEnabled: false, | |
font: {fontSize: '16sp', fontWeight: 'bold'}, | |
color: '#0099cc', | |
text : indicatorClosed, | |
height: Ti.UI.SIZE, | |
width: Ti.UI.SIZE, | |
right: '10dp' | |
} | |
} | |
] | |
} | |
] | |
}; | |
// This will be fake child template (a simple image in this example) | |
var imageTemplate = { | |
properties: { | |
accessoryType: Ti.UI.LISTACCESSORYTYPENONE, | |
height: 64, | |
width: 64, | |
}, | |
events: { | |
click: function () { | |
alert('Hey, you just clicked me!'); | |
} | |
}, | |
childTemplates: [ | |
{ | |
type: 'Ti.UI.ImageView', | |
bindId: 'icon', | |
properties: { | |
width: Ti.UI.Size, | |
height: Ti.UI.Size, | |
hires: true //Setting this in iOS disable retina scaling for remote images | |
} | |
} | |
] | |
}; | |
//Setup our list | |
exampleList = Ti.UI.createListView({ | |
top: Ti.Platform.osname == 'android' ? 0 : 20, //iOS specific padding | |
width: Ti.UI.FILL, | |
height: Ti.UI.FILL, | |
separatorColor: 'transparent', | |
touchEnabled: true, | |
templates: { 'header': expandableHeaderTemplate , 'image': imageTemplate }, //Notice how templates are associated | |
defaultItemTemplate: 'header', //Use header template by default | |
showVerticalScrollIndicator: true | |
}); | |
window.add(exampleList); | |
} | |
function addHeaders() { | |
//Add some fake expandable headers. Each header will correspond to a new ListSection | |
var dummyHeaders = [ | |
{ template: 'header', title: {text: 'Weather icons' }, expand: {text: indicatorClosed }, isExpanded: false }, | |
{ template: 'header', title: {text: 'Document icons' }, expand: {text: indicatorClosed }, isExpanded: false }, | |
]; | |
var sections = []; | |
for(var i=0,j=dummyHeaders.length; i<j; i++){ | |
sections.push(Ti.UI.createListSection({ | |
items: [dummyHeaders[i]], | |
id: i | |
})); | |
}; | |
exampleList.setSections(sections); | |
} | |
function headerSelected(e) { | |
//When our fake header is clicked we'll handle it here | |
var header = e.section.getItemAt(e.itemIndex); | |
var items = e.section.getItems(); | |
//Check if it is expanded - remember our custom property? | |
if (header.isExpanded) { | |
//It's expanded, so we'll 'close' it, remove all header children rows that is | |
// Position 0 of the list section is the header, so we start at position 1 | |
var totDel = items.length - e.itemIndex+1; | |
e.section.deleteItemsAt(e.itemIndex+1, totDel); | |
header.expand.text = indicatorClosed; | |
} | |
else { | |
//It's closed, so we'll expand it, add children rows, that is | |
showSectionItems(e.section); | |
header.expand.text = indicatorOpened; | |
} | |
//Update our header so it reflect the changes | |
header.isExpanded = !header.isExpanded; | |
e.section.updateItemAt(e.itemIndex, header); | |
} | |
function showSectionItems(section) { | |
var dummyIcons; | |
switch (section.id) { | |
case 0: | |
//Show some weather icons | |
dummyIcons = [ | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/440711/weathersunny/128/png' } }, | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/440760/weatherrain/128/png' } }, | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/440715/weathersnow/128/png' } }, | |
]; | |
break; | |
case 1: | |
//Show some document icons | |
dummyIcons = [ | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/71512/filedoc/128/png' } }, | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/71485/filexml/128/png' } }, | |
{ template: 'image', icon: {image: 'http://findicons.com/icon/download/71485/filepdf/128/png' } }, | |
]; | |
break; | |
} | |
section.appendItems(dummyIcons); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment