Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-19667] iOS9.1: Support for Apple Pencil

GitHub Issuen/a
TypeNew Feature
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2016-02-12T03:27:35.000+0000
Affected Version/sn/a
Fix Version/sRelease 5.2.0
ComponentsiOS
Labelsapplepencil, iOS9.1, notable, qe-5.2.0
ReporterChee Kiat Ng
AssigneeAngel Petkov
Created2015-10-05T06:25:47.000+0000
Updated2018-10-10T16:30:04.000+0000

Description

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITouch_Class/index.html#//apple_ref/occ/cl/UITouch iOS 9.1 introduces APIs that help you use coalesced and predictive touches that can be produced by Apple Pencil on supported devices. Specifically, the UITouch class includes: The preciseLocationInView: and precisePreviousLocationInView: methods, which give you the precise location for a touch (when available) The altitudeAngle property and the azimuthAngleInView: and azimuthUnitVectorInView: methods, which help you determine the altitude and azimuth of the stylus The estimatedProperties and updatedProperties properties, which help you prepare to update touches that are estimated For an example of some ways to take advantage of these APIs in your app, see the sample project [TouchCanvas: Using UITouch efficiently and effectively](https://developer.apple.com/library/prerelease/ios/samplecode/TouchCanvas/Introduction/Intro.html#//apple_ref/doc/uid/TP40016561).

