@maccesar/titools 2.0.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/AGENTS-TEMPLATE.md +173 -0
- package/README.md +867 -0
- package/agents/ti-researcher.md +108 -0
- package/bin/titools.js +53 -0
- package/lib/commands/agents.js +126 -0
- package/lib/commands/install.js +188 -0
- package/lib/commands/uninstall.js +215 -0
- package/lib/commands/update.js +159 -0
- package/lib/config.js +119 -0
- package/lib/downloader.js +153 -0
- package/lib/installer.js +253 -0
- package/lib/platform.js +108 -0
- package/lib/symlink.js +142 -0
- package/lib/utils.js +270 -0
- package/package.json +67 -0
- package/skills/alloy-expert/SKILL.md +247 -0
- package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
- package/skills/alloy-expert/references/alloy-structure.md +381 -0
- package/skills/alloy-expert/references/anti-patterns.md +133 -0
- package/skills/alloy-expert/references/code-conventions.md +469 -0
- package/skills/alloy-expert/references/contracts.md +280 -0
- package/skills/alloy-expert/references/controller-patterns.md +520 -0
- package/skills/alloy-expert/references/error-handling.md +484 -0
- package/skills/alloy-expert/references/examples.md +735 -0
- package/skills/alloy-expert/references/migration-patterns.md +298 -0
- package/skills/alloy-expert/references/patterns.md +448 -0
- package/skills/alloy-expert/references/performance-patterns.md +855 -0
- package/skills/alloy-expert/references/security-patterns.md +847 -0
- package/skills/alloy-expert/references/state-management.md +779 -0
- package/skills/alloy-expert/references/testing.md +872 -0
- package/skills/alloy-guides/SKILL.md +214 -0
- package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
- package/skills/alloy-guides/references/CONCEPTS.md +191 -0
- package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
- package/skills/alloy-guides/references/MODELS.md +1028 -0
- package/skills/alloy-guides/references/PURGETSS.md +56 -0
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
- package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
- package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
- package/skills/alloy-guides/references/WIDGETS.md +176 -0
- package/skills/alloy-howtos/SKILL.md +203 -0
- package/skills/alloy-howtos/references/best_practices.md +138 -0
- package/skills/alloy-howtos/references/cli_reference.md +253 -0
- package/skills/alloy-howtos/references/config_files.md +87 -0
- package/skills/alloy-howtos/references/custom_tags.md +147 -0
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
- package/skills/alloy-howtos/references/samples.md +167 -0
- package/skills/purgetss/SKILL.md +442 -0
- package/skills/purgetss/assets/purgetss.config.cjs +17 -0
- package/skills/purgetss/references/EXAMPLES.md +247 -0
- package/skills/purgetss/references/animation-system.md +1294 -0
- package/skills/purgetss/references/apply-directive.md +375 -0
- package/skills/purgetss/references/arbitrary-values.md +612 -0
- package/skills/purgetss/references/class-index.md +1350 -0
- package/skills/purgetss/references/cli-commands.md +948 -0
- package/skills/purgetss/references/configurable-properties.md +654 -0
- package/skills/purgetss/references/custom-rules.md +161 -0
- package/skills/purgetss/references/customization-deep-dive.md +722 -0
- package/skills/purgetss/references/dynamic-component-creation.md +489 -0
- package/skills/purgetss/references/grid-layout.md +455 -0
- package/skills/purgetss/references/icon-fonts.md +609 -0
- package/skills/purgetss/references/installation-setup.md +366 -0
- package/skills/purgetss/references/opacity-modifier.md +291 -0
- package/skills/purgetss/references/platform-modifiers.md +479 -0
- package/skills/purgetss/references/smart-mappings.md +42 -0
- package/skills/purgetss/references/titanium-resets.md +359 -0
- package/skills/purgetss/references/ui-ux-design.md +1526 -0
- package/skills/ti-guides/SKILL.md +94 -0
- package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
- package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
- package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
- package/skills/ti-guides/references/android-manifest.md +97 -0
- package/skills/ti-guides/references/app-distribution.md +258 -0
- package/skills/ti-guides/references/application-frameworks.md +377 -0
- package/skills/ti-guides/references/cli-reference.md +402 -0
- package/skills/ti-guides/references/coding-best-practices.md +102 -0
- package/skills/ti-guides/references/commonjs-advanced.md +134 -0
- package/skills/ti-guides/references/hello-world.md +100 -0
- package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
- package/skills/ti-guides/references/javascript-primer.md +411 -0
- package/skills/ti-guides/references/reserved-words.md +36 -0
- package/skills/ti-guides/references/resources.md +183 -0
- package/skills/ti-guides/references/style-and-conventions.md +48 -0
- package/skills/ti-guides/references/tiapp-config.md +609 -0
- package/skills/ti-howtos/SKILL.md +174 -0
- package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
- package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
- package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
- package/skills/ti-howtos/references/cross-platform-development.md +348 -0
- package/skills/ti-howtos/references/debugging-profiling.md +543 -0
- package/skills/ti-howtos/references/extending-titanium.md +723 -0
- package/skills/ti-howtos/references/google-maps-v2.md +169 -0
- package/skills/ti-howtos/references/ios-map-kit.md +143 -0
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
- package/skills/ti-howtos/references/local-data-sources.md +301 -0
- package/skills/ti-howtos/references/location-and-maps.md +252 -0
- package/skills/ti-howtos/references/media-apis.md +210 -0
- package/skills/ti-howtos/references/notification-services.md +599 -0
- package/skills/ti-howtos/references/remote-data-sources.md +349 -0
- package/skills/ti-howtos/references/tutorials.md +502 -0
- package/skills/ti-howtos/references/using-modules.md +237 -0
- package/skills/ti-howtos/references/web-content-integration.md +307 -0
- package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
- package/skills/ti-ui/SKILL.md +179 -0
- package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
- package/skills/ti-ui/references/animation-and-matrices.md +599 -0
- package/skills/ti-ui/references/application-structures.md +655 -0
- package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
- package/skills/ti-ui/references/event-handling.md +393 -0
- package/skills/ti-ui/references/gestures.md +473 -0
- package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
- package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
- package/skills/ti-ui/references/listviews-and-performance.md +619 -0
- package/skills/ti-ui/references/orientation.md +362 -0
- package/skills/ti-ui/references/platform-ui-android.md +635 -0
- package/skills/ti-ui/references/platform-ui-ios.md +469 -0
- package/skills/ti-ui/references/scrolling-views.md +252 -0
- package/skills/ti-ui/references/tableviews.md +568 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
# ListViews and Performance Optimization
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [ListViews and Performance Optimization](#listviews-and-performance-optimization)
|
|
6
|
+
- [Table of Contents](#table-of-contents)
|
|
7
|
+
- [1. Overview](#1-overview)
|
|
8
|
+
- [Core Concepts](#core-concepts)
|
|
9
|
+
- [2. Basic ListView Structure](#2-basic-listview-structure)
|
|
10
|
+
- [Declarative (Alloy XML)](#declarative-alloy-xml)
|
|
11
|
+
- [Programmatic Data Binding](#programmatic-data-binding)
|
|
12
|
+
- [Mapping External Data](#mapping-external-data)
|
|
13
|
+
- [3. Templates](#3-templates)
|
|
14
|
+
- [Default Template](#default-template)
|
|
15
|
+
- [Custom Templates](#custom-templates)
|
|
16
|
+
- [Multiple Templates](#multiple-templates)
|
|
17
|
+
- [4. Data Binding](#4-data-binding)
|
|
18
|
+
- [Binding Syntax](#binding-syntax)
|
|
19
|
+
- [Programmatic Binding with Custom Templates](#programmatic-binding-with-custom-templates)
|
|
20
|
+
- [5. Section Operations](#5-section-operations)
|
|
21
|
+
- [CRUD Methods](#crud-methods)
|
|
22
|
+
- [Example Operations](#example-operations)
|
|
23
|
+
- [6. Events](#6-events)
|
|
24
|
+
- [Item Click](#item-click)
|
|
25
|
+
- [Marker Events (Infinite Scroll)](#marker-events-infinite-scroll)
|
|
26
|
+
- [Template Element Events](#template-element-events)
|
|
27
|
+
- [7. Critical Performance Rules](#7-critical-performance-rules)
|
|
28
|
+
- [Rule 1: Avoid Ti.UI.SIZE in Templates](#rule-1-avoid-tiuisize-in-templates)
|
|
29
|
+
- [Rule 2: Cannot Access Children Directly](#rule-2-cannot-access-children-directly)
|
|
30
|
+
- [Rule 3: Minimize Template Count](#rule-3-minimize-template-count)
|
|
31
|
+
- [Rule 4: Use updateItemAt for Changes](#rule-4-use-updateitemat-for-changes)
|
|
32
|
+
- [Rule 5: Animations are Limited](#rule-5-animations-are-limited)
|
|
33
|
+
- [8. iOS Action Items (Swipe Actions)](#8-ios-action-items-swipe-actions)
|
|
34
|
+
- [9. Search](#9-search)
|
|
35
|
+
- [10. Performance Best Practices](#10-performance-best-practices)
|
|
36
|
+
- [DO:](#do)
|
|
37
|
+
- [DON'T:](#dont)
|
|
38
|
+
- [11. Transitioning from TableView](#11-transitioning-from-tableview)
|
|
39
|
+
- [Core Logic Differences](#core-logic-differences)
|
|
40
|
+
- [API Differences](#api-differences)
|
|
41
|
+
- [12. Common Patterns](#12-common-patterns)
|
|
42
|
+
- [Infinite Scroll with Markers](#infinite-scroll-with-markers)
|
|
43
|
+
- [Multiple Selection](#multiple-selection)
|
|
44
|
+
- [Section Index (A-Z)](#section-index-a-z)
|
|
45
|
+
- [13. Platform Differences](#13-platform-differences)
|
|
46
|
+
- [iOS vs Android](#ios-vs-android)
|
|
47
|
+
- [cacheSize (iOS)](#cachesize-ios)
|
|
48
|
+
- [14. Debugging](#14-debugging)
|
|
49
|
+
- [Common Issues](#common-issues)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 1. Overview
|
|
54
|
+
|
|
55
|
+
ListView is a data-oriented, high-performance replacement for TableView. It optimizes large datasets by recycling native views and managing the item lifecycle automatically.
|
|
56
|
+
|
|
57
|
+
### Core Concepts
|
|
58
|
+
|
|
59
|
+
| Concept | Description |
|
|
60
|
+
| ---------------- | ------------------------------------------------------------- |
|
|
61
|
+
| **ListView** | Container for sections |
|
|
62
|
+
| **ListSection** | Organizes items, supports CRUD operations |
|
|
63
|
+
| **ListItem** | Virtual view object (not directly accessible after rendering) |
|
|
64
|
+
| **ItemTemplate** | Defines row structure and binding |
|
|
65
|
+
| **ListDataItem** | Raw data bound to templates |
|
|
66
|
+
|
|
67
|
+
## 2. Basic ListView Structure
|
|
68
|
+
|
|
69
|
+
### Declarative (Alloy XML)
|
|
70
|
+
|
|
71
|
+
```xml
|
|
72
|
+
<Alloy>
|
|
73
|
+
<Window>
|
|
74
|
+
<ListView id="myList">
|
|
75
|
+
<ListSection name="section1">
|
|
76
|
+
<ListItem title="Item 1"/>
|
|
77
|
+
<ListItem title="Item 2"/>
|
|
78
|
+
<ListItem title="Item 3"/>
|
|
79
|
+
</ListSection>
|
|
80
|
+
</ListView>
|
|
81
|
+
</Window>
|
|
82
|
+
</Alloy>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Programmatic Data Binding
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
const items = [
|
|
89
|
+
{ properties: { title: "Item 1" } },
|
|
90
|
+
{ properties: { title: "Item 2" } },
|
|
91
|
+
{ properties: { title: "Item 3" } }
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
$.myList.sections[0].setItems(items);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Mapping External Data
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const externalData = [
|
|
101
|
+
{ name: "Item 1", value: 100 },
|
|
102
|
+
{ name: "Item 2", value: 200 }
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
// Map to ListDataItem format
|
|
106
|
+
const items = _.map(externalData, (item) => {
|
|
107
|
+
return {
|
|
108
|
+
properties: {
|
|
109
|
+
title: item.name
|
|
110
|
+
},
|
|
111
|
+
// Custom binding
|
|
112
|
+
value: { text: item.value.toString() }
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
$.myList.sections[0].setItems(items);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 3. Templates
|
|
120
|
+
|
|
121
|
+
### Default Template
|
|
122
|
+
|
|
123
|
+
Built-in template with:
|
|
124
|
+
- ImageView (left on iOS, right on Android)
|
|
125
|
+
- Title Label (left-aligned, black)
|
|
126
|
+
- Optional accessory icon
|
|
127
|
+
|
|
128
|
+
```xml
|
|
129
|
+
<ListView id="myList">
|
|
130
|
+
<ListSection>
|
|
131
|
+
<ListItem title="Title" image="icon.png" accessoryType="Ti.UI.LIST_ACCESSORY_TYPE_DISCLOSURE"/>
|
|
132
|
+
</ListSection>
|
|
133
|
+
</ListView>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Custom Templates
|
|
137
|
+
|
|
138
|
+
Create with `<Templates>` and `<ItemTemplate>`:
|
|
139
|
+
|
|
140
|
+
```xml
|
|
141
|
+
<ListView id="elementsList" defaultItemTemplate="elementTemplate">
|
|
142
|
+
<Templates>
|
|
143
|
+
<ItemTemplate name="elementTemplate">
|
|
144
|
+
<!-- Bindable elements with bindId -->
|
|
145
|
+
<Label bindId="symbol" id="symbol" />
|
|
146
|
+
<View id="atomProperties">
|
|
147
|
+
<Label bindId="name" id="name" />
|
|
148
|
+
<View id="secondLine">
|
|
149
|
+
<Label class="line2" bindId="number" id="number" />
|
|
150
|
+
<Label class="line2" bindId="mass" id="mass" />
|
|
151
|
+
</View>
|
|
152
|
+
</View>
|
|
153
|
+
<ImageView bindId="image" id="image" />
|
|
154
|
+
</ItemTemplate>
|
|
155
|
+
</Templates>
|
|
156
|
+
<ListSection>
|
|
157
|
+
<!-- Bind data using bindId:property syntax -->
|
|
158
|
+
<ListItem symbol:text="H" symbol:color="#090" name:text="Hydrogen" number:text="1" mass:text="1.00794"/>
|
|
159
|
+
</ListSection>
|
|
160
|
+
</ListView>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Multiple Templates
|
|
164
|
+
|
|
165
|
+
```xml
|
|
166
|
+
<ListView id="dynamicListView">
|
|
167
|
+
<Templates>
|
|
168
|
+
<ItemTemplate name="image_title" height="100">
|
|
169
|
+
<View layout="horizontal" left="15">
|
|
170
|
+
<ImageView bindId="image" id="image"/>
|
|
171
|
+
<Label bindId="label" id="label1"/>
|
|
172
|
+
</View>
|
|
173
|
+
</ItemTemplate>
|
|
174
|
+
<ItemTemplate name="title_only" height="50">
|
|
175
|
+
<View left="15">
|
|
176
|
+
<Label bindId="label"/>
|
|
177
|
+
</View>
|
|
178
|
+
</ItemTemplate>
|
|
179
|
+
</Templates>
|
|
180
|
+
<ListSection/>
|
|
181
|
+
</ListView>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Assign template per item:
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
const items = [
|
|
188
|
+
{
|
|
189
|
+
label: { text: "Full item" },
|
|
190
|
+
image: { image: "photo.png" },
|
|
191
|
+
template: "image_title" // Use this template
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
label: { text: "Text only" },
|
|
195
|
+
template: "title_only" // Use this template
|
|
196
|
+
}
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
$.dynamicListView.sections[0].setItems(items);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## 4. Data Binding
|
|
203
|
+
|
|
204
|
+
### Binding Syntax
|
|
205
|
+
|
|
206
|
+
**XML (Alloy)**: `bindId:property="value"`
|
|
207
|
+
**JavaScript**: `{ bindId: { property: value } }`
|
|
208
|
+
|
|
209
|
+
### Programmatic Binding with Custom Templates
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
const items = [
|
|
213
|
+
{
|
|
214
|
+
mass: { text: "1.00794" },
|
|
215
|
+
name: { text: "Hydrogen" },
|
|
216
|
+
number: { text: "1" },
|
|
217
|
+
symbol: { color: "#090", text: "H" }
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
mass: { text: "4.002602" },
|
|
221
|
+
name: { text: "Helium" },
|
|
222
|
+
number: { text: "2" },
|
|
223
|
+
symbol: { color: "#090", text: "He" }
|
|
224
|
+
}
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
$.elementsList.sections[0].setItems(items);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 5. Section Operations
|
|
231
|
+
|
|
232
|
+
### CRUD Methods
|
|
233
|
+
|
|
234
|
+
| Method | Description |
|
|
235
|
+
| ------------------------------------- | ------------------ |
|
|
236
|
+
| `setItems(items)` | Replace all items |
|
|
237
|
+
| `appendItems(items)` | Add to end |
|
|
238
|
+
| `insertItemsAt(index, items)` | Insert at position |
|
|
239
|
+
| `replaceItemsAt(index, count, items)` | Replace range |
|
|
240
|
+
| `deleteItemsAt(index, count)` | Delete range |
|
|
241
|
+
|
|
242
|
+
### Example Operations
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
const section = $.myList.sections[0];
|
|
246
|
+
|
|
247
|
+
// Replace all (clears first)
|
|
248
|
+
section.setItems(items);
|
|
249
|
+
|
|
250
|
+
// Append to end
|
|
251
|
+
section.appendItems(newItems);
|
|
252
|
+
|
|
253
|
+
// Insert at position 5
|
|
254
|
+
section.insertItemsAt(5, moreItems);
|
|
255
|
+
|
|
256
|
+
// Replace 3 items starting at index 2
|
|
257
|
+
section.replaceItemsAt(2, 3, replacementItems);
|
|
258
|
+
|
|
259
|
+
// Delete 2 items starting at index 10
|
|
260
|
+
section.deleteItemsAt(10, 2);
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## 6. Events
|
|
264
|
+
|
|
265
|
+
### Item Click
|
|
266
|
+
|
|
267
|
+
```xml
|
|
268
|
+
<ListView id="list" onItemclick="handleClick">
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
function handleClick(e) {
|
|
273
|
+
// e.sectionIndex: which section
|
|
274
|
+
// e.itemIndex: which item
|
|
275
|
+
// e.bindId: which template element (null if row clicked)
|
|
276
|
+
// e.itemId: custom itemId if set
|
|
277
|
+
|
|
278
|
+
const section = $.list.sections[e.sectionIndex];
|
|
279
|
+
const item = section.getItemAt(e.itemIndex);
|
|
280
|
+
|
|
281
|
+
// Update item
|
|
282
|
+
item.properties.title += " (clicked)";
|
|
283
|
+
item.properties.color = 'red';
|
|
284
|
+
section.updateItemAt(e.itemIndex, item);
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Marker Events (Infinite Scroll)
|
|
289
|
+
|
|
290
|
+
Markers act as "tripwires" for loading more data:
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
// Set initial marker at item 100
|
|
294
|
+
$.myList.setMarker({ sectionIndex: 0, itemIndex: 99 });
|
|
295
|
+
|
|
296
|
+
// Handle marker event
|
|
297
|
+
function markerReached(e) {
|
|
298
|
+
// Load more data
|
|
299
|
+
const moreData = loadNextPage();
|
|
300
|
+
|
|
301
|
+
// Append to list
|
|
302
|
+
e.section.appendItems(moreData);
|
|
303
|
+
|
|
304
|
+
// Set next marker
|
|
305
|
+
const nextMarker = e.itemIndex + moreData.length - 1;
|
|
306
|
+
$.myList.setMarker({ sectionIndex: e.sectionIndex, itemIndex: nextMarker });
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
$.myList.addEventListener('marker', markerReached);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Template Element Events
|
|
313
|
+
|
|
314
|
+
```xml
|
|
315
|
+
<ListView id="likeList" onItemclick="handleItemClick">
|
|
316
|
+
<Templates>
|
|
317
|
+
<ItemTemplate name="custom">
|
|
318
|
+
<Label bindId="label" left="15" />
|
|
319
|
+
<ImageView bindId="icon" right="15" />
|
|
320
|
+
</ItemTemplate>
|
|
321
|
+
</Templates>
|
|
322
|
+
<ListSection>
|
|
323
|
+
<ListItem label:text="Like me?" icon:image="star_grey.png" />
|
|
324
|
+
</ListSection>
|
|
325
|
+
</ListView>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
function handleItemClick(e) {
|
|
330
|
+
// Check which element was clicked
|
|
331
|
+
if (e.bindId === "icon") {
|
|
332
|
+
const item = e.section.getItemAt(e.itemIndex);
|
|
333
|
+
|
|
334
|
+
// Toggle image (update data, NOT e.source)
|
|
335
|
+
if (item.icon.image === "star_grey.png") {
|
|
336
|
+
item.icon.image = "star_gold.png";
|
|
337
|
+
} else {
|
|
338
|
+
item.icon.image = "star_grey.png";
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
e.section.updateItemAt(e.itemIndex, item);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## 7. Critical Performance Rules
|
|
347
|
+
|
|
348
|
+
### Rule 1: Avoid Ti.UI.SIZE in Templates
|
|
349
|
+
|
|
350
|
+
**BAD** - Causes jerky scrolling:
|
|
351
|
+
|
|
352
|
+
```xml
|
|
353
|
+
<ItemTemplate name="bad">
|
|
354
|
+
<Label bindId="title" height="Ti.UI.SIZE"/> <!-- DON'T -->
|
|
355
|
+
</ItemTemplate>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**GOOD** - Use fixed height or Ti.UI.FILL:
|
|
359
|
+
|
|
360
|
+
```xml
|
|
361
|
+
<ItemTemplate name="good">
|
|
362
|
+
<Label bindId="title" height="40"/> <!-- Fixed -->
|
|
363
|
+
</ItemTemplate>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Rule 2: Cannot Access Children Directly
|
|
367
|
+
|
|
368
|
+
Views are recycled. Always update via data:
|
|
369
|
+
|
|
370
|
+
**BAD**:
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
// DON'T - Will be lost when recycled
|
|
374
|
+
function handleClick(e) {
|
|
375
|
+
e.source.image = "star_gold.png";
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**GOOD**:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
// DO - Update the data item
|
|
383
|
+
function handleClick(e) {
|
|
384
|
+
const item = e.section.getItemAt(e.itemIndex);
|
|
385
|
+
item.icon.image = "star_gold.png";
|
|
386
|
+
e.section.updateItemAt(e.itemIndex, item);
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Rule 3: Minimize Template Count
|
|
391
|
+
|
|
392
|
+
Fewer templates = better native cell reuse:
|
|
393
|
+
|
|
394
|
+
**GOOD** - One template with conditional visibility:
|
|
395
|
+
|
|
396
|
+
```xml
|
|
397
|
+
<ItemTemplate name="flexible">
|
|
398
|
+
<ImageView bindId="icon"/>
|
|
399
|
+
<Label bindId="title"/>
|
|
400
|
+
<Label bindId="subtitle"/> <!-- Hidden if not needed -->
|
|
401
|
+
</ItemTemplate>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**BAD** - Multiple similar templates:
|
|
405
|
+
|
|
406
|
+
```xml
|
|
407
|
+
<ItemTemplate name="withIcon">...</ItemTemplate>
|
|
408
|
+
<ItemTemplate name="withoutIcon">...</ItemTemplate>
|
|
409
|
+
<ItemTemplate name="withSubtitle">...</ItemTemplate>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Rule 4: Use updateItemAt for Changes
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
// Get item data
|
|
416
|
+
const item = section.getItemAt(index);
|
|
417
|
+
|
|
418
|
+
// Modify properties
|
|
419
|
+
item.properties.backgroundColor = 'blue';
|
|
420
|
+
item.customField.text = 'Updated';
|
|
421
|
+
|
|
422
|
+
// Update in list
|
|
423
|
+
section.updateItemAt(index, item);
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Rule 5: Animations are Limited
|
|
427
|
+
|
|
428
|
+
ListView items have limited animation support. For complex animations, consider TableView.
|
|
429
|
+
|
|
430
|
+
## 8. iOS Action Items (Swipe Actions)
|
|
431
|
+
|
|
432
|
+
```javascript
|
|
433
|
+
const section = $.myList.sections[0];
|
|
434
|
+
|
|
435
|
+
// Define edit actions
|
|
436
|
+
const deleteAction = Ti.UI.iOS.createListViewDeleteOptions({
|
|
437
|
+
title: 'Delete'
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const moreAction = Ti.UI.iOS.createListViewEditAction({
|
|
441
|
+
title: 'More',
|
|
442
|
+
backgroundColor: 'blue',
|
|
443
|
+
style: Ti.UI.iOS.LIST_VIEW_EDIT_ACTION_STYLE_NORMAL
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// Enable editing
|
|
447
|
+
section.editActions = [deleteAction, moreAction];
|
|
448
|
+
section.canEdit = true;
|
|
449
|
+
|
|
450
|
+
// Handle actions
|
|
451
|
+
$.myList.addEventListener('editaction', (e) => {
|
|
452
|
+
if (e.action === deleteAction) {
|
|
453
|
+
section.deleteItemsAt(e.itemIndex, 1);
|
|
454
|
+
} else if (e.action === moreAction) {
|
|
455
|
+
// Handle more action
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## 9. Search
|
|
461
|
+
|
|
462
|
+
```javascript
|
|
463
|
+
const searchView = Ti.UI.createSearchBar({
|
|
464
|
+
showCancel: true
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
$.myList.searchView = searchView;
|
|
468
|
+
|
|
469
|
+
// Mark searchable text in items
|
|
470
|
+
const items = [
|
|
471
|
+
{
|
|
472
|
+
properties: {
|
|
473
|
+
title: "Apple",
|
|
474
|
+
searchableText: "Apple fruit red delicious" // Extra keywords
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
];
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## 10. Performance Best Practices
|
|
481
|
+
|
|
482
|
+
### DO:
|
|
483
|
+
- Use fixed heights in templates
|
|
484
|
+
- Minimize number of templates
|
|
485
|
+
- Use `updateItemAt()` for changes
|
|
486
|
+
- Cache `sections[0]` reference
|
|
487
|
+
- Use markers for infinite scroll
|
|
488
|
+
- Test with real device data volumes
|
|
489
|
+
|
|
490
|
+
### DON'T:
|
|
491
|
+
- Use `Ti.UI.SIZE` for row dimensions
|
|
492
|
+
- Access `e.source` in itemclick events
|
|
493
|
+
- Create too many similar templates
|
|
494
|
+
- Add complex animations to list items
|
|
495
|
+
- Ignore the "recycled" nature of views
|
|
496
|
+
|
|
497
|
+
## 11. Transitioning from TableView
|
|
498
|
+
|
|
499
|
+
### Core Logic Differences
|
|
500
|
+
|
|
501
|
+
| TableView | ListView |
|
|
502
|
+
| -------------------- | ---------------------------- |
|
|
503
|
+
| TableViewRow | ListItem (Virtual) |
|
|
504
|
+
| `add()` views to row | `childTemplates` in Template |
|
|
505
|
+
| `data` property | `sections` property |
|
|
506
|
+
| Direct child access | Bound data updates only |
|
|
507
|
+
| `appendRow()` | `appendItems()` |
|
|
508
|
+
| `updateRow()` | `updateItemAt()` |
|
|
509
|
+
| `deleteRow()` | `deleteItemsAt()` |
|
|
510
|
+
|
|
511
|
+
### API Differences
|
|
512
|
+
|
|
513
|
+
**Properties NOT available for ListItem**:
|
|
514
|
+
- `accessibilityLabel`, `className`, `editable`, `hasCheck`, `hasChild`, `hasDetail`, `leftImage`, `moveable`, `rightImage`.
|
|
515
|
+
- *Alternatives*: Use `accessoryType` for indicators, and `image` or custom templates for images.
|
|
516
|
+
|
|
517
|
+
**TableViewSection methods NOT supported by ListSection**:
|
|
518
|
+
- `add`, `remove`, `rowAtIndex`.
|
|
519
|
+
- *Alternatives*: Use `getItemAt` and `appendItems`/`deleteItemsAt`.
|
|
520
|
+
|
|
521
|
+
**TableView methods NOT available to ListView**:
|
|
522
|
+
- `appendRow`, `deleteRow`, `deselectRow`, `insertRowAfter`, `insertRowBefore`, `selectRow`, `updateRow`, `scrollToIndex`.
|
|
523
|
+
- *Alternatives*: Use `scrollToItem` and `selectItem` (iOS). For row manipulation, use the containing `ListSection`.
|
|
524
|
+
|
|
525
|
+
## 12. Common Patterns
|
|
526
|
+
|
|
527
|
+
### Infinite Scroll with Markers
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
const PAGE_SIZE = 25;
|
|
531
|
+
let currentPage = 0;
|
|
532
|
+
|
|
533
|
+
function loadPage(page) {
|
|
534
|
+
const data = fetchDataFromAPI(page);
|
|
535
|
+
|
|
536
|
+
if (page === 0) {
|
|
537
|
+
$.myList.sections[0].setItems(data);
|
|
538
|
+
} else {
|
|
539
|
+
$.myList.sections[0].appendItems(data);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Set marker for next page
|
|
543
|
+
const markerIndex = (page * PAGE_SIZE) + data.length - 1;
|
|
544
|
+
$.myList.setMarker({ sectionIndex: 0, itemIndex: markerIndex });
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Initial load
|
|
548
|
+
loadPage(0);
|
|
549
|
+
|
|
550
|
+
// Marker handler
|
|
551
|
+
$.myList.addEventListener('marker', (e) => {
|
|
552
|
+
currentPage++;
|
|
553
|
+
loadPage(currentPage);
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Multiple Selection
|
|
558
|
+
|
|
559
|
+
```javascript
|
|
560
|
+
const selectedItems = {};
|
|
561
|
+
|
|
562
|
+
$.myList.addEventListener('itemclick', (e) => {
|
|
563
|
+
const item = e.section.getItemAt(e.itemIndex);
|
|
564
|
+
const key = `${e.sectionIndex}-${e.itemIndex}`;
|
|
565
|
+
|
|
566
|
+
if (selectedItems[key]) {
|
|
567
|
+
// Deselect
|
|
568
|
+
delete selectedItems[key];
|
|
569
|
+
item.properties.accessoryType = Ti.UI.LIST_ACCESSORY_TYPE_NONE;
|
|
570
|
+
} else {
|
|
571
|
+
// Select
|
|
572
|
+
selectedItems[key] = item;
|
|
573
|
+
item.properties.accessoryType = Ti.UI.LIST_ACCESSORY_TYPE_CHECKMARK;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
e.section.updateItemAt(e.itemIndex, item);
|
|
577
|
+
});
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Section Index (A-Z)
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
$.myList.sectionIndexTitles = ["A", "B", "C", ...];
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## 13. Platform Differences
|
|
587
|
+
|
|
588
|
+
### iOS vs Android
|
|
589
|
+
|
|
590
|
+
| Feature | iOS | Android |
|
|
591
|
+
| ---------------------- | ------------ | ------------- |
|
|
592
|
+
| Action items (swipe) | Full support | Not supported |
|
|
593
|
+
| Section index titles | Full support | Not supported |
|
|
594
|
+
| Search bar | Full support | Full support |
|
|
595
|
+
| Default template image | Left side | Right side |
|
|
596
|
+
| cacheSize property | Supported | Not supported |
|
|
597
|
+
|
|
598
|
+
### cacheSize (iOS)
|
|
599
|
+
|
|
600
|
+
```javascript
|
|
601
|
+
// Number of views to pre-render offscreen
|
|
602
|
+
$.myList.cacheSize = 3; // Default
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## 14. Debugging
|
|
606
|
+
|
|
607
|
+
### Common Issues
|
|
608
|
+
|
|
609
|
+
**Problem**: Jerky scrolling
|
|
610
|
+
**Solution**: Remove `Ti.UI.SIZE` from templates
|
|
611
|
+
|
|
612
|
+
**Problem**: Data changes not visible
|
|
613
|
+
**Solution**: Use `updateItemAt()` instead of modifying views
|
|
614
|
+
|
|
615
|
+
**Problem**: Event not firing on template element
|
|
616
|
+
**Solution**: Check `bindId` in event handler
|
|
617
|
+
|
|
618
|
+
**Problem**: Wrong item updated
|
|
619
|
+
**Solution**: Use `e.section.getItemAt(e.itemIndex)` not global reference
|