Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
TICONFEU,AMSTERDAM,29/06/2014
{native: “FTW”}
!
Integrating native views in Titanium apps
Olivier Morandi
TICONFEU,AMSTERDAM,29/06/2014
Olivier Morandi
Software engineer
!
http://titaniumninja.com!
olivier.morandi@gmail.com
@oli...
TICONFEU,AMSTERDAM,29/06/2014 3
TICONFEU,AMSTERDAM,29/06/2014
• Ti app development
• Native module development (iOS/Android)
• Optimisations
• R&D
4
TICONFEU,AMSTERDAM,29/06/2014
This Talk
• How to create view-based native modules
• How to integrate third party libraries...
TICONFEU,AMSTERDAM,29/06/2014
Not in This Talk
• Basics of native module development
★ module creation
★ proxies, methods,...
TICONFEU,AMSTERDAM,29/06/2014
Why Native Views
• UX/Performance
★ Stock Ti UI components not suitable for
the specific UX r...
TICONFEU,AMSTERDAM,29/06/2014
Ti.Next/Hyperloop
• Q: Are Ti.Current native modules still
relevant?
• A: YES!
★ Ti.Next/Hyp...
TICONFEU,AMSTERDAM,29/06/2014
Learning Resources
TICONFEU,AMSTERDAM,29/06/2014
Official Appcelerator Guides
• http://docs.appcelerator.com/titanium/latest/#!/guide/
Extendin...
TICONFEU,AMSTERDAM,29/06/2014 11
TICONFEU,AMSTERDAM,29/06/2014
Source code
• Titanium Mobile SDK
★ https://github.com/appcelerator/
titanium_mobile
• Open ...
TICONFEU,AMSTERDAM,29/06/2014
Follow these people (and more)
• Aaron K. Saunders: https://github.com/aaronksaunders
• Adam...
TICONFEU,AMSTERDAM,29/06/2014
Architecture Recap
TICONFEU,AMSTERDAM,29/06/2014 15
Titanium cli (node.js)
TICONFEU,AMSTERDAM,29/06/2014
Runtime (iOS)
16
Titanium
Modules
(API)
JS APP
Parser
Interpreter
IOS SDK
Bytecode
gen
JavaS...
TICONFEU,AMSTERDAM,29/06/2014
Runtime (iOS)
16
Titanium
Modules
(API)
JS APP
Parser
Interpreter
IOS SDK
Bytecode
gen
JavaS...
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Run...
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Run...
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Run...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
var win1 = Titanium.UI.createWindow({
title:'Hello World',
backgroundColor:'w...
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Typ...
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Typ...
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Typ...
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Typ...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds ...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds ...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds ...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds ...
TICONFEU,AMSTERDAM,29/06/2014
A Basic Native View
TICONFEU,AMSTERDAM,29/06/2014 22
TICONFEU,AMSTERDAM,29/06/2014
Usage Scenario
23
var win = Ti.UI.createWindow({
backgroundColor: 'white'
});
!
var ticonf =...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy Class
24
#import "TiViewProxy.h"
!
@interface TiConfBasicViewProxy : TiViewProxy
@...
TICONFEU,AMSTERDAM,29/06/2014
View Class
25
#import "TiUIView.h"
!
@interface TiConfBasicView : TiUIView
{
UIView *theView...
TICONFEU,AMSTERDAM,29/06/2014 26
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: where’s my view?
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: where’s my view?
TiConfBasicView
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: where’s my view?
TiConfBasicView
theView
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementatio...
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementatio...
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementatio...
TICONFEU,AMSTERDAM,29/06/2014
An alternative
28
TiConfBasicView.m
-(void)initializeState
{
theView = [[UIView alloc] initW...
TICONFEU,AMSTERDAM,29/06/2014
An alternative
28
TiConfBasicView.m
-(void)initializeState
{
theView = [[UIView alloc] initW...
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy Class
29
@Kroll.proxy(creatableInModule=AndroidModule.class)
public class BasicVie...
TICONFEU,AMSTERDAM,29/06/2014
View Class
30
public class BasicView extends TiUIView
{
View theView;
public BasicView(TiVie...
TICONFEU,AMSTERDAM,29/06/2014 31
TICONFEU,AMSTERDAM,29/06/2014
Properties
• Properties belong to the ViewProxy object
• How do we make use of property valu...
TICONFEU,AMSTERDAM,29/06/2014
Setting a property
33
var basicView = ticonf.createBasicView({
color: "red"
});
!
//or
!
bas...
TICONFEU,AMSTERDAM,29/06/2014
Property from the Proxy
34
!
UIColor *color = [[TiUtils colorValue:[self.proxy valueForKey:@...
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColo...
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColo...
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColo...
TICONFEU,AMSTERDAM,29/06/2014
Implicit Setter in the View Class
36
-(void)setColor_:(id)arg
{
theView.backgroundColor = [[...
TICONFEU,AMSTERDAM,29/06/2014
Implicit Setter in the View Class
36
-(void)setColor_:(id)arg
{
theView.backgroundColor = [[...
TICONFEU,AMSTERDAM,29/06/2014
Property from the Proxy
37
!
int color = TiConvert.toColor((String) proxy.getProperty(“color...
TICONFEU,AMSTERDAM,29/06/2014
Creation Properties
38
BasicView.java
@Override
public void processProperties(KrollDict prop...
TICONFEU,AMSTERDAM,29/06/2014
Property Changed Listener
39
BasicView.java
@Override
public void propertyChanged(String key...
TICONFEU,AMSTERDAM,29/06/2014
Methods
• Exposed to JS by the ViewProxy object
• Dispatched to the View object
40
TICONFEU,AMSTERDAM,29/06/2014
View Methods
41
basicView.makeRounded();
TICONFEU,AMSTERDAM,29/06/2014 42
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(v...
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(v...
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(v...
TICONFEU,AMSTERDAM,29/06/2014
Dispatching via GCD
44
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicVi...
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new Gradient...
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new Gradient...
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new Gradient...
TICONFEU,AMSTERDAM,29/06/2014
Message Dispatching
46
private static final int MSG_MAKE_ROUNDED = TiViewProxy.MSG_LAST_ID +...
TICONFEU,AMSTERDAM,29/06/2014
View Events
47
basicView.addEventListener('viewTapped', function() {
alert('tapped');
});
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
48
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bound...
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
48
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bound...
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
49
public BasicView(final TiViewProxy proxy) {
super(proxy);
!
Activity contex...
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
49
public BasicView(final TiViewProxy proxy) {
super(proxy);
!
Activity contex...
TICONFEU,AMSTERDAM,29/06/2014
Integrating Third
Party Libraries
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
• Static library file (.a)
• Objective-c/C/C++ headers folder
51
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
static lib file (.a)
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
static lib file (.a)
ensure the lib is linked...
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
• Framework bundle
★ Header files
★ Library
★ Resources
53
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application S...
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application S...
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application S...
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
55
!
OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK>...
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
55
!
OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK>...
TICONFEU,AMSTERDAM,29/06/2014
ARC vs. NON-ARC
• ARC = Automatic Reference Counting
★ Retain/Release handled automatically ...
TICONFEU,AMSTERDAM,29/06/2014
Enabling ARC for a specific file
57
TICONFEU,AMSTERDAM,29/06/2014
Using external JARs
58
drag & drop the JAR in the
lib folder of the module
project
TICONFEU,AMSTERDAM,29/06/2014
Using external JARs
59
Add the external JAR
to the project build
path
TICONFEU,AMSTERDAM,29/06/2014
Integrating native libs (NDK)
60
Import the native shared
libraries (.so), separated
by targ...
TICONFEU,AMSTERDAM,29/06/2014
Fix build.xml
61
<project name="android" default="dist">	
	 <description>	
	 	 Ant build scr...
TICONFEU,AMSTERDAM,29/06/2014
Fix build.xml
61
<project name="android" default="dist">	
	 <description>	
	 	 Ant build scr...
TICONFEU,AMSTERDAM,29/06/2014
Questions?
Upcoming SlideShare
Loading in …5
×

Native FTW: Integrating native views in Titanium apps

3,780 views

Published on

Published in: Mobile, Technology, Travel
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Native FTW: Integrating native views in Titanium apps

  1. 1. TICONFEU,AMSTERDAM,29/06/2014 {native: “FTW”} ! Integrating native views in Titanium apps Olivier Morandi
  2. 2. TICONFEU,AMSTERDAM,29/06/2014 Olivier Morandi Software engineer ! http://titaniumninja.com! olivier.morandi@gmail.com @olivier_morandi https://github.com/omorandi 2
  3. 3. TICONFEU,AMSTERDAM,29/06/2014 3
  4. 4. TICONFEU,AMSTERDAM,29/06/2014 • Ti app development • Native module development (iOS/Android) • Optimisations • R&D 4
  5. 5. TICONFEU,AMSTERDAM,29/06/2014 This Talk • How to create view-based native modules • How to integrate third party libraries 5
  6. 6. TICONFEU,AMSTERDAM,29/06/2014 Not in This Talk • Basics of native module development ★ module creation ★ proxies, methods, properties, events, callbacks • Check out http://www.slideshare.net/ omorandi/ticonf 6
  7. 7. TICONFEU,AMSTERDAM,29/06/2014 Why Native Views • UX/Performance ★ Stock Ti UI components not suitable for the specific UX requirements • Integration of native UI components and libraries ★ Leverage existing solutions from the Android and iOS OSS communities ★ Integrate third party SDKs 7
  8. 8. TICONFEU,AMSTERDAM,29/06/2014 Ti.Next/Hyperloop • Q: Are Ti.Current native modules still relevant? • A: YES! ★ Ti.Next/Hyperloop is WIP ★ Active need in current Titanium projects ★ Maintaining legacy modules 8
  9. 9. TICONFEU,AMSTERDAM,29/06/2014 Learning Resources
  10. 10. TICONFEU,AMSTERDAM,29/06/2014 Official Appcelerator Guides • http://docs.appcelerator.com/titanium/latest/#!/guide/ Extending_Titanium_Mobile • http://docs.appcelerator.com/titanium/latest/#!/guide/ iOS_Module_Development_Guide • http://docs.appcelerator.com/titanium/latest/#!/guide/ Android_Module_Development_Guide 10
  11. 11. TICONFEU,AMSTERDAM,29/06/2014 11
  12. 12. TICONFEU,AMSTERDAM,29/06/2014 Source code • Titanium Mobile SDK ★ https://github.com/appcelerator/ titanium_mobile • Open source modules from Appcelerator ★ https://github.com/appcelerator/ titanium_modules 12
  13. 13. TICONFEU,AMSTERDAM,29/06/2014 Follow these people (and more) • Aaron K. Saunders: https://github.com/aaronksaunders • Adam Paxton: https://github.com/adampax/ • Ben Bahrenburg: https://github.com/benbahrenburg • David Bankier: https://github.com/dbankier • Jordi Domenec: https://github.com/iamyellow • Mads Møller: https://github.com/viezel • Marcel Pociot: https://github.com/mpociot • Matt Apperson: https://github.com/mattapperson • Paul Mietz Egli: https://github.com/pegli • Ruben Fonseca: https://github.com/rubenfonseca • Many more… find them on http://gitt.io/ 13
  14. 14. TICONFEU,AMSTERDAM,29/06/2014 Architecture Recap
  15. 15. TICONFEU,AMSTERDAM,29/06/2014 15 Titanium cli (node.js)
  16. 16. TICONFEU,AMSTERDAM,29/06/2014 Runtime (iOS) 16 Titanium Modules (API) JS APP Parser Interpreter IOS SDK Bytecode gen JavaScriptCore objective-c C++ KROLLBRIDGE
  17. 17. TICONFEU,AMSTERDAM,29/06/2014 Runtime (iOS) 16 Titanium Modules (API) JS APP Parser Interpreter IOS SDK Bytecode gen JavaScriptCore NO JIT objective-c C++ KROLLBRIDGE
  18. 18. TICONFEU,AMSTERDAM,29/06/2014 Titanium Modules (API) JS APP Parser Native Code Android SDK Native Code gen KROLLBRIDGE Runtime (Android) 17 Java C++ V8 OPT
  19. 19. TICONFEU,AMSTERDAM,29/06/2014 Titanium Modules (API) JS APP Parser Native Code Android SDK Native Code gen KROLLBRIDGE Runtime (Android) 17 Java C++ V8 OPT
  20. 20. TICONFEU,AMSTERDAM,29/06/2014 Titanium Modules (API) JS APP Parser Native Code Android SDK Native Code gen KROLLBRIDGE Runtime (Android) 17 Java C++ V8 OPT
  21. 21. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open();
  22. 22. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); module object
  23. 23. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); factory method
  24. 24. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); creation properties
  25. 25. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); proxy object
  26. 26. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); view proxy object
  27. 27. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); proxy property
  28. 28. TICONFEU,AMSTERDAM,29/06/2014 Terminology 18 var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white' }); ! var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100 }); ! label1.text = 'howdy?'; win1.add(label1); ! win1.open(); proxy method
  29. 29. TICONFEU,AMSTERDAM,29/06/2014 Proxies & Modules Proxy ViewProxy ViewModule extends has a creates 19 manages NativeView Type iOS UIView AndroidView extends
  30. 30. TICONFEU,AMSTERDAM,29/06/2014 Proxies & Modules Proxy ViewProxy ViewModule extends has a creates 19 manages NativeView Type iOS UIView AndroidView State: properties Actions: methods Events: addEventListener(), fireEvent() Interface extends
  31. 31. TICONFEU,AMSTERDAM,29/06/2014 Proxies & Modules Proxy ViewProxy ViewModule extends has a creates 19 manages NativeView Type iOS UIView AndroidView State: properties Actions: methods Events: addEventListener(), fireEvent() Interface Methods for the integration within the application lifecycle •startup() (iOS) •shutdown() (iOS) •onAppCreate() (Android) extends
  32. 32. TICONFEU,AMSTERDAM,29/06/2014 Proxies & Modules Proxy ViewProxy ViewModule extends has a creates 19 manages NativeView Type iOS UIView AndroidView State: properties Actions: methods Events: addEventListener(), fireEvent() Interface Additional members for the integration within the UI layout system: •add() •remove() •height •width •backgroundColor •... Methods for the integration within the application lifecycle •startup() (iOS) •shutdown() (iOS) •onAppCreate() (Android) extends
  33. 33. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy 20 ViewProxy View NativeViews Hierarchy Methods Properties (get/set) Events Holds the state of a view Manages the native view hierarchy
  34. 34. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy 20 ViewProxy View NativeViews Hierarchy Methods Properties (get/set) Events Holds the state of a view Manages the native view hierarchy JS THREAD
  35. 35. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy 20 ViewProxy View NativeViews Hierarchy Methods Properties (get/set) Events Holds the state of a view Manages the native view hierarchy JS THREAD UI THREAD
  36. 36. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy 20 ViewProxy View NativeViews Hierarchy Methods Properties (get/set) Events Holds the state of a view Manages the native view hierarchy JS THREAD UI THREAD ASYNC
  37. 37. TICONFEU,AMSTERDAM,29/06/2014 A Basic Native View
  38. 38. TICONFEU,AMSTERDAM,29/06/2014 22
  39. 39. TICONFEU,AMSTERDAM,29/06/2014 Usage Scenario 23 var win = Ti.UI.createWindow({ backgroundColor: 'white' }); ! var ticonf = require('ti.conf'); ! var basicView = ticonf.createBasicView({ width: 100, height: 100 }); ! win.add(basicView); ! win.open(); app.js
  40. 40. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy Class 24 #import "TiViewProxy.h" ! @interface TiConfBasicViewProxy : TiViewProxy @end TiConfBasicViewProxy.h TiConfBasicViewProxy.m #import "TiConfBasicViewProxy.h" ! @implementation TiConfBasicViewProxy ! ! @end
  41. 41. TICONFEU,AMSTERDAM,29/06/2014 View Class 25 #import "TiUIView.h" ! @interface TiConfBasicView : TiUIView { UIView *theView; } @end TiConfBasicView.h TiConfBasicView.m #import "TiConfBasicView.h" ! @implementation TiConfBasicView ! -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! @end
  42. 42. TICONFEU,AMSTERDAM,29/06/2014 26
  43. 43. TICONFEU,AMSTERDAM,29/06/2014 26 WTF: where’s my view?
  44. 44. TICONFEU,AMSTERDAM,29/06/2014 26 WTF: where’s my view? TiConfBasicView
  45. 45. TICONFEU,AMSTERDAM,29/06/2014 26 WTF: where’s my view? TiConfBasicView theView
  46. 46. TICONFEU,AMSTERDAM,29/06/2014 Managing the subview frame 27 TiConfBasicView.m #import "TiConfBasicView.h" ! @implementation TiConfBasicView ! ! -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! @end
  47. 47. TICONFEU,AMSTERDAM,29/06/2014 Managing the subview frame 27 TiConfBasicView.m #import "TiConfBasicView.h" ! @implementation TiConfBasicView ! ! -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! @end The Ti View frame is managed by the Ti layout system. Bounds are not valid until the view takes part to an on-screen Ti view hierarchy
  48. 48. TICONFEU,AMSTERDAM,29/06/2014 Managing the subview frame 27 TiConfBasicView.m #import "TiConfBasicView.h" ! @implementation TiConfBasicView ! ! -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! @end The Ti View frame is managed by the Ti layout system. Bounds are not valid until the view takes part to an on-screen Ti view hierarchy
  49. 49. TICONFEU,AMSTERDAM,29/06/2014 An alternative 28 TiConfBasicView.m -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! ! ! -(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds { theView.frame = bounds; }
  50. 50. TICONFEU,AMSTERDAM,29/06/2014 An alternative 28 TiConfBasicView.m -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; theView.backgroundColor = [UIColor redColor]; [self addSubview:theView]; } ! ! ! -(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds { theView.frame = bounds; } called by -[TiUIView drawRect:]
  51. 51. TICONFEU,AMSTERDAM,29/06/2014 ViewProxy Class 29 @Kroll.proxy(creatableInModule=AndroidModule.class) public class BasicViewProxy extends TiViewProxy { // Constructor public BasicViewProxy() { super(); } ! @Override public TiUIView createView(Activity activity) { TiUIView view = new BasicView(this); return view; } ! } BasicViewProxy.java
  52. 52. TICONFEU,AMSTERDAM,29/06/2014 View Class 30 public class BasicView extends TiUIView { View theView; public BasicView(TiViewProxy proxy) { super(proxy); ! Activity context = proxy.getActivity(); theView = new View(context); theView.setBackgroundColor(Color.RED); getLayoutParams().autoFillsHeight = true; getLayoutParams().autoFillsWidth = true; setNativeView(theView); } ! } BasicView.java
  53. 53. TICONFEU,AMSTERDAM,29/06/2014 31
  54. 54. TICONFEU,AMSTERDAM,29/06/2014 Properties • Properties belong to the ViewProxy object • How do we make use of property values in View objects? 32
  55. 55. TICONFEU,AMSTERDAM,29/06/2014 Setting a property 33 var basicView = ticonf.createBasicView({ color: "red" }); ! //or ! basicView.color = "red";
  56. 56. TICONFEU,AMSTERDAM,29/06/2014 Property from the Proxy 34 ! UIColor *color = [[TiUtils colorValue:[self.proxy valueForKey:@"color"]] color]; TiConfBasicView.m Retrieving the property value from the ViewProxy when needed
  57. 57. TICONFEU,AMSTERDAM,29/06/2014 Explicit Setter in the ViewProxy 35 -(void)setColor:(UIColor*)color { theView.backgroundColor = color; } TiConfBasicView.m -(void)setColor:(id)args { //expect 1 argument ENSURE_ARG_COUNT(args, 1); UIColor *color = [[TiUtils colorValue:args] color]; //dispatch to the view on UI thread //(create it if needed, don't wait for completion) [self makeViewPerformSelector:@selector(setColor:) withObject:color createIfNeeded:YES waitUntilDone:NO]; } TiConfBasicViewProxy.m
  58. 58. TICONFEU,AMSTERDAM,29/06/2014 Explicit Setter in the ViewProxy 35 -(void)setColor:(UIColor*)color { theView.backgroundColor = color; } TiConfBasicView.m -(void)setColor:(id)args { //expect 1 argument ENSURE_ARG_COUNT(args, 1); UIColor *color = [[TiUtils colorValue:args] color]; //dispatch to the view on UI thread //(create it if needed, don't wait for completion) [self makeViewPerformSelector:@selector(setColor:) withObject:color createIfNeeded:YES waitUntilDone:NO]; } TiConfBasicViewProxy.m JS THREAD
  59. 59. TICONFEU,AMSTERDAM,29/06/2014 Explicit Setter in the ViewProxy 35 -(void)setColor:(UIColor*)color { theView.backgroundColor = color; } TiConfBasicView.m -(void)setColor:(id)args { //expect 1 argument ENSURE_ARG_COUNT(args, 1); UIColor *color = [[TiUtils colorValue:args] color]; //dispatch to the view on UI thread //(create it if needed, don't wait for completion) [self makeViewPerformSelector:@selector(setColor:) withObject:color createIfNeeded:YES waitUntilDone:NO]; } TiConfBasicViewProxy.m JS THREAD UI THREAD
  60. 60. TICONFEU,AMSTERDAM,29/06/2014 Implicit Setter in the View Class 36 -(void)setColor_:(id)arg { theView.backgroundColor = [[TiUtils colorValue:arg] color]; } TiConfBasicView.m
  61. 61. TICONFEU,AMSTERDAM,29/06/2014 Implicit Setter in the View Class 36 -(void)setColor_:(id)arg { theView.backgroundColor = [[TiUtils colorValue:arg] color]; } TiConfBasicView.m Automatically dispatched by the ViewProxy on the UI thread
  62. 62. TICONFEU,AMSTERDAM,29/06/2014 Property from the Proxy 37 ! int color = TiConvert.toColor((String) proxy.getProperty(“color")); BasicView.java
  63. 63. TICONFEU,AMSTERDAM,29/06/2014 Creation Properties 38 BasicView.java @Override public void processProperties(KrollDict props) { super.processProperties(props); if (props.containsKey("color")) { theView.setBackgroundColor(TiConvert.toColor(props.getString("color"))); } else if (…) { //do something else } }
  64. 64. TICONFEU,AMSTERDAM,29/06/2014 Property Changed Listener 39 BasicView.java @Override public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) { if (key.equals("color")) { theView.setBackgroundColor(TiConvert.toColor((String)newValue)); } else if () { //do something else } } public abstract class TiUIView implements KrollProxyListener titanium_mobile/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java:73
  65. 65. TICONFEU,AMSTERDAM,29/06/2014 Methods • Exposed to JS by the ViewProxy object • Dispatched to the View object 40
  66. 66. TICONFEU,AMSTERDAM,29/06/2014 View Methods 41 basicView.makeRounded();
  67. 67. TICONFEU,AMSTERDAM,29/06/2014 42
  68. 68. TICONFEU,AMSTERDAM,29/06/2014 View Method 43 -(void)makeRounded { theView.layer.cornerRadius = 20; } TiConfBasicView.m -(void)makeRounded:(id)args { ENSURE_UI_THREAD(makeRounded, args); TiConfBasicView *thisView = (TiConfBasicView*)[self view]; [thisView makeRounded]; } TiConfBasicViewProxy.m
  69. 69. TICONFEU,AMSTERDAM,29/06/2014 View Method 43 -(void)makeRounded { theView.layer.cornerRadius = 20; } TiConfBasicView.m -(void)makeRounded:(id)args { ENSURE_UI_THREAD(makeRounded, args); TiConfBasicView *thisView = (TiConfBasicView*)[self view]; [thisView makeRounded]; } TiConfBasicViewProxy.m JS THREAD
  70. 70. TICONFEU,AMSTERDAM,29/06/2014 View Method 43 -(void)makeRounded { theView.layer.cornerRadius = 20; } TiConfBasicView.m -(void)makeRounded:(id)args { ENSURE_UI_THREAD(makeRounded, args); TiConfBasicView *thisView = (TiConfBasicView*)[self view]; [thisView makeRounded]; } TiConfBasicViewProxy.m JS THREAD UI THREAD
  71. 71. TICONFEU,AMSTERDAM,29/06/2014 Dispatching via GCD 44 -(void)makeRounded { theView.layer.cornerRadius = 20; } TiConfBasicView.m -(void)makeRounded:(id)args { dispatch_async(dispatch_get_main_queue(), ^{ TiConfBasicView *thisView = (TiConfBasicView*)[self view]; [thisView makeRounded]; }); } TiConfBasicViewProxy.m
  72. 72. TICONFEU,AMSTERDAM,29/06/2014 View Method Dispatching 45 public void makeRounded() { GradientDrawable shape = new GradientDrawable(); shape.setColor(Color.RED); shape.setCornerRadius(50); theView.setBackgroundDrawable(shape); } BasicView.java @Kroll.method public void makeRounded() { TiMessenger.postOnMain(new Runnable() { ! @Override public void run() { BasicView view = (BasicView)getOrCreateView(); view.makeRounded(); } }); } BasicViewProxy.java
  73. 73. TICONFEU,AMSTERDAM,29/06/2014 View Method Dispatching 45 public void makeRounded() { GradientDrawable shape = new GradientDrawable(); shape.setColor(Color.RED); shape.setCornerRadius(50); theView.setBackgroundDrawable(shape); } BasicView.java @Kroll.method public void makeRounded() { TiMessenger.postOnMain(new Runnable() { ! @Override public void run() { BasicView view = (BasicView)getOrCreateView(); view.makeRounded(); } }); } BasicViewProxy.java JS THREAD
  74. 74. TICONFEU,AMSTERDAM,29/06/2014 View Method Dispatching 45 public void makeRounded() { GradientDrawable shape = new GradientDrawable(); shape.setColor(Color.RED); shape.setCornerRadius(50); theView.setBackgroundDrawable(shape); } BasicView.java @Kroll.method public void makeRounded() { TiMessenger.postOnMain(new Runnable() { ! @Override public void run() { BasicView view = (BasicView)getOrCreateView(); view.makeRounded(); } }); } BasicViewProxy.java JS THREAD UI THREAD
  75. 75. TICONFEU,AMSTERDAM,29/06/2014 Message Dispatching 46 private static final int MSG_MAKE_ROUNDED = TiViewProxy.MSG_LAST_ID + 4001; protected static final int MSG_LAST_ID = MSG_MAKE_ROUNDED; ! private void handleMakeRounded() { BasicView view = (BasicView)getOrCreateView(); view.makeRounded(); } @Override public boolean handleMessage(Message msg){ if (msg.what == MSG_MAKE_ROUNDED) { handleMakeRounded(); return true; } return super.handleMessage(msg); } @Kroll.method public void makeRounded() { if (TiApplication.isUIThread()) { handleMakeRounded(); } else { TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_MAKE_ROUNDED)); } } BasicViewProxy.java
  76. 76. TICONFEU,AMSTERDAM,29/06/2014 View Events 47 basicView.addEventListener('viewTapped', function() { alert('tapped'); });
  77. 77. TICONFEU,AMSTERDAM,29/06/2014 Firing Events 48 -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; // other initialisation operations ! UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(basicViewTapped:)]; // Specify that the gesture must be a single tap tapRecognizer.numberOfTapsRequired = 1; // Add the tap gesture recognizer to the view [theView addGestureRecognizer:tapRecognizer]; } ! - (void)basicViewTapped:(UITapGestureRecognizer *)recognizer { NSDictionary *event = @{@"color": @"red"}; [self.proxy fireEvent:@"viewTapped" withObject:event]; } TiConfBasicView.m
  78. 78. TICONFEU,AMSTERDAM,29/06/2014 Firing Events 48 -(void)initializeState { theView = [[UIView alloc] initWithFrame:self.bounds]; // other initialisation operations ! UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(basicViewTapped:)]; // Specify that the gesture must be a single tap tapRecognizer.numberOfTapsRequired = 1; // Add the tap gesture recognizer to the view [theView addGestureRecognizer:tapRecognizer]; } ! - (void)basicViewTapped:(UITapGestureRecognizer *)recognizer { NSDictionary *event = @{@"color": @"red"}; [self.proxy fireEvent:@"viewTapped" withObject:event]; } TiConfBasicView.m
  79. 79. TICONFEU,AMSTERDAM,29/06/2014 Firing Events 49 public BasicView(final TiViewProxy proxy) { super(proxy); ! Activity context = proxy.getActivity(); theView = new View(context); ! //other initialisation operations View.OnTouchListener gestureListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent e) { KrollDict event = new KrollDict(); event.put("color", "red"); proxy.fireEvent("viewTapped", event); return true; } }; theView.setOnTouchListener(gestureListener); ! setNativeView(theView); } BasicView.java
  80. 80. TICONFEU,AMSTERDAM,29/06/2014 Firing Events 49 public BasicView(final TiViewProxy proxy) { super(proxy); ! Activity context = proxy.getActivity(); theView = new View(context); ! //other initialisation operations View.OnTouchListener gestureListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent e) { KrollDict event = new KrollDict(); event.put("color", "red"); proxy.fireEvent("viewTapped", event); return true; } }; theView.setOnTouchListener(gestureListener); ! setNativeView(theView); } BasicView.java
  81. 81. TICONFEU,AMSTERDAM,29/06/2014 Integrating Third Party Libraries
  82. 82. TICONFEU,AMSTERDAM,29/06/2014 iOS Static Library • Static library file (.a) • Objective-c/C/C++ headers folder 51
  83. 83. TICONFEU,AMSTERDAM,29/06/2014 iOS Static Library 52
  84. 84. TICONFEU,AMSTERDAM,29/06/2014 iOS Static Library 52 includes (headers) folder
  85. 85. TICONFEU,AMSTERDAM,29/06/2014 iOS Static Library 52 includes (headers) folder static lib file (.a)
  86. 86. TICONFEU,AMSTERDAM,29/06/2014 iOS Static Library 52 includes (headers) folder static lib file (.a) ensure the lib is linked with the module
  87. 87. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks • Framework bundle ★ Header files ★ Library ★ Resources 53
  88. 88. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks 54 TITANIUM_SDK_VERSION = 3.2.3.GA ! ! TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS titanium.xcconfig
  89. 89. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks 54 TITANIUM_SDK_VERSION = 3.2.3.GA ! ! TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS titanium.xcconfig
  90. 90. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks 54 TITANIUM_SDK_VERSION = 3.2.3.GA ! ! TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS titanium.xcconfig Used ad module build time
  91. 91. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks 55 ! OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK> ! For example: ! OTHER_LDFLAGS=$(inherited) -framework ArcGIS -F $HOME/Library/SDKs/ArcGIS/iOS/ module.xcconfig
  92. 92. TICONFEU,AMSTERDAM,29/06/2014 iOS Frameworks 55 ! OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK> ! For example: ! OTHER_LDFLAGS=$(inherited) -framework ArcGIS -F $HOME/Library/SDKs/ArcGIS/iOS/ module.xcconfig Used ad application build time
  93. 93. TICONFEU,AMSTERDAM,29/06/2014 ARC vs. NON-ARC • ARC = Automatic Reference Counting ★ Retain/Release handled automatically by the Clang compiler • Ti module template project is still NON- ARC • You can use ARC code inside of a Ti module project 56
  94. 94. TICONFEU,AMSTERDAM,29/06/2014 Enabling ARC for a specific file 57
  95. 95. TICONFEU,AMSTERDAM,29/06/2014 Using external JARs 58 drag & drop the JAR in the lib folder of the module project
  96. 96. TICONFEU,AMSTERDAM,29/06/2014 Using external JARs 59 Add the external JAR to the project build path
  97. 97. TICONFEU,AMSTERDAM,29/06/2014 Integrating native libs (NDK) 60 Import the native shared libraries (.so), separated by target architecture in the lib folder
  98. 98. TICONFEU,AMSTERDAM,29/06/2014 Fix build.xml 61 <project name="android" default="dist"> <description> Ant build script for Titanium Android module android </description> ! <property name="ti.module.root" location="${basedir}"/> <property file="build.properties" /> ! <import file="${titanium.platform}/../module/android/build.xml"/> <target name="post.jar"> <copy todir="${libs}"> <fileset dir="lib"> <include name="**/*.so"/> </fileset> </copy> </target> </project> build.xml Copy the .so files from lib to libs before packaging Paul Mietz Egli: http://developer.appcelerator.com/question/121573/how-do-i-use-so-library-in-module#answer-228134
  99. 99. TICONFEU,AMSTERDAM,29/06/2014 Fix build.xml 61 <project name="android" default="dist"> <description> Ant build script for Titanium Android module android </description> ! <property name="ti.module.root" location="${basedir}"/> <property file="build.properties" /> ! <import file="${titanium.platform}/../module/android/build.xml"/> <target name="post.jar"> <copy todir="${libs}"> <fileset dir="lib"> <include name="**/*.so"/> </fileset> </copy> </target> </project> build.xml Copy the .so files from lib to libs before packaging Paul Mietz Egli: http://developer.appcelerator.com/question/121573/how-do-i-use-so-library-in-module#answer-228134
  100. 100. TICONFEU,AMSTERDAM,29/06/2014 Questions?

×