Comments

  1. Angel Petkov 2015-11-03

    PR pending: https://github.com/appcelerator/titanium_mobile/pull/7419 Demo code :
       //this sets the background color of the master UIView (when there are no windows/tab groups on it)
       var previousePos = 0;
       var listenerType = "Nothing";
       var win = Titanium.UI.createWindow({
       	backgroundColor : "#FFFFFF"
       });
       
       var bswitchingViews = false;
       
       var tab1 = Ti.UI.createTab({
           window: win,
           title: 'Normal View'
       });
       
       var view = Titanium.UI.createView({
          borderRadius:10,
          backgroundColor:'blue',
          width:Ti.UI.FILL,
          height:Ti.UI.FILL
       });
       
       var label1 = Ti.UI.createLabel({
           text : 'Main Screen',
           accessibilityLabel : 'Label on first Scrollview',
           color : 'white'
       });
       
       var button1 = Ti.UI.createButton({
       	title : 'Listener : '+ listenerType,
       	color : 'White',
       	top 	: -40,
       	left	: 5,
          	width 	: 150,
          	height	: 150
       
       
       });
       
       
       
       
       var forceButton = Ti.UI.createButton({
       	title : 'Enable/Dissable',
       	color : 'White',
       	top 	: -40,
       	right	: 10,
          	width 	: 180,
          	height	: 150
       
       
       });
       
       forceButton.addEventListener("singletap",function (e) { 
       	bswitchingViews = !bswitchingViews; 
       	label2.text = 'Enables/Dissables switching between views with force touch. Current status =' + bswitchingViews;
       });
       
       var label2 = Ti.UI.createLabel({
           text : 'Enables/Disables switching between views with force touch. Current status =' + bswitchingViews,
           accessibilityLabel : 'Label on first Scrollview',
           color 	: 'white',
           top 	: 10,
       	right	: 5,
       	font: { fontSize:12 },
          	width 	: 150,
          	height	: 150
       });
       
       
       
       button1.addEventListener("touchend", function(e) {
        	//printNewProperties(e,"Button:touchEnd");
        	switch (listenerType) {
       
         	case "touchmove":
           	listenerType = "touchstart";
           	button1.title = 'Listener : '+ listenerType;
           	break;
         	case "touchstart":
           	listenerType = "touchend";
           	button1.title = 'Listener : '+ listenerType;
           	break;
         	case "touchend":
          		listenerType = "touchmove";
          		button1.title = 'Listener : '+ listenerType;
           	break;
         	default:
           listenerType = "touchmove";
           button1.title = 'Listener : '+ listenerType;
       	}
       });
       
       view.addEventListener("touchmove", function(e) {
       	if (listenerType == "touchmove") { 
       	printNewProperties(e,"View: " + listenerType);
       	}
       });
       
       view.addEventListener("touchstart", function(e) {
       	if (listenerType == "touchstart") {
       	printNewProperties(e,"View: "+listenerType);
       	}
       });
       
       view.addEventListener("touchend", function(e) {
       	if (listenerType == "touchend") {
       	printNewProperties(e,"View: "+listenerType);
       	}
       });
       
       function printNewProperties(e, touchType) {
       	Ti.API.info(touchType+":force "+e.force);
       	var forceString = touchType+":force "+e.force;
       	Ti.API.info(touchType+":maximumPossibleForce "+e.maximumPossibleForce);
       	Ti.API.info(touchType+":altitudeAngle "+ e.altitudeAngle);
       	Ti.API.info(touchType+":time stamp "+ e.timestamp);
       	printToScreen(e);
       }
       
       /*Second Wndow and Second  Tab*/
       var win2 = Titanium.UI.createWindow({
       	backgroundColor : "#FFFFFF"
       });
       
       var tab2 = Ti.UI.createTab({
           window: win2,
           title: 'Table View'
       });
       
       var justStuff = Ti.UI.createTableViewSection({ headerTitle: 'Items' });
       	justStuff.add(Ti.UI.createTableViewRow({ title: 'Arrow' }));
       	justStuff.add(Ti.UI.createTableViewRow({ title: 'Bow'}));
       
       var justStuff2 = Ti.UI.createTableViewSection({ headerTitle: 'More Items' });
       	justStuff2.add(Ti.UI.createTableViewRow({ title: 'Bottle' }));
       	justStuff2.add(Ti.UI.createTableViewRow({ title: 'Apple' }));
       
       var table = Ti.UI.createTableView({
         data: [justStuff,justStuff2]
       });
       
       table.addEventListener("touchmove", function(e) {
       	if (listenerType == "touchmove") { 
       	printNewProperties(e,"Table: " + listenerType);
       	}
       });
       
       table.addEventListener("touchstart", function(e) {
       	if (listenerType == "touchstart") {
       	printNewProperties(e,"Table: "+listenerType);
       	}
       });
       
       table.addEventListener("touchend", function(e) {
       	if (listenerType == "touchend") {
       	printNewProperties(e,"Table: "+listenerType);
       	}
       });
       
       win2.add(table);
       
       var tabGroup = Ti.UI.createTabGroup({
           tabs: [tab1, tab2]
       });
       
       
       
       /*Window 3 and 4 for the longPress and Force Press*/
       var win3 = Titanium.UI.createWindow({
       	backgroundColor : "Green"
       });
       
       var win3View = Titanium.UI.createView({
          borderRadius:10,
          backgroundColor:'Green',
          width:Ti.UI.FILL,
          height:Ti.UI.FILL
       });
       
       var labelWin3 = Titanium.UI.createLabel({
       	text : 'Label for the longPress window',
       });
       
       var win4 = Titanium.UI.createWindow({
       	backgroundColor : "Red"
       });
       
       var win4View = Titanium.UI.createView({
          borderRadius:10,
          backgroundColor:'Red',
          width:Ti.UI.FILL,
          height:Ti.UI.FILL
       });
       
       var labelWin4 = Titanium.UI.createLabel({
       	text : 'Label for Force Touch',
       	color : 'White'
       });
       
       win3View.add(labelWin3);
       win3.add(win3View);
       
       view.addEventListener("longpress", function(e){
       	if (bswitchingViews == true) { 
       		win3.open();
       	}
       	
       });
       
       win4View.add(labelWin4);
       win4.add(win4View);
       
       view.addEventListener("touchmove", function(e){
       	if (e.force > 2 && bswitchingViews == true) { 
       	win4.open();
       	}
       });
       
       //Return to Main Window
       win3View.addEventListener("singletap" , function(e){
       	win3.close();
       });
       
       win4View.addEventListener("singletap" , function(e){
       	win4.close();
       });
       
       /*Console within App*/
       
       var textArea = Ti.UI.createTextArea({
         borderWidth		: 2,
         borderColor		: '#bbb',
         borderRadius 		: 5,
         color 			: 'Red',
         font      		: {fontSize:10},
         editable  		: false,
         textAlign			: 'left',
         bottom 			: 0,
         height 			: 100,
         width 			: Ti.UI.FILL,
         opacity			: 0.5
       });
       
       function printToScreen(values) { 
       	if (values.y >  previousePos.y + 10 || values.y <  previousePos.y -10
       		||values.x >  previousePos.x + 10 || values.x <  previousePos.x -10) {
       
       		textArea.value = textArea.value + "force: " + values.force +"\n";
       		previousePos = values;
       	}
           if (previousePos == 0) { 
           	previousePos = values;
           }
       	
       }
       view.add(button1);
       view.add(label1);
       view.add(label2);
       view.add(forceButton);
       view.add(textArea);
       win.add(view);
       tabGroup.open();
       
  2. Hans Knöchel 2015-11-11

    PR approved!
  3. Josh Longton 2016-02-11

    When using the demo code on the iPad Pro, all touches including the pencil have an undefined force. Tested on: 
