Skip to content

Instantly share code, notes, and snippets.

@hansemannn
Created May 28, 2019 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hansemannn/20297e983e2b8c898975b600e7ab8418 to your computer and use it in GitHub Desktop.
Save hansemannn/20297e983e2b8c898975b600e7ab8418 to your computer and use it in GitHub Desktop.
A cross platform modal loading indicator to use in Appcelerator Titanium
import TiAnimation from 'ti.animation';
/**
* A loader class to show a modal loading indicator
* above the current context (even above modal).
*
* Author: Hans Knöchel
*
*/
export default class Loader {
/**
* The constructor of the loading indicator. It
* configures the native API's based on the platform.
* @param {Object} options The options passed to the loader.
* @param {String} options.view The view to show on the loader (optional).
* @param {String} options.title The title to show on the loader (optional).
*/
constructor(options = {}) {
this.view = !this.isAndroid ? Ti.UI.createWindow() : undefined;
this.title = options.title || L('loading_progress');
this.viewBased = options.view !== undefined && options.view != null;
if (options.view) {
this.view = options.view;
}
if (this.isAndroid) {
this.activityIndicator = Ti.UI.Android.createProgressIndicator({
message: this.title,
location: Ti.UI.Android.PROGRESS_INDICATOR_DIALOG,
type: Ti.UI.Android.PROGRESS_INDICATOR_INDETERMINANT,
cancelable: false
});
} else {
this.activityIndicator = TiAnimation.createAnimationView({
file: '/animations/spinner.json',
loop: true,
autoStart: true,
top: 28,
width: 65,
height: 65
});
this.containerView = Ti.UI.createView({ backgroundColor: '#55000000', visible: false });
const indicatorView = Ti.UI.iOS.createBlurView({
effect: Ti.UI.iOS.BLUR_EFFECT_STYLE_LIGHT,
width: 200,
height: 150,
borderRadius: 20
});
const label = Ti.UI.createLabel({
text: this.title,
top: 100,
width: 160,
textAlign: 'center',
height: Ti.UI.SIZE,
font: {
fontFamily: Alloy.CFG.fonts.sourceSansPro.semibold,
fontSize: 15
},
color: '#000'
});
indicatorView.add(this.activityIndicator);
indicatorView.add(label);
this.containerView.add(indicatorView);
this.view.add(this.containerView);
}
}
/**
* A utility getter to determine if we are on Android or not.
*
* @return {Boolean} Whether or not the current process runs on Android or not.
*/
get isAndroid() {
return Ti.Platform.osname === 'android';
}
/**
* Shows the loader. On iOS, it uses a animation to fade in
* the parent view before showing the actual loader.
*/
show() {
return new Promise((resolve, _reject) => {
if (!this.isAndroid) {
if (this.viewBased) {
this.view.add(this.containerView);
resolve();
} else {
this.showResolveCallback = resolve;
this.view.navBarHidden = true;
this.navigationWindow = Ti.UI.createNavigationWindow({
window: this.view
});
this.view.addEventListener('open', () => { this._handleOpen(); });
this.view.addEventListener('close', () => { this._handleClose(); });
// Using this navigation window config, we can even show loaders above modal windows
this.navigationWindow.open({
modal: true,
modalStyle: Ti.UI.iOS.MODAL_PRESENTATION_OVER_CURRENT_FULL_SCREEN,
modalTransitionStyle: Ti.UI.iOS.MODAL_TRANSITION_STYLE_CROSS_DISSOLVE,
animated: false
});
}
this.containerView.visible = true;
} else {
this.activityIndicator.show();
resolve();
}
});
}
/**
* Hides the loader. On iOS, it uses a animation to fade out
* the parent view before hiding the actual loader.
*/
hide() {
return new Promise((resolve, _reject) => {
if (!this.isAndroid) {
if (this.viewBased) {
this.view.remove(this.containerView);
resolve();
} else {
this.hideResolveCallback = resolve;
setTimeout(() => {
this.navigationWindow.close({ animated: false });
}, 500);
}
} else {
this.activityIndicator.hide();
resolve();
}
});
}
_handleClose() {
if (this.hideResolveCallback) {
this.hideResolveCallback();
this.hideResolveCallback = null;
}
}
_handleOpen() {
if (this.showResolveCallback) {
this.showResolveCallback();
this.showResolveCallback = null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment