@maccesar/titools 5.3.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +1 -1
- package/README.md +31 -60
- package/agents/ti-pro.md +3 -1
- package/commands/ti-audit.md +6 -4
- package/docs/examples.md +9 -0
- package/docs/knowledge-index.md +2 -1
- package/lib/config.js +1 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +18 -179
- package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
- package/skills/alloy-guides/references/CONCEPTS.md +27 -162
- package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
- package/skills/alloy-guides/references/MODELS.md +47 -723
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
- package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
- package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
- package/skills/alloy-guides/references/WIDGETS.md +49 -127
- package/skills/alloy-howtos/SKILL.md +14 -169
- package/skills/alloy-howtos/references/best_practices.md +9 -113
- package/skills/alloy-howtos/references/cli_reference.md +18 -223
- package/skills/alloy-howtos/references/config_files.md +50 -133
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
- package/skills/alloy-howtos/references/samples.md +21 -138
- package/skills/ti-api/SKILL.md +10 -2
- package/skills/ti-api/references/api-android.md +36 -2
- package/skills/ti-api/references/api-app-platform.md +39 -3
- package/skills/ti-api/references/api-core.md +50 -18
- package/skills/ti-api/references/api-data-network.md +49 -35
- package/skills/ti-api/references/api-media.md +45 -27
- package/skills/ti-api/references/api-services.md +39 -9
- package/skills/ti-api/references/api-ui-android.md +33 -13
- package/skills/ti-api/references/api-ui-extras.md +41 -15
- package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
- package/skills/ti-api/references/api-ui-ios.md +74 -2
- package/skills/ti-api/references/api-ui-lists.md +32 -16
- package/skills/ti-api/references/api-ui-text-input.md +34 -17
- package/skills/ti-api/references/api-ui-views.md +27 -1
- package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
- package/skills/ti-api/references/api-xml-global.md +66 -16
- package/skills/ti-create-release/SKILL.md +98 -0
- package/skills/ti-create-release/references/module-discovery.md +69 -0
- package/skills/ti-expert/references/adaptive-layouts.md +1 -1
- package/skills/ti-guides/SKILL.md +37 -76
- package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
- package/skills/ti-guides/references/android-manifest.md +24 -83
- package/skills/ti-guides/references/app-distribution.md +31 -377
- package/skills/ti-guides/references/application-frameworks.md +127 -335
- package/skills/ti-guides/references/cli-reference.md +184 -633
- package/skills/ti-guides/references/commonjs-advanced.md +81 -231
- package/skills/ti-guides/references/compatibility-matrix.md +36 -75
- package/skills/ti-guides/references/hello-world.md +95 -70
- package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
- package/skills/ti-guides/references/resources.md +174 -142
- package/skills/ti-guides/references/sdk-release-notes.md +28 -71
- package/skills/ti-guides/references/tiapp-config.md +222 -598
- package/skills/ti-howtos/SKILL.md +23 -123
- package/skills/ti-howtos/references/cross-platform-development.md +119 -324
- package/skills/ti-howtos/references/debugging-profiling.md +77 -445
- package/skills/ti-howtos/references/extending-titanium.md +199 -673
- package/skills/ti-howtos/references/local-data-sources.md +87 -300
- package/skills/ti-howtos/references/location-and-maps.md +86 -213
- package/skills/ti-howtos/references/media-apis.md +103 -223
- package/skills/ti-howtos/references/notification-services.md +86 -506
- package/skills/ti-howtos/references/remote-data-sources.md +97 -316
- package/skills/ti-howtos/references/using-modules.md +77 -133
- package/skills/ti-ui/SKILL.md +28 -143
- package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
- package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
- package/skills/ti-ui/references/listviews-and-performance.md +100 -703
- package/skills/ti-ui/references/platform-conventions.md +180 -0
- package/skills/ti-ui/references/user-interface.md +43 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
- package/skills/alloy-howtos/references/custom_tags.md +0 -148
- package/skills/ti-guides/references/coding-best-practices.md +0 -149
- package/skills/ti-guides/references/javascript-primer.md +0 -414
- package/skills/ti-guides/references/reserved-words.md +0 -36
- package/skills/ti-guides/references/style-and-conventions.md +0 -103
- package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
- package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
- package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
- package/skills/ti-howtos/references/google-maps-v2.md +0 -172
- package/skills/ti-howtos/references/ios-map-kit.md +0 -149
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
- package/skills/ti-howtos/references/tutorials.md +0 -565
- package/skills/ti-howtos/references/web-content-integration.md +0 -287
- package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
- package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
- package/skills/ti-ui/references/animation-and-matrices.md +0 -569
- package/skills/ti-ui/references/application-structures.md +0 -626
- package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
- package/skills/ti-ui/references/event-handling.md +0 -401
- package/skills/ti-ui/references/gestures.md +0 -448
- package/skills/ti-ui/references/orientation.md +0 -374
- package/skills/ti-ui/references/platform-ui-android.md +0 -727
- package/skills/ti-ui/references/platform-ui-ios.md +0 -576
- package/skills/ti-ui/references/scrolling-views.md +0 -288
- package/skills/ti-ui/references/tableviews.md +0 -542
|
@@ -1,448 +0,0 @@
|
|
|
1
|
-
# Gestures
|
|
2
|
-
|
|
3
|
-
<!-- TOC-START -->
|
|
4
|
-
## Contents
|
|
5
|
-
|
|
6
|
-
- [1. Overview](#1-overview)
|
|
7
|
-
- [2. Touch events](#2-touch-events)
|
|
8
|
-
- [3. Swipe gesture](#3-swipe-gesture)
|
|
9
|
-
- [4. Pinch gesture (iOS only)](#4-pinch-gesture-ios-only)
|
|
10
|
-
- [5. Long press gesture](#5-long-press-gesture)
|
|
11
|
-
- [6. Shake gesture](#6-shake-gesture)
|
|
12
|
-
- [7. Accelerometer as input](#7-accelerometer-as-input)
|
|
13
|
-
- [8. Gesture lifecycle management](#8-gesture-lifecycle-management)
|
|
14
|
-
- [9. Platform-specific considerations](#9-platform-specific-considerations)
|
|
15
|
-
- [10. Best practices](#10-best-practices)
|
|
16
|
-
- [11. Combining gestures](#11-combining-gestures)
|
|
17
|
-
|
|
18
|
-
<!-- TOC-END -->
|
|
19
|
-
|
|
20
|
-
## 1. Overview
|
|
21
|
-
|
|
22
|
-
Titanium supports more than simple taps.
|
|
23
|
-
- Touch events for low-level tracking.
|
|
24
|
-
- Swipe for left and right drags.
|
|
25
|
-
- Pinch for zoom (iOS only).
|
|
26
|
-
- Long press for extended presses.
|
|
27
|
-
- Shake for device shake detection.
|
|
28
|
-
- Accelerometer for device orientation and movement.
|
|
29
|
-
|
|
30
|
-
## 2. Touch events
|
|
31
|
-
|
|
32
|
-
### Touch lifecycle
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
const view = Ti.UI.createView({
|
|
36
|
-
backgroundColor: 'blue',
|
|
37
|
-
width: 200, height: 200
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
view.addEventListener('touchstart', (e) => {
|
|
41
|
-
Ti.API.info(`Touch started at: ${e.x}, ${e.y}`);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
view.addEventListener('touchmove', (e) => {
|
|
45
|
-
Ti.API.info(`Moving to: ${e.x}, ${e.y}`);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
view.addEventListener('touchend', (e) => {
|
|
49
|
-
Ti.API.info(`Touch ended at: ${e.x}, ${e.y}`);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
view.addEventListener('touchcancel', (e) => {
|
|
53
|
-
Ti.API.info('Touch cancelled (incoming call, etc.)');
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Touch event properties
|
|
58
|
-
|
|
59
|
-
| Property | Description |
|
|
60
|
-
| ------------- | ---------------------------------------- |
|
|
61
|
-
| `x` | X coordinate in view's coordinate system |
|
|
62
|
-
| `y` | Y coordinate in view's coordinate system |
|
|
63
|
-
| `globalPoint` | Screen coordinates (iOS only) |
|
|
64
|
-
|
|
65
|
-
### Android note
|
|
66
|
-
|
|
67
|
-
On Android, `longpress` and `swipe` cancel touch events. `touchend` may not fire after `touchstart`.
|
|
68
|
-
|
|
69
|
-
## 3. Swipe gesture
|
|
70
|
-
|
|
71
|
-
### Basic swipe
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
const view = Ti.UI.createView({
|
|
75
|
-
backgroundColor: 'yellow',
|
|
76
|
-
width: Ti.UI.FILL,
|
|
77
|
-
height: 100
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
view.addEventListener('swipe', (e) => {
|
|
81
|
-
Ti.API.info(`Swiped direction: ${e.direction}`);
|
|
82
|
-
// e.direction can be: 'left', 'right', 'up', 'down'
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Swipe direction detection
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
view.addEventListener('swipe', (e) => {
|
|
90
|
-
switch(e.direction) {
|
|
91
|
-
case 'left':
|
|
92
|
-
Ti.API.info('Swiped left');
|
|
93
|
-
showPreviousPage();
|
|
94
|
-
break;
|
|
95
|
-
case 'right':
|
|
96
|
-
Ti.API.info('Swiped right');
|
|
97
|
-
showNextPage();
|
|
98
|
-
break;
|
|
99
|
-
case 'up':
|
|
100
|
-
Ti.API.info('Swiped up');
|
|
101
|
-
break;
|
|
102
|
-
case 'down':
|
|
103
|
-
Ti.API.info('Swiped down');
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Swipe vs scroll
|
|
110
|
-
|
|
111
|
-
- Swipe is a quick flick, usually left or right.
|
|
112
|
-
- Scroll is a sustained drag, usually up or down.
|
|
113
|
-
|
|
114
|
-
## 4. Pinch gesture (iOS only)
|
|
115
|
-
|
|
116
|
-
```javascript
|
|
117
|
-
const view = Ti.UI.createView({
|
|
118
|
-
backgroundColor: 'green',
|
|
119
|
-
width: 300, height: 300
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
view.addEventListener('pinch', (e) => {
|
|
123
|
-
Ti.API.info(`Pinch scale: ${e.scale}`);
|
|
124
|
-
// e.scale < 1.0 = pinch together
|
|
125
|
-
// e.scale > 1.0 = pinch apart
|
|
126
|
-
});
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Pinch to zoom
|
|
130
|
-
|
|
131
|
-
```javascript
|
|
132
|
-
const imageView = Ti.UI.createImageView({
|
|
133
|
-
image: 'photo.jpg',
|
|
134
|
-
width: 300, height: 300
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
let currentScale = 1.0;
|
|
138
|
-
|
|
139
|
-
imageView.addEventListener('pinch', (e) => {
|
|
140
|
-
currentScale = e.scale;
|
|
141
|
-
imageView.transform = Ti.UI.create2DMatrix().scale(currentScale);
|
|
142
|
-
});
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## 5. Long press gesture
|
|
146
|
-
|
|
147
|
-
### Basic long press
|
|
148
|
-
|
|
149
|
-
```javascript
|
|
150
|
-
const view = Ti.UI.createView({
|
|
151
|
-
backgroundColor: 'orange',
|
|
152
|
-
width: 200, height: 200
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
view.addEventListener('longpress', (e) => {
|
|
156
|
-
Ti.API.info(`Long press at: ${e.x}, ${e.y}`);
|
|
157
|
-
showContextMenu(e);
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Long press duration
|
|
162
|
-
|
|
163
|
-
Default duration varies by platform. You can roll your own:
|
|
164
|
-
|
|
165
|
-
```javascript
|
|
166
|
-
let pressTimer = null;
|
|
167
|
-
const PRESS_DURATION = 1000; // 1 second
|
|
168
|
-
|
|
169
|
-
view.addEventListener('touchstart', (e) => {
|
|
170
|
-
pressTimer = setTimeout(() => {
|
|
171
|
-
showContextMenu(e);
|
|
172
|
-
}, PRESS_DURATION);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
view.addEventListener('touchend', () => {
|
|
176
|
-
if (pressTimer) {
|
|
177
|
-
clearTimeout(pressTimer);
|
|
178
|
-
pressTimer = null;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
view.addEventListener('touchmove', () => {
|
|
183
|
-
// Cancel long press if moved significantly
|
|
184
|
-
if (pressTimer) {
|
|
185
|
-
clearTimeout(pressTimer);
|
|
186
|
-
pressTimer = null;
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Android long press convention
|
|
192
|
-
|
|
193
|
-
On Android, long press usually shows a context menu:
|
|
194
|
-
|
|
195
|
-
```javascript
|
|
196
|
-
view.addEventListener('longpress', (e) => {
|
|
197
|
-
const dialog = Ti.UI.createAlertDialog({
|
|
198
|
-
title: 'Options',
|
|
199
|
-
message: 'What would you like to do?',
|
|
200
|
-
buttonNames: ['Edit', 'Delete', 'Share', 'Cancel']
|
|
201
|
-
});
|
|
202
|
-
dialog.addEventListener('click', (e) => {
|
|
203
|
-
switch(e.index) {
|
|
204
|
-
case 0: editItem(); break;
|
|
205
|
-
case 1: deleteItem(); break;
|
|
206
|
-
case 2: shareItem(); break;
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
dialog.show();
|
|
210
|
-
});
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## 6. Shake gesture
|
|
214
|
-
|
|
215
|
-
### Detecting shake
|
|
216
|
-
|
|
217
|
-
```javascript
|
|
218
|
-
Ti.Gesture.addEventListener('shake', (e) => {
|
|
219
|
-
Ti.API.info(`Device shaken at ${e.timestamp}`);
|
|
220
|
-
|
|
221
|
-
// Refresh content, undo action, etc.
|
|
222
|
-
refreshData();
|
|
223
|
-
});
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Shake example
|
|
227
|
-
|
|
228
|
-
```javascript
|
|
229
|
-
// Use shake to refresh data
|
|
230
|
-
const scrollView = Ti.UI.createScrollView({
|
|
231
|
-
contentHeight: Ti.UI.SIZE
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
Ti.Gesture.addEventListener('shake', () => {
|
|
235
|
-
// Refresh data
|
|
236
|
-
loadDataFromServer();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
function loadDataFromServer() {
|
|
240
|
-
// ...
|
|
241
|
-
Ti.API.info('Data refreshed due to shake');
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Testing shake
|
|
246
|
-
|
|
247
|
-
- iOS Simulator: Hardware > Shake Device
|
|
248
|
-
- Android Emulator: not supported, test on physical device
|
|
249
|
-
- Physical device: shake the device
|
|
250
|
-
|
|
251
|
-
## 7. Accelerometer as input
|
|
252
|
-
|
|
253
|
-
### Basic accelerometer
|
|
254
|
-
|
|
255
|
-
```javascript
|
|
256
|
-
const labelX = Ti.UI.createLabel({ text: 'X: 0' });
|
|
257
|
-
const labelY = Ti.UI.createLabel({ text: 'Y: 0', top: 30 });
|
|
258
|
-
const labelZ = Ti.UI.createLabel({ text: 'Z: 0', top: 60 });
|
|
259
|
-
|
|
260
|
-
Ti.Accelerometer.addEventListener('update', (e) => {
|
|
261
|
-
labelX.text = `X: ${e.x.toFixed(2)}`;
|
|
262
|
-
labelY.text = `Y: ${e.y.toFixed(2)}`;
|
|
263
|
-
labelZ.text = `Z: ${e.z.toFixed(2)}`;
|
|
264
|
-
});
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### Accelerometer properties
|
|
268
|
-
|
|
269
|
-
| Property | Description | Range |
|
|
270
|
-
| ----------- | ------------------- | -------------------- |
|
|
271
|
-
| `x` | X-axis acceleration | G-force (±9.81 m/s²) |
|
|
272
|
-
| `y` | Y-axis acceleration | G-force |
|
|
273
|
-
| `z` | Z-axis acceleration | G-force |
|
|
274
|
-
| `timestamp` | When event occurred | Timestamp |
|
|
275
|
-
|
|
276
|
-
### Using accelerometer for control
|
|
277
|
-
|
|
278
|
-
```javascript
|
|
279
|
-
const sensitivity = 2.0;
|
|
280
|
-
let lastX = 0, lastY = 0;
|
|
281
|
-
|
|
282
|
-
Ti.Accelerometer.addEventListener('update', (e) => {
|
|
283
|
-
const deltaX = e.x - lastX;
|
|
284
|
-
const deltaY = e.y - lastY;
|
|
285
|
-
|
|
286
|
-
if (Math.abs(deltaX) > sensitivity) {
|
|
287
|
-
if (deltaX > 0) {
|
|
288
|
-
moveRight();
|
|
289
|
-
} else {
|
|
290
|
-
moveLeft();
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
lastX = e.x;
|
|
295
|
-
lastY = e.y;
|
|
296
|
-
});
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Smoothing accelerometer data
|
|
300
|
-
|
|
301
|
-
Accelerometer data is noisy. Smooth it:
|
|
302
|
-
|
|
303
|
-
```javascript
|
|
304
|
-
let samples = [];
|
|
305
|
-
const SAMPLE_SIZE = 10;
|
|
306
|
-
|
|
307
|
-
Ti.Accelerometer.addEventListener('update', (e) => {
|
|
308
|
-
samples.push({ x: e.x, y: e.y, z: e.z });
|
|
309
|
-
|
|
310
|
-
if (samples.length >= SAMPLE_SIZE) {
|
|
311
|
-
// Calculate average
|
|
312
|
-
const avgX = samples.reduce((sum, s) => sum + s.x, 0) / samples.length;
|
|
313
|
-
const avgY = samples.reduce((sum, s) => sum + s.y, 0) / samples.length;
|
|
314
|
-
const avgZ = samples.reduce((sum, s) => sum + s.z, 0) / samples.length;
|
|
315
|
-
|
|
316
|
-
// Use averaged values
|
|
317
|
-
updatePosition(avgX, avgY, avgZ);
|
|
318
|
-
|
|
319
|
-
// Clear samples
|
|
320
|
-
samples = [];
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## 8. Gesture lifecycle management
|
|
326
|
-
|
|
327
|
-
### Battery considerations
|
|
328
|
-
|
|
329
|
-
Global gesture events (`Ti.Gesture`, `Ti.Accelerometer`) keep hardware powered and drain battery. Remove listeners when not needed.
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
let accelerometerAdded = false;
|
|
333
|
-
const accelerometerCallback = (e) => {
|
|
334
|
-
// Process accelerometer data
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
function startTracking() {
|
|
338
|
-
if (!accelerometerAdded) {
|
|
339
|
-
Ti.Accelerometer.addEventListener('update', accelerometerCallback);
|
|
340
|
-
accelerometerAdded = true;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function stopTracking() {
|
|
345
|
-
if (accelerometerAdded) {
|
|
346
|
-
Ti.Accelerometer.removeEventListener('update', accelerometerCallback);
|
|
347
|
-
accelerometerAdded = false;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Android: Manage with app lifecycle
|
|
352
|
-
if (Ti.Platform.osname === 'android') {
|
|
353
|
-
Ti.Android.currentActivity.addEventListener('pause', () => {
|
|
354
|
-
stopTracking();
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
Ti.Android.currentActivity.addEventListener('resume', () => {
|
|
358
|
-
startTracking();
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
## 9. Platform-specific considerations
|
|
364
|
-
|
|
365
|
-
### iOS
|
|
366
|
-
|
|
367
|
-
- Pinch is fully supported.
|
|
368
|
-
- Simulator shake: Hardware > Shake Device.
|
|
369
|
-
- More touch events are supported.
|
|
370
|
-
- Gesture recognition is smoother.
|
|
371
|
-
|
|
372
|
-
### Android
|
|
373
|
-
|
|
374
|
-
- Pinch support is limited or experimental.
|
|
375
|
-
- No simulator shake. Test on device.
|
|
376
|
-
- Long press opens context menus (standard pattern).
|
|
377
|
-
- Hardware button events are available.
|
|
378
|
-
|
|
379
|
-
## 10. Best practices
|
|
380
|
-
|
|
381
|
-
1. Test on physical devices. Simulators do not support all gestures.
|
|
382
|
-
2. Remove global gesture listeners when not needed to save battery.
|
|
383
|
-
3. Smooth accelerometer data with averaging.
|
|
384
|
-
4. Use the right gesture for the task. Long press for context menus, swipe for navigation.
|
|
385
|
-
5. Consider accessibility. Make sure gestures do not conflict with screen readers.
|
|
386
|
-
6. Handle edge cases like touch cancel and gesture interruptions.
|
|
387
|
-
7. Provide alternatives. Not all users can perform all gestures.
|
|
388
|
-
|
|
389
|
-
## 11. Combining gestures
|
|
390
|
-
|
|
391
|
-
### Multiple gesture types
|
|
392
|
-
|
|
393
|
-
```javascript
|
|
394
|
-
const view = Ti.UI.createView({
|
|
395
|
-
width: 300, height: 300,
|
|
396
|
-
backgroundColor: 'cyan'
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
// Swipe for navigation
|
|
400
|
-
view.addEventListener('swipe', (e) => {
|
|
401
|
-
if (e.direction === 'left') {
|
|
402
|
-
showPrevious();
|
|
403
|
-
} else if (e.direction === 'right') {
|
|
404
|
-
showNext();
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
// Long press for options
|
|
409
|
-
view.addEventListener('longpress', (e) => {
|
|
410
|
-
showOptions();
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
// Double tap for like
|
|
414
|
-
view.addEventListener('doubletap', (e) => {
|
|
415
|
-
likeContent();
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
// Pinch to zoom (iOS)
|
|
419
|
-
view.addEventListener('pinch', (e) => {
|
|
420
|
-
if (e.scale > 1.0) {
|
|
421
|
-
zoomIn();
|
|
422
|
-
} else {
|
|
423
|
-
zoomOut();
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
### Preventing gesture conflicts
|
|
429
|
-
|
|
430
|
-
```javascript
|
|
431
|
-
let touchStartTime = 0;
|
|
432
|
-
|
|
433
|
-
view.addEventListener('touchstart', (e) => {
|
|
434
|
-
touchStartTime = Date.now();
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
view.addEventListener('touchend', (e) => {
|
|
438
|
-
const touchDuration = Date.now() - touchStartTime;
|
|
439
|
-
|
|
440
|
-
if (touchDuration < 200) {
|
|
441
|
-
// Short tap - treat as click
|
|
442
|
-
handleClick();
|
|
443
|
-
} else if (touchDuration > 500) {
|
|
444
|
-
// Long touch - already handled by longpress
|
|
445
|
-
// Ignore
|
|
446
|
-
}
|
|
447
|
-
});
|
|
448
|
-
```
|