iPad Pro (9.1) 
Mac OSX El Capitan 10.11.2
 Studio: 4.5.0.201602111338
 Ti SDK: 5.2.0.v20160210114026 Appc NPM: 4.2.3-2
 App CLI: 5.2.0-255 
Xcode 7.2
 Node v4.2.4 Reopening issue.
  4. Angel Petkov 2016-02-12

    PR(Master): https://github.com/appcelerator/titanium_mobile/pull/7712 PR(5_2_X): https://github.com/appcelerator/titanium_mobile/pull/7711
  5. Chee Kiat Ng 2016-02-12

    PRs merged!
  6. Fokke Zandbergen 2016-02-16

    The PR seems to only implement part of the [attributes](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITouch_Class/index.html#//apple_ref/doc/uid/TP40006785-CH3-SW13) The [source](https://github.com/AngelkPetkov/titanium_mobile/blob/3d2c5daa39ef146e808cb48e68d1aabc804f0327/iphone/Classes/TiUtils.m#L1148-L1170) has force, maximumPossibleForce, timestamp and altitudeAngel, but not azimuthAngleInView, azimuthUnitVectorInView, preciseLocationInView and precisePreviousLocationInView I'm asking because [~bimmel] did mention these missing ones in the release notes: https://wiki.appcelerator.org/display/~bimmel/Titanium+SDK+5.2.0+Beta+Release+Note#TitaniumSDK5.2.0BetaReleaseNote-NewiOS9.1Features [~apetkov] given short time, maybe create a ticket for the missing ones?
  7. Angel Petkov 2016-02-16

  8. (deactived) Brian Immel 2016-02-16

    That line has been updated to the following: "Full coverage for Apple Pencil APIs including force, maximumPossibleForce, timestamp and altitudeAngle." and a note (to myself) added that these features will be documented in 5.2.1 per a conversation with Angel this morning.
  9. Wilson Luu 2016-02-19

    Closing ticket as fixed. Verified that the following events/properties can be triggered on the iPad Pro with the pencil: * touchmove * touchstart * touchend * force * maximumPossibleForce * altitudeAngle Tested on: Appcelerator Studio, build: 4.5.0.201602170821 Appc CLI NPM: 4.2.3-2 Appc CLI Core: 5.2.0-269 Arrow: 1.7.27 SDK: 5.2.0.v20160218123934 Node: v4.2.4 OS: El Capitan (10.11.3) Xcode: 7.2 Device: ipad pro (9.2.1) with pencil

JSON Source