@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,727 +0,0 @@
|
|
|
1
|
-
# Android UI components and conventions
|
|
2
|
-
|
|
3
|
-
<!-- TOC-START -->
|
|
4
|
-
## Contents
|
|
5
|
-
|
|
6
|
-
- [1. Action bar](#1-action-bar)
|
|
7
|
-
- [2. Android themes](#2-android-themes)
|
|
8
|
-
- [3. Options menu](#3-options-menu)
|
|
9
|
-
- [4. Status bar notifications](#4-status-bar-notifications)
|
|
10
|
-
- [5. Progress bars](#5-progress-bars)
|
|
11
|
-
- [6. Tab groups and tabs](#6-tab-groups-and-tabs)
|
|
12
|
-
- [7. Hardware back button handling](#7-hardware-back-button-handling)
|
|
13
|
-
- [8. Notification drawer](#8-notification-drawer)
|
|
14
|
-
- [9. Android UI conventions](#9-android-ui-conventions)
|
|
15
|
-
- [10. Material design components](#10-material-design-components)
|
|
16
|
-
- [11. Toast notifications](#11-toast-notifications)
|
|
17
|
-
- [12. HTML labels and linkification](#12-html-labels-and-linkification)
|
|
18
|
-
- [13. Nine-patch images](#13-nine-patch-images)
|
|
19
|
-
- [Best practices](#best-practices)
|
|
20
|
-
|
|
21
|
-
<!-- TOC-END -->
|
|
22
|
-
|
|
23
|
-
## 1. Action bar
|
|
24
|
-
|
|
25
|
-
### Overview
|
|
26
|
-
|
|
27
|
-
The action bar sits at the top of the screen. It shows actions, navigation, and app branding.
|
|
28
|
-
|
|
29
|
-
### Enable the action bar
|
|
30
|
-
|
|
31
|
-
In `tiapp.xml`:
|
|
32
|
-
|
|
33
|
-
```xml
|
|
34
|
-
<android>
|
|
35
|
-
<manifest>
|
|
36
|
-
<application>
|
|
37
|
-
<activity android:name=".MyActivity"
|
|
38
|
-
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode">
|
|
39
|
-
<intent-filter>
|
|
40
|
-
<action android:name="android.intent.action.MAIN" />
|
|
41
|
-
<category android:name="android.intent.category.LAUNCHER" />
|
|
42
|
-
</intent-filter>
|
|
43
|
-
</activity>
|
|
44
|
-
</application>
|
|
45
|
-
</manifest>
|
|
46
|
-
</android>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Create the action bar (programmatic)
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
const activity = Ti.Android.currentActivity;
|
|
53
|
-
|
|
54
|
-
activity.onCreateOptionsMenu = (e) => {
|
|
55
|
-
const menu = e.menu;
|
|
56
|
-
|
|
57
|
-
// Add "Refresh" action
|
|
58
|
-
const refreshItem = menu.add({
|
|
59
|
-
title: 'Refresh',
|
|
60
|
-
icon: Ti.Android.R.drawable.ic_menu_refresh,
|
|
61
|
-
showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
|
|
62
|
-
itemId: 1
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Add "Settings" action
|
|
66
|
-
const settingsItem = menu.add({
|
|
67
|
-
title: 'Settings',
|
|
68
|
-
icon: Ti.Android.R.drawable.ic_menu_preferences,
|
|
69
|
-
showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
|
|
70
|
-
itemId: 2
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Add "Search" action (shown as collapsible action view)
|
|
74
|
-
const searchItem = menu.add({
|
|
75
|
-
title: 'Search',
|
|
76
|
-
icon: Ti.Android.R.drawable.ic_menu_search,
|
|
77
|
-
actionView: Ti.UI.createSearchBar({
|
|
78
|
-
showCancel: true
|
|
79
|
-
}),
|
|
80
|
-
itemId: 3,
|
|
81
|
-
expandActionView: Ti.Android.COLLAPSE_ACTION_VIEW_IF_ROOM
|
|
82
|
-
});
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
activity.onOptionsItemSelected = (e) => {
|
|
86
|
-
switch (e.itemId) {
|
|
87
|
-
case 1:
|
|
88
|
-
refreshData();
|
|
89
|
-
return true;
|
|
90
|
-
case 2:
|
|
91
|
-
openSettings();
|
|
92
|
-
return true;
|
|
93
|
-
case 3:
|
|
94
|
-
// Search action - handled by SearchBar
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
return false;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
activity.onPrepareOptionsMenu = (e) => {
|
|
101
|
-
// Update menu items before showing
|
|
102
|
-
const menu = e.menu;
|
|
103
|
-
// Modify items based on state
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// Force menu recreation (useful when menu items need to change dynamically)
|
|
107
|
-
activity.invalidateOptionsMenu();
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Action bar properties
|
|
111
|
-
|
|
112
|
-
```javascript
|
|
113
|
-
const activity = Ti.Android.currentActivity;
|
|
114
|
-
const actionBar = activity.actionBar;
|
|
115
|
-
|
|
116
|
-
// Show the "up" affordance arrow next to the home icon
|
|
117
|
-
actionBar.displayHomeAsUp = true;
|
|
118
|
-
|
|
119
|
-
// Customize icon and logo
|
|
120
|
-
actionBar.icon = '/images/actionbar_icon.png';
|
|
121
|
-
actionBar.logo = '/images/actionbar_logo.png';
|
|
122
|
-
|
|
123
|
-
// Handle home icon/logo clicks
|
|
124
|
-
actionBar.onHomeIconItemSelected = () => {
|
|
125
|
-
// Navigate up or open navigation drawer
|
|
126
|
-
win.close();
|
|
127
|
-
};
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Refresh the options menu
|
|
131
|
-
|
|
132
|
-
Call `activity.invalidateOptionsMenu()` to force `onCreateOptionsMenu` to run again. This is useful when menu items need to change at runtime, for example after a tab switch or a state change.
|
|
133
|
-
|
|
134
|
-
### Action bar with app icon
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
const activity = Ti.Android.currentActivity;
|
|
138
|
-
|
|
139
|
-
activity.onCreateOptionsMenu = (e) => {
|
|
140
|
-
const menu = e.menu;
|
|
141
|
-
|
|
142
|
-
// App icon on left
|
|
143
|
-
const appIcon = menu.addMenuItem({
|
|
144
|
-
title: 'My App',
|
|
145
|
-
icon: Ti.App.Android.R.drawable.app_icon,
|
|
146
|
-
itemId: 0
|
|
147
|
-
});
|
|
148
|
-
appIcon.setEnabled(false); // Not clickable, just branding
|
|
149
|
-
};
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Action view (custom layout)
|
|
153
|
-
|
|
154
|
-
```javascript
|
|
155
|
-
activity.onCreateOptionsMenu = (e) => {
|
|
156
|
-
const menu = e.menu;
|
|
157
|
-
|
|
158
|
-
// Custom action view with button
|
|
159
|
-
const actionView = Ti.UI.createView({
|
|
160
|
-
height: Ti.UI.FILL,
|
|
161
|
-
backgroundColor: '#4CAF50',
|
|
162
|
-
layout: 'horizontal'
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
const actionButton = Ti.UI.createButton({
|
|
166
|
-
title: 'Action',
|
|
167
|
-
color: 'white',
|
|
168
|
-
height: Ti.UI.FILL,
|
|
169
|
-
width: Ti.UI.SIZE
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
actionButton.addEventListener('click', () => {
|
|
173
|
-
performAction();
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
actionView.add(actionButton);
|
|
177
|
-
|
|
178
|
-
const actionItem = menu.add({
|
|
179
|
-
title: 'Custom',
|
|
180
|
-
actionView: actionView,
|
|
181
|
-
showAsAction: Ti.Android.SHOW_AS_ACTION_ALWAYS,
|
|
182
|
-
itemId: 10
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## 2. Android themes
|
|
188
|
-
|
|
189
|
-
### Overview
|
|
190
|
-
|
|
191
|
-
Themes control the visual style of Android apps. Titanium 10.0.0+ requires material-based themes.
|
|
192
|
-
|
|
193
|
-
### Titanium material themes (SDK 10.0.0+)
|
|
194
|
-
|
|
195
|
-
| Theme | Description |
|
|
196
|
-
| ------------------------------------ | ------------------------------------- |
|
|
197
|
-
| `Theme.Titanium.DayNight` | Light/dark switching (default 10.0.x) |
|
|
198
|
-
| `Theme.Titanium.DayNight.NoTitleBar` | No action bar |
|
|
199
|
-
| `Theme.Titanium.DayNight.Fullscreen` | No action bar or status bar |
|
|
200
|
-
| `Theme.Titanium.DayNight.Solid` | Seamless background (default 10.1.0+) |
|
|
201
|
-
| `Theme.Titanium.Dark` | Dark only |
|
|
202
|
-
| `Theme.Titanium.Light` | Light only |
|
|
203
|
-
| `Theme.AppDerived.NoTitleBar` | Inherits app theme, no action bar |
|
|
204
|
-
| `Theme.AppDerived.Fullscreen` | Inherits app theme, fullscreen |
|
|
205
|
-
| `Theme.AppDerived.Translucent` | Transparent background |
|
|
206
|
-
|
|
207
|
-
### Material 3 themes (SDK 12.0.0+)
|
|
208
|
-
|
|
209
|
-
```xml
|
|
210
|
-
<!-- tiapp.xml -->
|
|
211
|
-
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
212
|
-
<manifest>
|
|
213
|
-
<application android:theme="@style/Theme.Titanium.Material3.DayNight"/>
|
|
214
|
-
</manifest>
|
|
215
|
-
</android>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
| Theme | Description |
|
|
219
|
-
| ---------------------------------------------- | ------------------------------ |
|
|
220
|
-
| `Theme.Titanium.Material3.DayNight` | Material 3 with dynamic colors |
|
|
221
|
-
| `Theme.Titanium.Material3.DayNight.NoTitleBar` | No action bar |
|
|
222
|
-
| `Theme.Titanium.Material3.DayNight.Fullscreen` | No action/status bar |
|
|
223
|
-
|
|
224
|
-
Custom Material 3 theme:
|
|
225
|
-
|
|
226
|
-
```xml
|
|
227
|
-
<!-- platform/android/res/values/mytheme.xml -->
|
|
228
|
-
<resources>
|
|
229
|
-
<style name="AppTheme" parent="Theme.Material3.DynamicColors.DayNight"/>
|
|
230
|
-
</resources>
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Apply themes
|
|
234
|
-
|
|
235
|
-
Global (`tiapp.xml`):
|
|
236
|
-
|
|
237
|
-
```xml
|
|
238
|
-
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
239
|
-
<manifest>
|
|
240
|
-
<application android:theme="@style/Theme.Titanium.DayNight.Solid"/>
|
|
241
|
-
</manifest>
|
|
242
|
-
</android>
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Per-window (JavaScript):
|
|
246
|
-
|
|
247
|
-
```javascript
|
|
248
|
-
const win = Ti.UI.createWindow({
|
|
249
|
-
theme: 'Theme.AppDerived.Fullscreen'
|
|
250
|
-
});
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Custom theme
|
|
254
|
-
|
|
255
|
-
```xml
|
|
256
|
-
<!-- platform/android/res/values/mytheme.xml -->
|
|
257
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
258
|
-
<resources>
|
|
259
|
-
<!-- SDK 10.0.0+ -->
|
|
260
|
-
<style name="Theme.MyTheme" parent="@style/Theme.Titanium.Light">
|
|
261
|
-
<item name="colorPrimary">#c91326</item>
|
|
262
|
-
<item name="colorPrimaryDark">#900000</item>
|
|
263
|
-
<item name="colorAccent">#c91326</item>
|
|
264
|
-
<item name="android:textColorPrimary">#000000</item>
|
|
265
|
-
<item name="android:statusBarColor">#c91326</item>
|
|
266
|
-
<item name="android:navigationBarColor">#c91326</item>
|
|
267
|
-
</style>
|
|
268
|
-
</resources>
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Dark theme variant (`values-night/`):
|
|
272
|
-
|
|
273
|
-
```xml
|
|
274
|
-
<!-- platform/android/res/values-night/mytheme.xml -->
|
|
275
|
-
<resources>
|
|
276
|
-
<style name="Theme.MyTheme" parent="@style/Theme.Titanium.Dark">
|
|
277
|
-
<item name="colorPrimary">#d5544b</item>
|
|
278
|
-
<item name="colorAccent">#d5544b</item>
|
|
279
|
-
</style>
|
|
280
|
-
</resources>
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### Color palette attributes
|
|
284
|
-
|
|
285
|
-
| Attribute | Description |
|
|
286
|
-
| ---------------------------- | -------------------------- |
|
|
287
|
-
| `colorPrimary` | Action bar color |
|
|
288
|
-
| `colorPrimaryDark` | Status bar color (API 21+) |
|
|
289
|
-
| `colorAccent` | Control accent color |
|
|
290
|
-
| `colorControlNormal` | Inactive control color |
|
|
291
|
-
| `colorControlActivated` | Active control color |
|
|
292
|
-
| `colorControlHighlight` | Click highlight (API 21+) |
|
|
293
|
-
| `android:navigationBarColor` | Bottom nav bar (API 21+) |
|
|
294
|
-
| `android:textColorPrimary` | Primary text color |
|
|
295
|
-
|
|
296
|
-
### Hide the action bar
|
|
297
|
-
|
|
298
|
-
Via theme (recommended):
|
|
299
|
-
|
|
300
|
-
```xml
|
|
301
|
-
<application android:theme="@style/Theme.AppDerived.NoTitleBar"/>
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
Via JavaScript:
|
|
305
|
-
|
|
306
|
-
```javascript
|
|
307
|
-
const win = Ti.UI.createWindow({
|
|
308
|
-
theme: 'Theme.AppDerived.NoTitleBar'
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
// Or hide after open
|
|
312
|
-
win.addEventListener('open', () => {
|
|
313
|
-
win.activity.actionBar.hide();
|
|
314
|
-
});
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### Theme requirements
|
|
318
|
-
|
|
319
|
-
Warning: SDK 10.0.0+ requires material-based themes. Using non-material themes will cause a runtime error. Do not name your custom theme file `theme.xml`. This will overwrite Titanium's built-in theme file. Use names like `mytheme.xml`.
|
|
320
|
-
|
|
321
|
-
- SDK 10.0.0+ requires material-based themes (runtime error otherwise)
|
|
322
|
-
- Place custom themes in `platform/android/res/values/`
|
|
323
|
-
- Do not name the file `theme.xml` (overwrites Titanium's)
|
|
324
|
-
- Use `values-v<api>` for version-specific themes
|
|
325
|
-
- Use `values-night` for dark mode variants
|
|
326
|
-
|
|
327
|
-
## 3. Options menu
|
|
328
|
-
|
|
329
|
-
### Legacy options menu
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
const activity = Ti.Android.currentActivity;
|
|
333
|
-
|
|
334
|
-
activity.onCreateOptionsMenu = (e) => {
|
|
335
|
-
const menu = e.menu;
|
|
336
|
-
|
|
337
|
-
// Add items
|
|
338
|
-
menu.add({ title: 'Option 1', itemId: 1 });
|
|
339
|
-
menu.add({ title: 'Option 2', itemId: 2 });
|
|
340
|
-
menu.add({ title: 'Option 3', itemId: 3 });
|
|
341
|
-
menu.add({ title: 'Option 4', itemId: 4 });
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
activity.onOptionsItemSelected = (e) => {
|
|
345
|
-
switch (e.itemId) {
|
|
346
|
-
case 1:
|
|
347
|
-
handleOption1();
|
|
348
|
-
return true;
|
|
349
|
-
// ... other cases
|
|
350
|
-
}
|
|
351
|
-
return false;
|
|
352
|
-
};
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### Context menu (long press)
|
|
356
|
-
|
|
357
|
-
```javascript
|
|
358
|
-
const view = Ti.UI.createView({
|
|
359
|
-
backgroundColor: 'white'
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
view.addEventListener('longpress', (e) => {
|
|
363
|
-
// Register for context menu
|
|
364
|
-
registerForContextMenu();
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
function registerForContextMenu() {
|
|
368
|
-
// Android: Create and register for context menu
|
|
369
|
-
// This is typically done in tiapp.xml with intent filters
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
## 4. Status bar notifications
|
|
374
|
-
|
|
375
|
-
### Notifications
|
|
376
|
-
|
|
377
|
-
```javascript
|
|
378
|
-
// Create notification
|
|
379
|
-
const notification = Ti.Android.createNotification({
|
|
380
|
-
contentTitle: 'New Message',
|
|
381
|
-
contentText: 'You have a new message',
|
|
382
|
-
contentIntent: Ti.Android.createIntent({
|
|
383
|
-
url: 'myapp://message/123'
|
|
384
|
-
}),
|
|
385
|
-
number: 1, // Notification number
|
|
386
|
-
sound: Ti.App.Android.R.drawable.app_icon, // Notification sound
|
|
387
|
-
defaults: 0, // Flags (LED, vibration, etc.)
|
|
388
|
-
flags: Ti.Android.FLAG_AUTO_CANCEL | Ti.Android.FLAG_SHOW_LIGHTS
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
// Show notification
|
|
392
|
-
Ti.Android.NotificationManager.notify(1, notification);
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
### Notification channels (Android 8.0+)
|
|
396
|
-
|
|
397
|
-
```javascript
|
|
398
|
-
// Create notification channel for Android 8.0+
|
|
399
|
-
const channel = Ti.Android.createNotificationChannel({
|
|
400
|
-
id: 'my_channel_id',
|
|
401
|
-
name: 'My Channel',
|
|
402
|
-
importance: Ti.Android.NOTIFICATION_IMPORTANCE_HIGH,
|
|
403
|
-
lightColor: '#FF0000',
|
|
404
|
-
enableLights: true,
|
|
405
|
-
showBadge: true,
|
|
406
|
-
sound: Ti.Filesystem.getFile('sound.mp3')
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
Ti.Android.NotificationManager.createNotificationChannel(channel);
|
|
410
|
-
|
|
411
|
-
// Use channel in notification
|
|
412
|
-
const notification = Ti.Android.createNotification({
|
|
413
|
-
channelId: 'my_channel_id',
|
|
414
|
-
contentTitle: 'Channel Test',
|
|
415
|
-
contentText: 'Testing notification channels',
|
|
416
|
-
// ... other properties
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
Ti.Android.NotificationManager.notify(1, notification);
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### Clear notifications
|
|
423
|
-
|
|
424
|
-
```javascript
|
|
425
|
-
// Cancel specific notification
|
|
426
|
-
Ti.Android.NotificationManager.cancel(1);
|
|
427
|
-
|
|
428
|
-
// Clear all notifications
|
|
429
|
-
Ti.Android.NotificationManager.cancelAll();
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
## 5. Progress bars
|
|
433
|
-
|
|
434
|
-
### Horizontal progress bar
|
|
435
|
-
|
|
436
|
-
```javascript
|
|
437
|
-
const progressBar = Ti.UI.createProgressBar({
|
|
438
|
-
min: 0,
|
|
439
|
-
max: 100,
|
|
440
|
-
value: 0,
|
|
441
|
-
width: Ti.UI.FILL,
|
|
442
|
-
height: Ti.UI.SIZE,
|
|
443
|
-
style: Ti.UI.Android.PROGRESS_BAR_STYLE_HORIZONTAL,
|
|
444
|
-
top: 10
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
// Update progress
|
|
448
|
-
progressBar.value = 50;
|
|
449
|
-
|
|
450
|
-
// Indeterminate progress
|
|
451
|
-
progressBar.message = 'Loading...';
|
|
452
|
-
progressBar.show();
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### Spinner (indeterminate progress)
|
|
456
|
-
|
|
457
|
-
```javascript
|
|
458
|
-
const activityIndicator = Ti.UI.createActivityIndicator({
|
|
459
|
-
message: 'Loading...',
|
|
460
|
-
location: Ti.UI.Android.ACTIVITY_INDICATOR_DIALOG,
|
|
461
|
-
cancelable: false
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
activityIndicator.show();
|
|
465
|
-
|
|
466
|
-
// Later:
|
|
467
|
-
activityIndicator.hide();
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
## 6. Tab groups and tabs
|
|
471
|
-
|
|
472
|
-
### Native Android tabs
|
|
473
|
-
|
|
474
|
-
```javascript
|
|
475
|
-
const tabGroup = Ti.UI.createTabGroup({
|
|
476
|
-
tabs: [tab1, tab2, tab3]
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
tabGroup.addEventListener('open', (e) => {
|
|
480
|
-
Ti.API.info(`Tab opened: ${e.index} (${e.tab.title})`);
|
|
481
|
-
});
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
### Tab badges
|
|
485
|
-
|
|
486
|
-
```javascript
|
|
487
|
-
const tab = Titanium.UI.createTab({
|
|
488
|
-
title: 'Inbox',
|
|
489
|
-
window: winInbox,
|
|
490
|
-
icon: Ti.Android.R.drawable.ic_menu_info
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
// Set badge (number)
|
|
494
|
-
tab.badge = 5;
|
|
495
|
-
|
|
496
|
-
// Clear badge
|
|
497
|
-
tab.badge = null; // or tab.setBadge(null);
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
## 7. Hardware back button handling
|
|
501
|
-
|
|
502
|
-
### Handle back button
|
|
503
|
-
|
|
504
|
-
```javascript
|
|
505
|
-
const win = Ti.UI.createWindow();
|
|
506
|
-
|
|
507
|
-
win.addEventListener('androidback', (e) => {
|
|
508
|
-
e.cancelBubble = true; // Prevent default behavior
|
|
509
|
-
|
|
510
|
-
// Check if can go back
|
|
511
|
-
if (canGoBack()) {
|
|
512
|
-
closeCurrentWindow();
|
|
513
|
-
} else {
|
|
514
|
-
showExitConfirmation();
|
|
515
|
-
}
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
function canGoBack() {
|
|
519
|
-
// Your logic here
|
|
520
|
-
return true; // or false
|
|
521
|
-
}
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
### Exit confirmation dialog
|
|
525
|
-
|
|
526
|
-
```javascript
|
|
527
|
-
function showExitConfirmation() {
|
|
528
|
-
const dialog = Ti.UI.createAlertDialog({
|
|
529
|
-
title: 'Exit?',
|
|
530
|
-
message: 'Do you want to exit?',
|
|
531
|
-
buttonNames: ['Yes', 'No'],
|
|
532
|
-
cancel: 1
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
dialog.addEventListener('click', (e) => {
|
|
536
|
-
if (e.index === 0) {
|
|
537
|
-
const activity = Ti.Android.currentActivity;
|
|
538
|
-
activity.finish(); // Close app
|
|
539
|
-
}
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
dialog.show();
|
|
543
|
-
}
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
## 8. Notification drawer
|
|
547
|
-
|
|
548
|
-
### Display notification
|
|
549
|
-
|
|
550
|
-
```javascript
|
|
551
|
-
const notification = Ti.Android.createNotification({
|
|
552
|
-
contentTitle: 'Download Complete',
|
|
553
|
-
contentText: 'Your file has been downloaded',
|
|
554
|
-
contentIntent: Ti.Android.createIntent({
|
|
555
|
-
url: 'myapp://download/complete'
|
|
556
|
-
}),
|
|
557
|
-
largeIcon: Ti.App.Android.R.drawable.app_icon,
|
|
558
|
-
bigTextStyle: { bold: true, italic: false }
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
Ti.Android.NotificationManager.notify(1, notification);
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
## 9. Android UI conventions
|
|
565
|
-
|
|
566
|
-
### Back button behavior
|
|
567
|
-
|
|
568
|
-
Standard Android conventions:
|
|
569
|
-
- Back button = navigate back in hierarchy
|
|
570
|
-
- Long press back = show recent apps menu (system behavior)
|
|
571
|
-
- Apps should handle back button unless:
|
|
572
|
-
|
|
573
|
-
1. It's the root activity (app would exit)
|
|
574
|
-
2. User is in a task that shouldn't be interrupted
|
|
575
|
-
3. Confirmation needed (destructive action)
|
|
576
|
-
|
|
577
|
-
### Up and down navigation
|
|
578
|
-
|
|
579
|
-
Traditional Android navigation uses:
|
|
580
|
-
- Up button = navigate up in hierarchy
|
|
581
|
-
- Menu button = show options menu
|
|
582
|
-
- Home button = go to home (backgrounds app)
|
|
583
|
-
|
|
584
|
-
Modern apps may:
|
|
585
|
-
- Use Navigation Component (Jetpack)
|
|
586
|
-
- Use up button for a back-style pattern
|
|
587
|
-
- Implement custom up navigation
|
|
588
|
-
|
|
589
|
-
### App shortcuts
|
|
590
|
-
|
|
591
|
-
Android 7.1+ app shortcuts:
|
|
592
|
-
|
|
593
|
-
```xml
|
|
594
|
-
<activity
|
|
595
|
-
android:name=".MainActivity"
|
|
596
|
-
android:launchMode="singleTask">
|
|
597
|
-
<!-- Define shortcuts -->
|
|
598
|
-
<intent-filter>
|
|
599
|
-
<action android:name="android.intent.action.VIEW" />
|
|
600
|
-
<category android:name="android.intent.category.DEFAULT" />
|
|
601
|
-
<data android:scheme="myapp" />
|
|
602
|
-
</intent-filter>
|
|
603
|
-
</activity>
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
## 10. Material design components
|
|
607
|
-
|
|
608
|
-
### Using AppCompat v7
|
|
609
|
-
|
|
610
|
-
```xml
|
|
611
|
-
<android>
|
|
612
|
-
<manifest>
|
|
613
|
-
<application>
|
|
614
|
-
<!-- Use AppCompat for Material Design support -->
|
|
615
|
-
<meta-data android:name="android:theme"
|
|
616
|
-
android:resource="@style/Theme.AppCompat.Light" />
|
|
617
|
-
</application>
|
|
618
|
-
</manifest>
|
|
619
|
-
</android>
|
|
620
|
-
```
|
|
621
|
-
|
|
622
|
-
### Material design components
|
|
623
|
-
|
|
624
|
-
- `Toolbar` - Replaces action bar (recommended)
|
|
625
|
-
- `CardView` - Cards with elevation
|
|
626
|
-
- `RecyclerView` - Advanced list component
|
|
627
|
-
- `CoordinatorLayout` - Complex layout coordination
|
|
628
|
-
- `TextInputLayout` - Floating label hints
|
|
629
|
-
- `FloatingActionButton` - Circular action button
|
|
630
|
-
|
|
631
|
-
These can be accessed via Hyperloop or custom modules.
|
|
632
|
-
|
|
633
|
-
## 11. Toast notifications
|
|
634
|
-
|
|
635
|
-
Toast notifications display brief messages at the bottom of the screen that automatically disappear.
|
|
636
|
-
|
|
637
|
-
```javascript
|
|
638
|
-
const toast = Ti.UI.createNotification({
|
|
639
|
-
message: 'Item saved successfully',
|
|
640
|
-
duration: Ti.UI.NOTIFICATION_DURATION_LONG
|
|
641
|
-
});
|
|
642
|
-
toast.show();
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
### Positioning
|
|
646
|
-
|
|
647
|
-
Use `offsetX` and `offsetY` to reposition the toast from its default location:
|
|
648
|
-
|
|
649
|
-
```javascript
|
|
650
|
-
const toast = Ti.UI.createNotification({
|
|
651
|
-
message: 'Custom position',
|
|
652
|
-
duration: Ti.UI.NOTIFICATION_DURATION_SHORT,
|
|
653
|
-
offsetX: 0,
|
|
654
|
-
offsetY: 100
|
|
655
|
-
});
|
|
656
|
-
toast.show();
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
Duration options:
|
|
660
|
-
- `Ti.UI.NOTIFICATION_DURATION_SHORT` - Short display time
|
|
661
|
-
- `Ti.UI.NOTIFICATION_DURATION_LONG` - Longer display time
|
|
662
|
-
|
|
663
|
-
## 12. HTML labels and linkification
|
|
664
|
-
|
|
665
|
-
### HTML content in labels
|
|
666
|
-
|
|
667
|
-
Use the `html` property on labels to render inline HTML content:
|
|
668
|
-
|
|
669
|
-
```javascript
|
|
670
|
-
const label = Ti.UI.createLabel({
|
|
671
|
-
html: '<b>Bold</b> and <i>italic</i> text',
|
|
672
|
-
autoLink: Ti.UI.AUTOLINK_ALL
|
|
673
|
-
});
|
|
674
|
-
```
|
|
675
|
-
|
|
676
|
-
### Auto-link constants
|
|
677
|
-
|
|
678
|
-
The `autoLink` property detects and linkifies content:
|
|
679
|
-
|
|
680
|
-
| Constant | Description |
|
|
681
|
-
| -------------------------------- | ----------------------------- |
|
|
682
|
-
| `Ti.UI.AUTOLINK_ALL` | Linkify all detected patterns |
|
|
683
|
-
| `Ti.UI.AUTOLINK_EMAIL_ADDRESSES` | Linkify email addresses |
|
|
684
|
-
| `Ti.UI.AUTOLINK_MAP_ADDRESSES` | Linkify street addresses |
|
|
685
|
-
| `Ti.UI.AUTOLINK_PHONE_NUMBERS` | Linkify phone numbers |
|
|
686
|
-
| `Ti.UI.AUTOLINK_URLS` | Linkify web URLs |
|
|
687
|
-
|
|
688
|
-
You can combine multiple constants using bitwise OR:
|
|
689
|
-
|
|
690
|
-
```javascript
|
|
691
|
-
const label = Ti.UI.createLabel({
|
|
692
|
-
text: 'Call 555-1234 or visit example.com',
|
|
693
|
-
autoLink: Ti.UI.AUTOLINK_PHONE_NUMBERS | Ti.UI.AUTOLINK_URLS
|
|
694
|
-
});
|
|
695
|
-
```
|
|
696
|
-
|
|
697
|
-
## 13. Nine-patch images
|
|
698
|
-
|
|
699
|
-
Nine-patch images (`.9.png`) define stretchable regions that adapt to different screen sizes and content.
|
|
700
|
-
|
|
701
|
-
### Key points
|
|
702
|
-
|
|
703
|
-
- Files use the `.9.png` extension
|
|
704
|
-
- Only work as `backgroundImage` (not as regular images)
|
|
705
|
-
- Define stretchable regions so the image scales without distortion
|
|
706
|
-
- Reference without the `.9` in code. Android resolves it automatically
|
|
707
|
-
- Create with the Android SDK `draw9patch` tool
|
|
708
|
-
|
|
709
|
-
```javascript
|
|
710
|
-
const button = Ti.UI.createButton({
|
|
711
|
-
title: 'Submit',
|
|
712
|
-
backgroundImage: '/images/button_bg.png', // actual file: button_bg.9.png
|
|
713
|
-
width: Ti.UI.SIZE,
|
|
714
|
-
height: Ti.UI.SIZE
|
|
715
|
-
});
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
## Best practices
|
|
719
|
-
|
|
720
|
-
1. Follow Material Design guidelines for modern Android apps
|
|
721
|
-
2. Use AppCompat v7 for consistent styling across Android versions
|
|
722
|
-
3. Handle back button to prevent unexpected app exits
|
|
723
|
-
4. Use themes that match your brand/design
|
|
724
|
-
5. Test on multiple Android versions because theme support varies
|
|
725
|
-
6. Consider accessibility and set content descriptions
|
|
726
|
-
7. Use notification channels for Android 8.0+ apps
|
|
727
|
-
8. Test on physical devices. Some features do not work in the emulator
|