Skip to content

Instantly share code, notes, and snippets.

@joshleitzel
Created August 19, 2012 21:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joshleitzel/3397853 to your computer and use it in GitHub Desktop.
Save joshleitzel/3397853 to your computer and use it in GitHub Desktop.
Pull to Refresh on a TableView with Appcelerator Titanium
# (This is CoffeeScript. The compiled JavaScript is below.)
# Pull to Refresh in a TableView on Appcelerator Titanium
# Create an instance of the PullToRefresh class and set it as the table's pullView
# This class is based on code from http://developer.appcelerator.com/blog/2010/05/how-to-create-a-tweetie-like-pull-to-refresh-table.html
# Appcelerator Titanium SDK version 2.1.0.GA, tested only with iOS
class PullToRefresh
constructor: ->
@render()
lastUpdatedText: ->
now = new Date()
nowString = "#{now.getMonth()}/#{now.getDate()} "
hours = now.getHours()
minutes = now.getMinutes()
minutes = if minutes < 10 then "0#{minutes}" else minutes
nowString +=
if hours is 12 then "12:#{minutes} PM"
else if hours > 12 then "#{hours - 12}:#{minutes} PM"
else "#{hours}:#{minutes} AM"
String.format(L('last_updated'), nowString)
render: ->
view = Ti.UI.createView
width: 320
height: 60
@statusLabel = Ti.UI.createLabel
text: L 'pull_to_refresh'
left: 55
width: 200
bottom: 30
height: 'auto'
color: '#1D3819'
textAlign:'center'
font:
fontSize: 13
fontWeight: 'bold'
shadowColor: '#A1A1A1'
shadowOffset:
x: 0
y: 1
@lastUpdatedLabel = Ti.UI.createLabel
text: @lastUpdatedText()
left: 55
width: 200
bottom: 15
height: 'auto'
color: '#1D3819'
textAlign: 'center'
font:
fontSize: 12
shadowColor: '#A1A1A1'
shadowOffset:
x: 0
y: 1
@arrow = Ti.UI.createView
backgroundImage: 'images/arrow.png'
width: 12
bottom: 15
height: 30
left: 35
@loading = Ti.UI.createActivityIndicator
width: 30
bottom: 15
height: 30
left: 26
view.add @statusLabel
view.add @lastUpdatedLabel
view.add @loading
view.add @arrow
@view = view
setPulling: ->
unless @pulling or @refreshing
@pulling = true
t = Ti.UI.create2DMatrix().rotate(-180)
@arrow.animate(transform: t, duration: 180)
@statusLabel.text = L 'release_to_refresh'
setNotPulling: ->
if @pulling and not @refreshing
@pulling = false
t = Ti.UI.create2DMatrix()
@arrow.animate(transform: t, duration: 180)
@statusLabel.text = L 'pull_to_refresh'
startRefreshing: (callback) ->
if @pulling and not @refreshing
@refreshing = true
@startTime = new Date().getTime()
@pulling = false
@arrow.hide()
@loading.show()
@statusLabel.text = L 'refreshing'
@arrow.transform = Ti.UI.create2DMatrix()
callback()
true
else
false
stopRefreshing: ->
if @refreshing
@refreshing = false
# If at least a second hasn't passed, wait, for effect
while (new Date().getTime()) - @startTime < 1000
->
@lastUpdatedLabel.text = @lastUpdatedText()
@statusLabel.text = L 'pull_to_refresh'
@loading.hide()
@arrow.show()
# Example integration of the PtR class with a TableView
pullToRefresh = new PullToRefresh()
tableView = Ti.UI.createTableView(headerPullView: pullToRefresh.view)
tableView.addEventListener 'scroll', (e) =>
offset = e.contentOffset.y
if offset <= -65.0
pullToRefresh.setPulling()
else if offset < 0
pullToRefresh.setNotPulling()
tableView.addEventListener 'dragEnd', (e) =>
if offset <= -65.0
if pullToRefresh.startRefreshing(refreshHandler) # refreshHandler is a function that fetches the new data
tableView.setContentInsets({ top: 60 }, { animated: true })
var PullToRefresh, pullToRefresh, tableView,
_this = this;
PullToRefresh = (function() {
function PullToRefresh() {
this.render();
}
PullToRefresh.prototype.lastUpdatedText = function() {
var hours, minutes, now, nowString;
now = new Date();
nowString = "" + (now.getMonth()) + "/" + (now.getDate()) + " ";
hours = now.getHours();
minutes = now.getMinutes();
minutes = minutes < 10 ? "0" + minutes : minutes;
nowString += hours === 12 ? "12:" + minutes + " PM" : hours > 12 ? "" + (hours - 12) + ":" + minutes + " PM" : "" + hours + ":" + minutes + " AM";
return String.format(L('last_updated'), nowString);
};
PullToRefresh.prototype.render = function() {
var view;
view = Ti.UI.createView({
width: 320,
height: 60
});
this.statusLabel = Ti.UI.createLabel({
text: L('pull_to_refresh'),
left: 55,
width: 200,
bottom: 30,
height: 'auto',
color: '#1D3819',
textAlign: 'center',
font: {
fontSize: 13,
fontWeight: 'bold'
},
shadowColor: '#A1A1A1',
shadowOffset: {
x: 0,
y: 1
}
});
this.lastUpdatedLabel = Ti.UI.createLabel({
text: this.lastUpdatedText(),
left: 55,
width: 200,
bottom: 15,
height: 'auto',
color: '#1D3819',
textAlign: 'center',
font: {
fontSize: 12
},
shadowColor: '#A1A1A1',
shadowOffset: {
x: 0,
y: 1
}
});
this.arrow = Ti.UI.createView({
backgroundImage: 'images/arrow.png',
width: 12,
bottom: 15,
height: 30,
left: 35
});
this.loading = Ti.UI.createActivityIndicator({
width: 30,
bottom: 15,
height: 30,
left: 26
});
view.add(this.statusLabel);
view.add(this.lastUpdatedLabel);
view.add(this.loading);
view.add(this.arrow);
return this.view = view;
};
PullToRefresh.prototype.setPulling = function() {
var t;
if (!(this.pulling || this.refreshing)) {
this.pulling = true;
t = Ti.UI.create2DMatrix().rotate(-180);
this.arrow.animate({
transform: t,
duration: 180
});
return this.statusLabel.text = L('release_to_refresh');
}
};
PullToRefresh.prototype.setNotPulling = function() {
var t;
if (this.pulling && !this.refreshing) {
this.pulling = false;
t = Ti.UI.create2DMatrix();
this.arrow.animate({
transform: t,
duration: 180
});
return this.statusLabel.text = L('pull_to_refresh');
}
};
PullToRefresh.prototype.startRefreshing = function(callback) {
if (this.pulling && !this.refreshing) {
this.refreshing = true;
this.startTime = new Date().getTime();
this.pulling = false;
this.arrow.hide();
this.loading.show();
this.statusLabel.text = L('refreshing');
this.arrow.transform = Ti.UI.create2DMatrix();
callback();
return true;
} else {
return false;
}
};
PullToRefresh.prototype.stopRefreshing = function() {
if (this.refreshing) {
this.refreshing = false;
while ((new Date().getTime()) - this.startTime < 1000) {
(function() {});
}
this.lastUpdatedLabel.text = this.lastUpdatedText();
this.statusLabel.text = L('pull_to_refresh');
this.loading.hide();
return this.arrow.show();
}
};
return PullToRefresh;
})();
pullToRefresh = new PullToRefresh();
tableView = Ti.UI.createTableView({
headerPullView: pullToRefresh.view
});
tableView.addEventListener('scroll', function(e) {
var offset;
offset = e.contentOffset.y;
if (offset <= -65.0) {
return pullToRefresh.setPulling();
} else if (offset < 0) {
return pullToRefresh.setNotPulling();
}
});
tableView.addEventListener('dragEnd', function(e) {
if (offset <= -65.0) {
if (pullToRefresh.startRefreshing(refreshHandler)) { // refreshHandler is a function that fetches the new data
return tableView.setContentInsets({
top: 60
}, {
animated: true
});
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment