@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.
Files changed (98) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/README.md +31 -60
  3. package/agents/ti-pro.md +3 -1
  4. package/commands/ti-audit.md +6 -4
  5. package/docs/examples.md +9 -0
  6. package/docs/knowledge-index.md +2 -1
  7. package/lib/config.js +1 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +18 -179
  10. package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
  11. package/skills/alloy-guides/references/CONCEPTS.md +27 -162
  12. package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
  13. package/skills/alloy-guides/references/MODELS.md +47 -723
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
  15. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
  16. package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
  17. package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
  18. package/skills/alloy-guides/references/WIDGETS.md +49 -127
  19. package/skills/alloy-howtos/SKILL.md +14 -169
  20. package/skills/alloy-howtos/references/best_practices.md +9 -113
  21. package/skills/alloy-howtos/references/cli_reference.md +18 -223
  22. package/skills/alloy-howtos/references/config_files.md +50 -133
  23. package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
  24. package/skills/alloy-howtos/references/samples.md +21 -138
  25. package/skills/ti-api/SKILL.md +10 -2
  26. package/skills/ti-api/references/api-android.md +36 -2
  27. package/skills/ti-api/references/api-app-platform.md +39 -3
  28. package/skills/ti-api/references/api-core.md +50 -18
  29. package/skills/ti-api/references/api-data-network.md +49 -35
  30. package/skills/ti-api/references/api-media.md +45 -27
  31. package/skills/ti-api/references/api-services.md +39 -9
  32. package/skills/ti-api/references/api-ui-android.md +33 -13
  33. package/skills/ti-api/references/api-ui-extras.md +41 -15
  34. package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
  35. package/skills/ti-api/references/api-ui-ios.md +74 -2
  36. package/skills/ti-api/references/api-ui-lists.md +32 -16
  37. package/skills/ti-api/references/api-ui-text-input.md +34 -17
  38. package/skills/ti-api/references/api-ui-views.md +27 -1
  39. package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
  40. package/skills/ti-api/references/api-xml-global.md +66 -16
  41. package/skills/ti-create-release/SKILL.md +98 -0
  42. package/skills/ti-create-release/references/module-discovery.md +69 -0
  43. package/skills/ti-expert/references/adaptive-layouts.md +1 -1
  44. package/skills/ti-guides/SKILL.md +37 -76
  45. package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
  46. package/skills/ti-guides/references/android-manifest.md +24 -83
  47. package/skills/ti-guides/references/app-distribution.md +31 -377
  48. package/skills/ti-guides/references/application-frameworks.md +127 -335
  49. package/skills/ti-guides/references/cli-reference.md +184 -633
  50. package/skills/ti-guides/references/commonjs-advanced.md +81 -231
  51. package/skills/ti-guides/references/compatibility-matrix.md +36 -75
  52. package/skills/ti-guides/references/hello-world.md +95 -70
  53. package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
  54. package/skills/ti-guides/references/resources.md +174 -142
  55. package/skills/ti-guides/references/sdk-release-notes.md +28 -71
  56. package/skills/ti-guides/references/tiapp-config.md +222 -598
  57. package/skills/ti-howtos/SKILL.md +23 -123
  58. package/skills/ti-howtos/references/cross-platform-development.md +119 -324
  59. package/skills/ti-howtos/references/debugging-profiling.md +77 -445
  60. package/skills/ti-howtos/references/extending-titanium.md +199 -673
  61. package/skills/ti-howtos/references/local-data-sources.md +87 -300
  62. package/skills/ti-howtos/references/location-and-maps.md +86 -213
  63. package/skills/ti-howtos/references/media-apis.md +103 -223
  64. package/skills/ti-howtos/references/notification-services.md +86 -506
  65. package/skills/ti-howtos/references/remote-data-sources.md +97 -316
  66. package/skills/ti-howtos/references/using-modules.md +77 -133
  67. package/skills/ti-ui/SKILL.md +28 -143
  68. package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
  69. package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
  70. package/skills/ti-ui/references/listviews-and-performance.md +100 -703
  71. package/skills/ti-ui/references/platform-conventions.md +180 -0
  72. package/skills/ti-ui/references/user-interface.md +43 -0
  73. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
  74. package/skills/alloy-howtos/references/custom_tags.md +0 -148
  75. package/skills/ti-guides/references/coding-best-practices.md +0 -149
  76. package/skills/ti-guides/references/javascript-primer.md +0 -414
  77. package/skills/ti-guides/references/reserved-words.md +0 -36
  78. package/skills/ti-guides/references/style-and-conventions.md +0 -103
  79. package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
  80. package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
  81. package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
  82. package/skills/ti-howtos/references/google-maps-v2.md +0 -172
  83. package/skills/ti-howtos/references/ios-map-kit.md +0 -149
  84. package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
  85. package/skills/ti-howtos/references/tutorials.md +0 -565
  86. package/skills/ti-howtos/references/web-content-integration.md +0 -287
  87. package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
  88. package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
  89. package/skills/ti-ui/references/animation-and-matrices.md +0 -569
  90. package/skills/ti-ui/references/application-structures.md +0 -626
  91. package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
  92. package/skills/ti-ui/references/event-handling.md +0 -401
  93. package/skills/ti-ui/references/gestures.md +0 -448
  94. package/skills/ti-ui/references/orientation.md +0 -374
  95. package/skills/ti-ui/references/platform-ui-android.md +0 -727
  96. package/skills/ti-ui/references/platform-ui-ios.md +0 -576
  97. package/skills/ti-ui/references/scrolling-views.md +0 -288
  98. package/skills/ti-ui/references/tableviews.md +0 -542
@@ -1,749 +1,146 @@
1
- # ListViews and performance optimization
2
-
3
- <!-- TOC-START -->
4
- ## Contents
5
-
6
- - [1. Overview](#1-overview)
7
- - [2. Basic ListView structure](#2-basic-listview-structure)
8
- - [3. Templates](#3-templates)
9
- - [4. Data binding](#4-data-binding)
10
- - [5. Section operations](#5-section-operations)
11
- - [6. Events](#6-events)
12
- - [7. Critical performance rules](#7-critical-performance-rules)
13
- - [8. iOS action items (swipe actions)](#8-ios-action-items-swipe-actions)
14
- - [9. Editing mode (iOS)](#9-editing-mode-ios)
15
- - [10. Search](#10-search)
16
- - [11. Performance best practices](#11-performance-best-practices)
17
- - [12. Transitioning from TableView](#12-transitioning-from-tableview)
18
- - [13. Common patterns](#13-common-patterns)
19
- - [14. Platform differences](#14-platform-differences)
20
- - [15. Debugging](#15-debugging)
21
-
22
- <!-- TOC-END -->
23
-
24
- ## 1. Overview
25
-
26
- ListView is a data-oriented, high-performance replacement for TableView. It handles large datasets by recycling native views and managing the item lifecycle for you.
27
-
28
- ### Core concepts
29
-
30
- | Concept | Description |
31
- | ---------------- | ------------------------------------------------------------- |
32
- | ListView | Container for sections |
33
- | ListSection | Organizes items, supports CRUD operations |
34
- | ListItem | Virtual view object (not directly accessible after rendering) |
35
- | ItemTemplate | Defines row structure and binding |
36
- | ListDataItem | Raw data bound to templates |
37
-
38
- ## 2. Basic ListView structure
39
-
40
- ### Declarative (Alloy XML)
41
-
42
- ```xml
43
- <Alloy>
44
- <Window>
45
- <ListView id="myList">
46
- <ListSection name="section1">
47
- <ListItem title="Item 1"/>
48
- <ListItem title="Item 2"/>
49
- <ListItem title="Item 3"/>
50
- </ListSection>
51
- </ListView>
52
- </Window>
53
- </Alloy>
54
- ```
55
-
56
- ### Programmatic data binding
57
-
58
- ```javascript
59
- const items = [
60
- { properties: { title: "Item 1" } },
61
- { properties: { title: "Item 2" } },
62
- { properties: { title: "Item 3" } }
63
- ];
64
-
65
- $.myList.sections[0].setItems(items);
66
- ```
67
-
68
- ### Mapping external data
69
-
70
- ```javascript
71
- const externalData = [
72
- { name: "Item 1", value: 100 },
73
- { name: "Item 2", value: 200 }
74
- ];
75
-
76
- // Map to ListDataItem format
77
- const items = _.map(externalData, (item) => {
78
- return {
79
- properties: {
80
- title: item.name
81
- },
82
- // Custom binding
83
- value: { text: item.value.toString() }
84
- };
85
- });
86
-
87
- $.myList.sections[0].setItems(items);
88
- ```
89
-
90
- ## 3. Templates
91
-
92
- ### Default template
93
-
94
- Built-in template with:
95
- - ImageView (left on iOS, right on Android)
96
- - Title label (left-aligned, black)
97
- - Optional accessory icon
98
-
99
- ```xml
100
- <ListView id="myList">
101
- <ListSection>
102
- <ListItem title="Title" image="icon.png" accessoryType="Ti.UI.LIST_ACCESSORY_TYPE_DISCLOSURE"/>
103
- </ListSection>
104
- </ListView>
105
- ```
106
-
107
- ### Custom templates
108
-
109
- Create with `<Templates>` and `<ItemTemplate>`:
110
-
111
- ```xml
112
- <ListView id="elementsList" defaultItemTemplate="elementTemplate">
113
- <Templates>
114
- <ItemTemplate name="elementTemplate">
115
- <!-- Bindable elements with bindId -->
116
- <Label bindId="symbol" id="symbol" />
117
- <View id="atomProperties">
118
- <Label bindId="name" id="name" />
119
- <View id="secondLine">
120
- <Label class="line2" bindId="number" id="number" />
121
- <Label class="line2" bindId="mass" id="mass" />
122
- </View>
123
- </View>
124
- <ImageView bindId="image" id="image" />
125
- </ItemTemplate>
126
- </Templates>
127
- <ListSection>
128
- <!-- Bind data using bindId:property syntax -->
129
- <ListItem symbol:text="H" symbol:color="#090" name:text="Hydrogen" number:text="1" mass:text="1.00794"/>
130
- </ListSection>
131
- </ListView>
132
- ```
133
-
134
- ### Multiple templates
135
-
136
- ```xml
137
- <ListView id="dynamicListView">
138
- <Templates>
139
- <ItemTemplate name="image_title" height="100">
140
- <View layout="horizontal" left="15">
141
- <ImageView bindId="image" id="image"/>
142
- <Label bindId="label" id="label1"/>
143
- </View>
144
- </ItemTemplate>
145
- <ItemTemplate name="title_only" height="50">
146
- <View left="15">
147
- <Label bindId="label"/>
148
- </View>
149
- </ItemTemplate>
150
- </Templates>
151
- <ListSection/>
152
- </ListView>
153
- ```
154
-
155
- Assign template per item:
156
-
157
- ```javascript
158
- const items = [
159
- {
160
- label: { text: "Full item" },
161
- image: { image: "photo.png" },
162
- template: "image_title" // Use this template
163
- },
164
- {
165
- label: { text: "Text only" },
166
- template: "title_only" // Use this template
167
- }
168
- ];
169
-
170
- $.dynamicListView.sections[0].setItems(items);
171
- ```
172
-
173
- ### iOS built-in templates (iOS only)
174
-
175
- iOS provides four built-in templates you can use without defining custom templates:
176
-
177
- | Constant | Layout |
178
- | ----------------------------------- | --------------------------------------------------------------- |
179
- | `Ti.UI.LIST_ITEM_TEMPLATE_DEFAULT` | Left-justified title only (default) |
180
- | `Ti.UI.LIST_ITEM_TEMPLATE_SUBTITLE` | Title with subtitle below in smaller gray text |
181
- | `Ti.UI.LIST_ITEM_TEMPLATE_SETTINGS` | Left-justified title on left, right-justified subtitle on right |
182
- | `Ti.UI.LIST_ITEM_TEMPLATE_CONTACTS` | Right-justified title with left-justified subtitle |
183
-
184
- ```javascript
185
- const section = Ti.UI.createListSection({
186
- items: [
187
- { properties: { title: 'Title', subtitle: 'Subtitle' } }
188
- ]
189
- });
190
-
191
- const listView = Ti.UI.createListView({
192
- sections: [section],
193
- defaultItemTemplate: Ti.UI.LIST_ITEM_TEMPLATE_SUBTITLE
194
- });
195
- ```
196
-
197
- ### Supported template view classes
198
-
199
- The following views can be used as child elements in custom templates: ActivityIndicator, Button, ImageView, Label, MaskedImage, ProgressBar, Slider, Switch, TextArea, TextField.
200
-
201
- ## 4. Data binding
202
-
203
- ### Binding syntax
204
-
205
- XML (Alloy): `bindId:property="value"` JavaScript: `{ bindId: { property: value } }`
206
-
207
- ### Programmatic binding with custom templates
208
-
209
- ```javascript
210
- const items = [
211
- {
212
- mass: { text: "1.00794" },
213
- name: { text: "Hydrogen" },
214
- number: { text: "1" },
215
- symbol: { color: "#090", text: "H" }
216
- },
217
- {
218
- mass: { text: "4.002602" },
219
- name: { text: "Helium" },
220
- number: { text: "2" },
221
- symbol: { color: "#090", text: "He" }
222
- }
223
- ];
224
-
225
- $.elementsList.sections[0].setItems(items);
226
- ```
227
-
228
- ## 5. Section operations
229
-
230
- ### CRUD methods
231
-
232
- | Method | Description |
233
- | ------------------------------------- | ------------------ |
234
- | `setItems(items)` | Replace all items |
235
- | `appendItems(items)` | Add to end |
236
- | `insertItemsAt(index, items)` | Insert at position |
237
- | `replaceItemsAt(index, count, items)` | Replace range |
238
- | `deleteItemsAt(index, count)` | Delete range |
239
-
240
- ### Example operations
241
-
242
- ```javascript
243
- const section = $.myList.sections[0];
244
-
245
- // Replace all (clears first)
246
- section.setItems(items);
247
-
248
- // Append to end
249
- section.appendItems(newItems);
250
-
251
- // Insert at position 5
252
- section.insertItemsAt(5, moreItems);
253
-
254
- // Replace 3 items starting at index 2
255
- section.replaceItemsAt(2, 3, replacementItems);
256
-
257
- // Delete 2 items starting at index 10
258
- section.deleteItemsAt(10, 2);
259
- ```
260
-
261
- ### Row animation (iOS)
262
-
263
- You can pass animation styles to append, delete, insert, replace, and update methods:
264
-
265
- ```javascript
266
- section.deleteItemsAt(0, 1, {
267
- animationStyle: Ti.UI.iOS.RowAnimationStyle.LEFT
268
- });
269
-
270
- section.appendItems(newItems, {
271
- animationStyle: Ti.UI.iOS.RowAnimationStyle.FADE
272
- });
273
- ```
274
-
275
- Available styles: `Ti.UI.iOS.RowAnimationStyle.BOTTOM`, `FADE`, `LEFT`, `NONE`, `RIGHT`, `TOP`.
276
-
277
- ## 6. Events
278
-
279
- ### Item click
280
-
281
- ```xml
282
- <ListView id="list" onItemclick="handleClick">
283
- ```
284
-
285
- ```javascript
286
- function handleClick(e) {
287
- // e.sectionIndex: which section
288
- // e.itemIndex: which item
289
- // e.bindId: which template element (null if row clicked)
290
- // e.itemId: custom itemId if set
291
-
292
- const section = $.list.sections[e.sectionIndex];
293
- const item = section.getItemAt(e.itemIndex);
294
-
295
- // Update item
296
- item.properties.title += " (clicked)";
297
- item.properties.color = 'red';
298
- section.updateItemAt(e.itemIndex, item);
299
- }
300
- ```
301
-
302
- ### Marker events (infinite scroll)
303
-
304
- Markers act as tripwires for loading more data:
305
-
306
- ```javascript
307
- // Set initial marker at item 100
308
- $.myList.setMarker({ sectionIndex: 0, itemIndex: 99 });
309
-
310
- // Handle marker event
311
- function markerReached(e) {
312
- // Load more data
313
- const moreData = loadNextPage();
314
-
315
- // Append to list
316
- e.section.appendItems(moreData);
317
-
318
- // Set next marker
319
- const nextMarker = e.itemIndex + moreData.length - 1;
320
- $.myList.setMarker({ sectionIndex: e.sectionIndex, itemIndex: nextMarker });
321
- }
322
-
323
- $.myList.addEventListener('marker', markerReached);
324
- ```
325
-
326
- Since SDK 4.1.0, use `addMarker()` to add additional markers after the initial `setMarker()`:
327
-
328
- ```javascript
329
- $.myList.addMarker({ sectionIndex: 0, itemIndex: 149 });
330
- ```
331
-
332
- ### Scroll events
333
-
334
- Since SDK 4.1.0, use `scrollstart` and `scrollend` to monitor scrolling:
335
-
336
- ```javascript
337
- $.myList.addEventListener('scrollstart', (e) => {
338
- Ti.API.info(`Scroll started at section ${e.firstVisibleSectionIndex}, item ${e.firstVisibleItemIndex}`);
339
- Ti.API.info(`Visible items: ${e.visibleItemCount}`);
340
- });
341
-
342
- $.myList.addEventListener('scrollend', (e) => {
343
- Ti.API.info(`Scroll ended at section ${e.firstVisibleSectionIndex}, item ${e.firstVisibleItemIndex}`);
344
- });
345
- ```
346
-
347
- Event properties: `firstVisibleSectionIndex`, `firstVisibleItemIndex`, `visibleItemCount`.
348
-
349
- ### Template element events
350
-
351
- ```xml
352
- <ListView id="likeList" onItemclick="handleItemClick">
353
- <Templates>
354
- <ItemTemplate name="custom">
355
- <Label bindId="label" left="15" />
356
- <ImageView bindId="icon" right="15" />
357
- </ItemTemplate>
358
- </Templates>
359
- <ListSection>
360
- <ListItem label:text="Like me?" icon:image="star_grey.png" />
361
- </ListSection>
362
- </ListView>
363
- ```
1
+ # Lists & tables
364
2
 
365
- ```javascript
366
- function handleItemClick(e) {
367
- // Check which element was clicked
368
- if (e.bindId === "icon") {
369
- const item = e.section.getItemAt(e.itemIndex);
370
-
371
- // Toggle image (update data, not e.source)
372
- if (item.icon.image === "star_grey.png") {
373
- item.icon.image = "star_gold.png";
374
- } else {
375
- item.icon.image = "star_grey.png";
376
- }
3
+ > ListView, TableView, and which of the two to reach for.
377
4
 
378
- e.section.updateItemAt(e.itemIndex, item);
379
- }
380
- }
381
- ```
5
+ - Source: https://titaniumsdk.com/docs/build/ui/lists
6
+ - Written for Titanium SDK 13.4.0 and later.
7
+ - This corpus documents Titanium SDK 13.4.1. Anything here that does not name a version describes 13.4.1.
8
+ - Titanium is maintained by TiDev. The Appcelerator toolchain is retired: there is no `appc` CLI, no Appcelerator Studio and no hosted build service. The supported CLI is `titanium` on npm, invoked as `ti`.
382
9
 
383
- ## 7. Critical performance rules
10
+ ---
384
11
 
385
- ### Rule 1: Avoid Ti.UI.SIZE in templates
12
+ Titanium has two scrolling list types. **Reach for `ListView`.**
386
13
 
387
- Bad (jerky scrolling):
14
+ `TableView` represents rows as view proxies. `ListView` describes row layouts
15
+ as templates and supplies item data separately, so it is the recommended
16
+ approach for long lists.
388
17
 
389
- ```xml
390
- <ItemTemplate name="bad">
391
- <Label bindId="title" height="Ti.UI.SIZE"/> <!-- DON'T -->
392
- </ItemTemplate>
393
- ```
18
+ Neither is deprecated, and `TableView` is still the simpler thing to reach for
19
+ when a "list" is a settings screen of eight fixed rows. Past that, use
20
+ `ListView`.
394
21
 
395
- Good (fixed height or FILL):
22
+ ## A list in three parts
396
23
 
397
- ```xml
398
- <ItemTemplate name="good">
399
- <Label bindId="title" height="40"/> <!-- Fixed -->
400
- </ItemTemplate>
401
- ```
24
+ A `ListView` holds `ListSection`s, and a section holds items. An item is plain
25
+ data, not a view: it says which template to use and what to put in it.
402
26
 
403
- ### Rule 2: Cannot access children directly
27
+ ```js
28
+ const win = Ti.UI.createWindow({ backgroundColor: 'white' });
404
29
 
405
- Views are recycled. Always update via data.
30
+ const section = Ti.UI.createListSection({ headerTitle: 'Modules' });
31
+ section.setItems([
32
+ { properties: { title: 'ti.map' } },
33
+ { properties: { title: 'ti.barcode' } },
34
+ { properties: { title: 'ti.coremotion' } }
35
+ ]);
406
36
 
407
- Bad:
37
+ const list = Ti.UI.createListView({ sections: [section] });
408
38
 
409
- ```javascript
410
- // DON'T - Will be lost when recycled
411
- function handleClick(e) {
412
- e.source.image = "star_gold.png";
413
- }
414
- ```
415
-
416
- Good:
417
-
418
- ```javascript
419
- // DO - Update the data item
420
- function handleClick(e) {
39
+ list.addEventListener('itemclick', (e) => {
421
40
  const item = e.section.getItemAt(e.itemIndex);
422
- item.icon.image = "star_gold.png";
423
- e.section.updateItemAt(e.itemIndex, item);
424
- }
425
- ```
426
-
427
- ### Rule 3: Minimize template count
428
-
429
- Fewer templates means better native cell reuse.
430
-
431
- Good: one template with conditional visibility
432
-
433
- ```xml
434
- <ItemTemplate name="flexible">
435
- <ImageView bindId="icon"/>
436
- <Label bindId="title"/>
437
- <Label bindId="subtitle"/> <!-- Hidden if not needed -->
438
- </ItemTemplate>
439
- ```
440
-
441
- Bad: multiple similar templates
442
-
443
- ```xml
444
- <ItemTemplate name="withIcon">...</ItemTemplate>
445
- <ItemTemplate name="withoutIcon">...</ItemTemplate>
446
- <ItemTemplate name="withSubtitle">...</ItemTemplate>
447
- ```
448
-
449
- ### Rule 4: Use updateItemAt for changes
450
-
451
- ```javascript
452
- // Get item data
453
- const item = section.getItemAt(index);
454
-
455
- // Modify properties
456
- item.properties.backgroundColor = 'blue';
457
- item.customField.text = 'Updated';
458
-
459
- // Update in list
460
- section.updateItemAt(index, item);
461
- ```
462
-
463
- ### Rule 5: Animations are limited
464
-
465
- ListView items have limited animation support. For complex animations, consider TableView.
466
-
467
- ## 8. iOS action items (swipe actions)
468
-
469
- ```javascript
470
- const section = $.myList.sections[0];
471
-
472
- // Define edit actions as plain objects with title, style, and optional color
473
- section.editActions = [
474
- {
475
- title: 'Delete',
476
- style: Ti.UI.iOS.ROW_ACTION_STYLE_DESTRUCTIVE
477
- },
478
- {
479
- title: 'More',
480
- color: 'blue',
481
- style: Ti.UI.iOS.ROW_ACTION_STYLE_NORMAL
482
- }
483
- ];
484
- section.canEdit = true;
485
-
486
- // Handle actions - e.action is the title string of the tapped action
487
- $.myList.addEventListener('editaction', (e) => {
488
- if (e.action === 'Delete') {
489
- e.section.deleteItemsAt(e.itemIndex, 1);
490
- } else if (e.action === 'More') {
491
- // Handle more action
492
- Ti.API.info(`More tapped on item ${e.itemIndex} in section ${e.sectionIndex}`);
493
- }
41
+ Ti.API.info(`tapped ${item.properties.title}`);
494
42
  });
495
- ```
496
-
497
- Available action styles:
498
- - `Ti.UI.iOS.ROW_ACTION_STYLE_DEFAULT` - gray background
499
- - `Ti.UI.iOS.ROW_ACTION_STYLE_DESTRUCTIVE` - red background (default)
500
- - `Ti.UI.iOS.ROW_ACTION_STYLE_NORMAL` - custom color background
501
-
502
- Event properties: `action` (string, the title), `itemId`, `itemIndex`, `section`, `sectionIndex`.
503
-
504
- ## 9. Editing mode (iOS)
505
-
506
- Set `editing` to toggle edit mode and let users delete or reorder items:
507
43
 
508
- ```javascript
509
- // Toggle edit mode
510
- $.myList.editing = true;
511
-
512
- // Auto-remove sections that become empty during editing
513
- $.myList.pruneSectionsOnEdit = true;
44
+ win.add(list);
45
+ win.open();
514
46
  ```
515
47
 
516
- ### Delete event
517
-
518
- Fires when a user deletes an item in edit mode:
519
-
520
- ```javascript
521
- $.myList.addEventListener('delete', (e) => {
522
- Ti.API.info(`Deleted item ${e.itemIndex} from section ${e.sectionIndex}`);
523
- });
524
- ```
48
+ `properties` sets properties on the row itself. With no template, `title` is
49
+ the one that shows.
525
50
 
526
- ### Move event
51
+ ## Templates
527
52
 
528
- Fires when a user reorders an item in edit mode:
53
+ A template names the views in a row and gives each one a `bindId`. Items then
54
+ address those views by that id, so the data and the layout stay separate.
529
55
 
530
- ```javascript
531
- $.myList.addEventListener('move', (e) => {
532
- Ti.API.info(`Moved item from ${e.itemIndex} to ${e.targetItemIndex}`);
533
- });
534
- ```
535
-
536
- ## 10. Search
537
-
538
- ```javascript
539
- const searchView = Ti.UI.createSearchBar({
540
- showCancel: true
541
- });
542
-
543
- $.myList.searchView = searchView;
544
-
545
- // Mark searchable text in items
546
- const items = [
547
- {
548
- properties: {
549
- title: "Apple",
550
- searchableText: "Apple fruit red delicious" // Extra keywords
56
+ ```js
57
+ const template = {
58
+ childTemplates: [
59
+ {
60
+ type: 'Ti.UI.Label',
61
+ bindId: 'name',
62
+ properties: { left: 16, font: { fontSize: 16, fontWeight: 'bold' } }
63
+ },
64
+ {
65
+ type: 'Ti.UI.Label',
66
+ bindId: 'detail',
67
+ properties: { right: 16, color: '#888', font: { fontSize: 14 } }
551
68
  }
552
- }
553
- ];
554
- ```
555
-
556
- ### Search properties
557
-
558
- - `keepSectionsInSearch: true` preserves section headers while filtering results.
559
- - `caseInsensitiveSearch: true` enables case-insensitive filtering.
560
-
561
- ```javascript
562
- const listView = Ti.UI.createListView({
563
- searchView: searchView,
564
- keepSectionsInSearch: true,
565
- caseInsensitiveSearch: true
566
- });
567
- ```
568
-
569
- ### No results event
570
-
571
- Since SDK 3.3.0, when items are filtered using `searchView` or `searchText`, the `noresults` event fires when there are no matches:
69
+ ]
70
+ };
572
71
 
573
- ```javascript
574
- $.myList.addEventListener('noresults', (e) => {
575
- Ti.API.info('No matching items found');
72
+ const list = Ti.UI.createListView({
73
+ templates: { row: template },
74
+ defaultItemTemplate: 'row',
75
+ sections: [section]
576
76
  });
577
- ```
578
-
579
- ## 11. Performance best practices
580
-
581
- Do:
582
- - Use fixed heights in templates.
583
- - Minimize number of templates.
584
- - Use `updateItemAt()` for changes.
585
- - Cache `sections[0]` reference.
586
- - Use markers for infinite scroll.
587
- - Test with real device data volumes.
588
-
589
- Don't:
590
- - Use `Ti.UI.SIZE` for row dimensions.
591
- - Access `e.source` in itemclick events.
592
- - Create too many similar templates.
593
- - Add complex animations to list items.
594
- - Ignore the recycled nature of views.
595
-
596
- ## 12. Transitioning from TableView
597
-
598
- ### Core logic differences
599
-
600
- | TableView | ListView |
601
- | -------------------- | ---------------------------- |
602
- | TableViewRow | ListItem (Virtual) |
603
- | `add()` views to row | `childTemplates` in Template |
604
- | `data` property | `sections` property |
605
- | Direct child access | Bound data updates only |
606
- | `appendRow()` | `appendItems()` |
607
- | `updateRow()` | `updateItemAt()` |
608
- | `deleteRow()` | `deleteItemsAt()` |
609
-
610
- ### API differences
611
-
612
- Properties not available for ListItem:
613
- - `accessibilityLabel`, `className`, `editable`, `hasCheck`, `hasChild`, `hasDetail`, `leftImage`, `moveable`, `rightImage`.
614
- - Alternatives: use `accessoryType` for indicators, and `image` or custom templates for images.
615
-
616
- TableViewSection methods not supported by ListSection:
617
- - `add`, `remove`, `rowAtIndex`.
618
- - Alternatives: use `getItemAt` and `appendItems` or `deleteItemsAt`.
619
-
620
- TableView methods not available to ListView:
621
- - `appendRow`, `deleteRow`, `deselectRow`, `insertRowAfter`, `insertRowBefore`, `selectRow`, `updateRow`, `scrollToIndex`.
622
- - Alternatives: use `scrollToItem` and `selectItem` (iOS). For row manipulation, use the containing ListSection.
623
-
624
- ## 13. Common patterns
625
-
626
- ### Infinite scroll with markers
627
-
628
- ```javascript
629
- const PAGE_SIZE = 25;
630
- let currentPage = 0;
631
77
 
632
- function loadPage(page) {
633
- const data = fetchDataFromAPI(page);
634
-
635
- if (page === 0) {
636
- $.myList.sections[0].setItems(data);
637
- } else {
638
- $.myList.sections[0].appendItems(data);
639
- }
640
-
641
- // Set marker for next page
642
- const markerIndex = (page * PAGE_SIZE) + data.length - 1;
643
- $.myList.setMarker({ sectionIndex: 0, itemIndex: markerIndex });
644
- }
645
-
646
- // Initial load
647
- loadPage(0);
648
-
649
- // Marker handler
650
- $.myList.addEventListener('marker', (e) => {
651
- currentPage++;
652
- loadPage(currentPage);
653
- });
78
+ section.setItems([
79
+ { name: { text: 'ti.map' }, detail: { text: '5.7.0' } },
80
+ { name: { text: 'ti.barcode' }, detail: { text: '4.2.0' } }
81
+ ]);
654
82
  ```
655
83
 
656
- ### Multiple selection
84
+ Each key in an item that is not `properties` or `template` is a `bindId`, and
85
+ its value is the properties to set on that view.
657
86
 
658
- ```javascript
659
- const selectedItems = {};
87
+ > [!IMPORTANT]
88
+ > Row views are recycled. Every property a template sets on a row must be set
89
+ > by **every** item that uses it, or a row will inherit whatever the last item
90
+ > in that slot left behind. Set `color` on one item and not the next and the
91
+ > colour follows the recycled view down the list.
660
92
 
661
- $.myList.addEventListener('itemclick', (e) => {
662
- const item = e.section.getItemAt(e.itemIndex);
663
- const key = `${e.sectionIndex}-${e.itemIndex}`;
664
-
665
- if (selectedItems[key]) {
666
- // Deselect
667
- delete selectedItems[key];
668
- item.properties.accessoryType = Ti.UI.LIST_ACCESSORY_TYPE_NONE;
669
- } else {
670
- // Select
671
- selectedItems[key] = item;
672
- item.properties.accessoryType = Ti.UI.LIST_ACCESSORY_TYPE_CHECKMARK;
673
- }
674
-
675
- e.section.updateItemAt(e.itemIndex, item);
676
- });
677
- ```
93
+ ## Changing the contents
678
94
 
679
- ### Section index (A-Z)
95
+ Replace everything with `setItems`. Add to the end with `appendItems`. Change
96
+ one row in place with `updateItemAt`, which is what to use for a checkbox or a
97
+ "favourited" state, because it does not rebuild the section.
680
98
 
681
- ```javascript
682
- $.myList.sectionIndexTitles = ["A", "B", "C", ...];
99
+ ```js
100
+ section.updateItemAt(0, { name: { text: 'ti.map' }, detail: { text: '5.8.0' } });
683
101
  ```
684
102
 
685
- ## 14. Platform differences
686
-
687
- ### iOS vs Android
103
+ Sections are managed on the list: `appendSection`, `insertSectionAt`,
104
+ `replaceSectionAt`, `deleteSectionAt`.
688
105
 
689
- | Feature | iOS | Android |
690
- | ---------------------- | ------------ | ------------- |
691
- | Action items (swipe) | Full support | Not supported |
692
- | Section index titles | Full support | Not supported |
693
- | Search bar | Full support | Full support |
694
- | Default template image | Left side | Right side |
695
- | cacheSize property | Supported | Not supported |
106
+ ## Which events fire
696
107
 
697
- ### Grouped style (iOS)
108
+ `itemclick` is the one you want, and it gives you `sectionIndex`, `itemIndex`,
109
+ `section` and `bindId` - the last being which view inside the row was tapped,
110
+ which is how one row can have a tappable button and a tappable body.
698
111
 
699
- Set `style: Ti.UI.iOS.ListViewStyle.GROUPED` to display sections as separate visual groups with rounded corners and inset spacing:
112
+ `scrollstart`, `scrolling`, `scrollend`, `dragstart` and `dragend` cover
113
+ scrolling. `marker` fires when a row you nominated with `setMarker` comes into
114
+ view, which is the hook for loading the next page of results.
700
115
 
701
- ```javascript
702
- const listView = Ti.UI.createListView({
703
- style: Ti.UI.iOS.ListViewStyle.GROUPED,
704
- sections: [sectionA, sectionB]
705
- });
706
- ```
116
+ ## TableView
707
117
 
708
- ### Pull-to-refresh (iOS)
118
+ `TableView` builds rows as real views, so a row is a view you can hold onto and
119
+ change directly:
709
120
 
710
- The `pull` event fires when the user pulls past the top of the list, and `pullend` fires when they release. Use `pullView` to set a custom view:
711
-
712
- ```javascript
713
- const pullView = Ti.UI.createView({
714
- height: 60,
715
- backgroundColor: '#eee'
716
- });
717
- pullView.add(Ti.UI.createLabel({ text: 'Pull to refresh...' }));
718
-
719
- $.myList.pullView = pullView;
720
-
721
- $.myList.addEventListener('pull', (e) => {
722
- // User is pulling - update UI as needed
723
- pullView.children[0].text = e.active ? 'Release to refresh...' : 'Pull to refresh...';
724
- });
725
-
726
- $.myList.addEventListener('pullend', (e) => {
727
- // User released - trigger data refresh
728
- refreshData();
121
+ ```js
122
+ const table = Ti.UI.createTableView({
123
+ data: [
124
+ { title: 'General' },
125
+ { title: 'Notifications' },
126
+ { title: 'Privacy' }
127
+ ]
729
128
  });
730
- ```
731
129
 
732
- ### cacheSize (iOS)
733
-
734
- ```javascript
735
- // Number of views to pre-render offscreen
736
- $.myList.cacheSize = 3; // Default
130
+ table.addEventListener('click', (e) => Ti.API.info(`row ${e.index}`));
737
131
  ```
738
132
 
739
- ## 15. Debugging
740
-
741
- ### Common issues
133
+ That directness is useful for a short fixed list. Prefer template-based
134
+ `ListView` for long lists. Avoid treating the TableView model as a guarantee
135
+ that native rows are never reused: the released
136
+ [TableViewRow API](https://titaniumsdk.com/docs/sdk/13.4.1/Titanium.UI.TableViewRow)
137
+ documents structural row classes for Android rendering performance.
742
138
 
743
- Problem: Jerky scrolling Solution: Remove `Ti.UI.SIZE` from templates
139
+ The event is `click`, not `itemclick`.
744
140
 
745
- Problem: Data changes not visible Solution: Use `updateItemAt()` instead of modifying views
141
+ ![Two boxed screenshots labelled iOS and Android, side by side, each showing the same five-item list. On iOS the section header Modules is grey text on the window background above the first row. On Android it is white text on a filled grey bar spanning the width of the list.](https://titaniumsdk.com/docs/guides/list-view.png)
746
142
 
747
- Problem: Event not firing on template element Solution: Check `bindId` in event handler
143
+ ## Next
748
144
 
749
- Problem: Wrong item updated Solution: Use `e.section.getItemAt(e.itemIndex)` not a global reference
145
+ [Icons and launch screens](icons-and-splash-screens.md) is what the
146
+ app looks like before it opens.