@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,635 @@
|
|
|
1
|
+
# Android UI Components and Conventions
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Android UI Components and Conventions](#android-ui-components-and-conventions)
|
|
6
|
+
- [Table of Contents](#table-of-contents)
|
|
7
|
+
- [1. Action Bar](#1-action-bar)
|
|
8
|
+
- [Overview](#overview)
|
|
9
|
+
- [Enabling Action Bar](#enabling-action-bar)
|
|
10
|
+
- [Creating Action Bar (Programmatic)](#creating-action-bar-programmatic)
|
|
11
|
+
- [Action Bar with App Icon](#action-bar-with-app-icon)
|
|
12
|
+
- [Action View (Custom Layout)](#action-view-custom-layout)
|
|
13
|
+
- [2. Android Themes](#2-android-themes)
|
|
14
|
+
- [Overview](#overview-1)
|
|
15
|
+
- [Titanium Material Themes (SDK 10.0.0+)](#titanium-material-themes-sdk-1000)
|
|
16
|
+
- [Material 3 Themes (SDK 12.0.0+)](#material-3-themes-sdk-1200)
|
|
17
|
+
- [Applying Themes](#applying-themes)
|
|
18
|
+
- [Custom Theme](#custom-theme)
|
|
19
|
+
- [Color Palette Attributes](#color-palette-attributes)
|
|
20
|
+
- [Hiding Action Bar](#hiding-action-bar)
|
|
21
|
+
- [Theme Requirements](#theme-requirements)
|
|
22
|
+
- [3. Options Menu](#3-options-menu)
|
|
23
|
+
- [Legacy Options Menu](#legacy-options-menu)
|
|
24
|
+
- [Context Menu (Long Press)](#context-menu-long-press)
|
|
25
|
+
- [4. Status Bar Notifications](#4-status-bar-notifications)
|
|
26
|
+
- [Notifications](#notifications)
|
|
27
|
+
- [Notification Channels (Android 8.0+)](#notification-channels-android-80)
|
|
28
|
+
- [Clearing Notifications](#clearing-notifications)
|
|
29
|
+
- [5. Progress Bars](#5-progress-bars)
|
|
30
|
+
- [Horizontal Progress Bar](#horizontal-progress-bar)
|
|
31
|
+
- [Spinner (Indeterminate Progress)](#spinner-indeterminate-progress)
|
|
32
|
+
- [6. Tab Groups and Tabs](#6-tab-groups-and-tabs)
|
|
33
|
+
- [Native Android Tabs](#native-android-tabs)
|
|
34
|
+
- [Tab Badges](#tab-badges)
|
|
35
|
+
- [7. Hardware Back Button Handling](#7-hardware-back-button-handling)
|
|
36
|
+
- [Handling Back Button](#handling-back-button)
|
|
37
|
+
- [Exit Confirmation Dialog](#exit-confirmation-dialog)
|
|
38
|
+
- [8. Notification Drawer](#8-notification-drawer)
|
|
39
|
+
- [Display Notification](#display-notification)
|
|
40
|
+
- [9. Android UI Conventions](#9-android-ui-conventions)
|
|
41
|
+
- [Back Button Behavior](#back-button-behavior)
|
|
42
|
+
- [Up/Down Navigation](#updown-navigation)
|
|
43
|
+
- [App Shortcuts](#app-shortcuts)
|
|
44
|
+
- [10. Material Design Components](#10-material-design-components)
|
|
45
|
+
- [Using AppCompat v7](#using-appcompat-v7)
|
|
46
|
+
- [Material Design Components](#material-design-components)
|
|
47
|
+
- [Best Practices](#best-practices)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 1. Action Bar
|
|
52
|
+
|
|
53
|
+
### Overview
|
|
54
|
+
|
|
55
|
+
The Action Bar is a key Android UI component that appears at the top of the screen. It provides actions, navigation, and app branding.
|
|
56
|
+
|
|
57
|
+
### Enabling Action Bar
|
|
58
|
+
|
|
59
|
+
**In tiapp.xml**:
|
|
60
|
+
|
|
61
|
+
```xml
|
|
62
|
+
<android>
|
|
63
|
+
<manifest>
|
|
64
|
+
<application>
|
|
65
|
+
<activity android:name=".MyActivity"
|
|
66
|
+
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode">
|
|
67
|
+
<intent-filter>
|
|
68
|
+
<action android:name="android.intent.action.MAIN" />
|
|
69
|
+
<category android:name="android.intent.category.LAUNCHER" />
|
|
70
|
+
</intent-filter>
|
|
71
|
+
</activity>
|
|
72
|
+
</application>
|
|
73
|
+
</manifest>
|
|
74
|
+
</android>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Creating Action Bar (Programmatic)
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
const activity = Ti.Android.currentActivity;
|
|
81
|
+
|
|
82
|
+
activity.onCreateOptionsMenu = (e) => {
|
|
83
|
+
const menu = e.menu;
|
|
84
|
+
|
|
85
|
+
// Add "Refresh" action
|
|
86
|
+
const refreshItem = menu.add({
|
|
87
|
+
title: 'Refresh',
|
|
88
|
+
icon: Ti.Android.R.drawable.ic_menu_refresh,
|
|
89
|
+
showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
|
|
90
|
+
itemId: 1
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Add "Settings" action
|
|
94
|
+
const settingsItem = menu.add({
|
|
95
|
+
title: 'Settings',
|
|
96
|
+
icon: Ti.Android.R.drawable.ic_menu_preferences,
|
|
97
|
+
showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
|
|
98
|
+
itemId: 2
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Add "Search" action (shown as collapsible action view)
|
|
102
|
+
const searchItem = menu.add({
|
|
103
|
+
title: 'Search',
|
|
104
|
+
icon: Ti.Android.R.drawable.ic_menu_search,
|
|
105
|
+
actionView: Ti.UI.createSearchBar({
|
|
106
|
+
showCancel: true
|
|
107
|
+
}),
|
|
108
|
+
itemId: 3,
|
|
109
|
+
expandActionView: Ti.Android.COLLAPSE_ACTION_VIEW_IF_ROOM
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
activity.onOptionsItemSelected = (e) => {
|
|
114
|
+
switch (e.itemId) {
|
|
115
|
+
case 1:
|
|
116
|
+
refreshData();
|
|
117
|
+
return true;
|
|
118
|
+
case 2:
|
|
119
|
+
openSettings();
|
|
120
|
+
return true;
|
|
121
|
+
case 3:
|
|
122
|
+
// Search action - handled by SearchBar
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
activity.onPrepareOptionsMenu = (e) => {
|
|
129
|
+
// Update menu items before showing
|
|
130
|
+
const menu = e.menu;
|
|
131
|
+
// Modify items based on state
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Action Bar with App Icon
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
const activity = Ti.Android.currentActivity;
|
|
139
|
+
|
|
140
|
+
activity.onCreateOptionsMenu = (e) => {
|
|
141
|
+
const menu = e.menu;
|
|
142
|
+
|
|
143
|
+
// App icon on left
|
|
144
|
+
const appIcon = menu.addMenuItem({
|
|
145
|
+
title: 'My App',
|
|
146
|
+
icon: Ti.App.Android.R.drawable.app_icon,
|
|
147
|
+
itemId: 0
|
|
148
|
+
});
|
|
149
|
+
appIcon.setEnabled(false); // Not clickable, just branding
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Action View (Custom Layout)
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
activity.onCreateOptionsMenu = (e) => {
|
|
157
|
+
const menu = e.menu;
|
|
158
|
+
|
|
159
|
+
// Custom action view with button
|
|
160
|
+
const actionView = Ti.UI.createView({
|
|
161
|
+
height: Ti.UI.FILL,
|
|
162
|
+
backgroundColor: '#4CAF50',
|
|
163
|
+
layout: 'horizontal'
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const actionButton = Ti.UI.createButton({
|
|
167
|
+
title: 'Action',
|
|
168
|
+
color: 'white',
|
|
169
|
+
height: Ti.UI.FILL,
|
|
170
|
+
width: Ti.UI.SIZE
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
actionButton.addEventListener('click', () => {
|
|
174
|
+
performAction();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
actionView.add(actionButton);
|
|
178
|
+
|
|
179
|
+
const actionItem = menu.add({
|
|
180
|
+
title: 'Custom',
|
|
181
|
+
actionView: actionView,
|
|
182
|
+
showAsAction: Ti.Android.SHOW_AS_ACTION_ALWAYS,
|
|
183
|
+
itemId: 10
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 2. Android Themes
|
|
189
|
+
|
|
190
|
+
### Overview
|
|
191
|
+
|
|
192
|
+
Themes control the visual style of Android apps. Titanium 10.0.0+ **requires** material-based themes.
|
|
193
|
+
|
|
194
|
+
### Titanium Material Themes (SDK 10.0.0+)
|
|
195
|
+
|
|
196
|
+
| Theme | Description |
|
|
197
|
+
| ------------------------------------ | ------------------------------------- |
|
|
198
|
+
| `Theme.Titanium.DayNight` | Light/dark switching (default 10.0.x) |
|
|
199
|
+
| `Theme.Titanium.DayNight.NoTitleBar` | No action bar |
|
|
200
|
+
| `Theme.Titanium.DayNight.Fullscreen` | No action bar or status bar |
|
|
201
|
+
| `Theme.Titanium.DayNight.Solid` | Seamless background (default 10.1.0+) |
|
|
202
|
+
| `Theme.Titanium.Dark` | Dark only |
|
|
203
|
+
| `Theme.Titanium.Light` | Light only |
|
|
204
|
+
| `Theme.AppDerived.NoTitleBar` | Inherits app theme, no action bar |
|
|
205
|
+
| `Theme.AppDerived.Fullscreen` | Inherits app theme, fullscreen |
|
|
206
|
+
| `Theme.AppDerived.Translucent` | Transparent background |
|
|
207
|
+
|
|
208
|
+
### Material 3 Themes (SDK 12.0.0+)
|
|
209
|
+
|
|
210
|
+
```xml
|
|
211
|
+
<!-- tiapp.xml -->
|
|
212
|
+
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
213
|
+
<manifest>
|
|
214
|
+
<application android:theme="@style/Theme.Titanium.Material3.DayNight"/>
|
|
215
|
+
</manifest>
|
|
216
|
+
</android>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Theme | Description |
|
|
220
|
+
| ---------------------------------------------- | ------------------------------ |
|
|
221
|
+
| `Theme.Titanium.Material3.DayNight` | Material 3 with dynamic colors |
|
|
222
|
+
| `Theme.Titanium.Material3.DayNight.NoTitleBar` | No action bar |
|
|
223
|
+
| `Theme.Titanium.Material3.DayNight.Fullscreen` | No action/status bar |
|
|
224
|
+
|
|
225
|
+
**Custom Material 3 theme:**
|
|
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
|
+
### Applying Themes
|
|
234
|
+
|
|
235
|
+
**Global (tiapp.xml):**
|
|
236
|
+
```xml
|
|
237
|
+
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
238
|
+
<manifest>
|
|
239
|
+
<application android:theme="@style/Theme.Titanium.DayNight.Solid"/>
|
|
240
|
+
</manifest>
|
|
241
|
+
</android>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Per-window (JavaScript):**
|
|
245
|
+
```javascript
|
|
246
|
+
const win = Ti.UI.createWindow({
|
|
247
|
+
theme: 'Theme.AppDerived.Fullscreen'
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Custom Theme
|
|
252
|
+
|
|
253
|
+
```xml
|
|
254
|
+
<!-- platform/android/res/values/mytheme.xml -->
|
|
255
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
256
|
+
<resources>
|
|
257
|
+
<!-- SDK 10.0.0+ -->
|
|
258
|
+
<style name="Theme.MyTheme" parent="@style/Theme.Titanium.Light">
|
|
259
|
+
<item name="colorPrimary">#c91326</item>
|
|
260
|
+
<item name="colorPrimaryDark">#900000</item>
|
|
261
|
+
<item name="colorAccent">#c91326</item>
|
|
262
|
+
<item name="android:textColorPrimary">#000000</item>
|
|
263
|
+
<item name="android:statusBarColor">#c91326</item>
|
|
264
|
+
<item name="android:navigationBarColor">#c91326</item>
|
|
265
|
+
</style>
|
|
266
|
+
</resources>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Dark theme variant (values-night/):**
|
|
270
|
+
```xml
|
|
271
|
+
<!-- platform/android/res/values-night/mytheme.xml -->
|
|
272
|
+
<resources>
|
|
273
|
+
<style name="Theme.MyTheme" parent="@style/Theme.Titanium.Dark">
|
|
274
|
+
<item name="colorPrimary">#d5544b</item>
|
|
275
|
+
<item name="colorAccent">#d5544b</item>
|
|
276
|
+
</style>
|
|
277
|
+
</resources>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Color Palette Attributes
|
|
281
|
+
|
|
282
|
+
| Attribute | Description |
|
|
283
|
+
| ---------------------------- | -------------------------- |
|
|
284
|
+
| `colorPrimary` | Action bar color |
|
|
285
|
+
| `colorPrimaryDark` | Status bar color (API 21+) |
|
|
286
|
+
| `colorAccent` | Control accent color |
|
|
287
|
+
| `colorControlNormal` | Inactive control color |
|
|
288
|
+
| `colorControlActivated` | Active control color |
|
|
289
|
+
| `colorControlHighlight` | Click highlight (API 21+) |
|
|
290
|
+
| `android:navigationBarColor` | Bottom nav bar (API 21+) |
|
|
291
|
+
| `android:textColorPrimary` | Primary text color |
|
|
292
|
+
|
|
293
|
+
### Hiding Action Bar
|
|
294
|
+
|
|
295
|
+
**Via theme (recommended):**
|
|
296
|
+
```xml
|
|
297
|
+
<application android:theme="@style/Theme.AppDerived.NoTitleBar"/>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Via JavaScript:**
|
|
301
|
+
```javascript
|
|
302
|
+
const win = Ti.UI.createWindow({
|
|
303
|
+
theme: 'Theme.AppDerived.NoTitleBar'
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Or hide after open
|
|
307
|
+
win.addEventListener('open', () => {
|
|
308
|
+
win.activity.actionBar.hide();
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Theme Requirements
|
|
313
|
+
|
|
314
|
+
- SDK 10.0.0+ requires material-based themes (runtime error otherwise)
|
|
315
|
+
- Place custom themes in `platform/android/res/values/`
|
|
316
|
+
- Do NOT name file `theme.xml` (overwrites Titanium's)
|
|
317
|
+
- Use `values-v<api>` for version-specific themes
|
|
318
|
+
- Use `values-night` for dark mode variants
|
|
319
|
+
|
|
320
|
+
## 3. Options Menu
|
|
321
|
+
|
|
322
|
+
### Legacy Options Menu
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
const activity = Ti.Android.currentActivity;
|
|
326
|
+
|
|
327
|
+
activity.onCreateOptionsMenu = (e) => {
|
|
328
|
+
const menu = e.menu;
|
|
329
|
+
|
|
330
|
+
// Add items
|
|
331
|
+
menu.add({ title: 'Option 1', itemId: 1 });
|
|
332
|
+
menu.add({ title: 'Option 2', itemId: 2 });
|
|
333
|
+
menu.add({ title: 'Option 3', itemId: 3 });
|
|
334
|
+
menu.add({ title: 'Option 4', itemId: 4 });
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
activity.onOptionsItemSelected = (e) => {
|
|
338
|
+
switch (e.itemId) {
|
|
339
|
+
case 1:
|
|
340
|
+
handleOption1();
|
|
341
|
+
return true;
|
|
342
|
+
// ... other cases
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Context Menu (Long Press)
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
const view = Ti.UI.createView({
|
|
352
|
+
backgroundColor: 'white'
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
view.addEventListener('longpress', (e) => {
|
|
356
|
+
// Register for context menu
|
|
357
|
+
registerForContextMenu();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
function registerForContextMenu() {
|
|
361
|
+
// Android: Create and register for context menu
|
|
362
|
+
// This is typically done in tiapp.xml with intent filters
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## 4. Status Bar Notifications
|
|
367
|
+
|
|
368
|
+
### Notifications
|
|
369
|
+
|
|
370
|
+
```javascript
|
|
371
|
+
// Create notification
|
|
372
|
+
const notification = Ti.Android.createNotification({
|
|
373
|
+
contentTitle: 'New Message',
|
|
374
|
+
contentText: 'You have a new message',
|
|
375
|
+
contentIntent: Ti.Android.createIntent({
|
|
376
|
+
url: 'myapp://message/123'
|
|
377
|
+
}),
|
|
378
|
+
number: 1, // Notification number
|
|
379
|
+
sound: Ti.App.Android.R.drawable.app_icon, // Notification sound
|
|
380
|
+
defaults: 0, // Flags (LED, vibration, etc.)
|
|
381
|
+
flags: Ti.Android.FLAG_AUTO_CANCEL | Ti.Android.FLAG_SHOW_LIGHTS
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Show notification
|
|
385
|
+
Ti.Android.NotificationManager.notify(1, notification);
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Notification Channels (Android 8.0+)
|
|
389
|
+
|
|
390
|
+
```javascript
|
|
391
|
+
// Create notification channel for Android 8.0+
|
|
392
|
+
const channel = Ti.Android.createNotificationChannel({
|
|
393
|
+
id: 'my_channel_id',
|
|
394
|
+
name: 'My Channel',
|
|
395
|
+
importance: Ti.Android.NOTIFICATION_IMPORTANCE_HIGH,
|
|
396
|
+
lightColor: '#FF0000',
|
|
397
|
+
enableLights: true,
|
|
398
|
+
showBadge: true,
|
|
399
|
+
sound: Ti.Filesystem.getFile('sound.mp3')
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
Ti.Android.NotificationManager.createNotificationChannel(channel);
|
|
403
|
+
|
|
404
|
+
// Use channel in notification
|
|
405
|
+
const notification = Ti.Android.createNotification({
|
|
406
|
+
channelId: 'my_channel_id',
|
|
407
|
+
contentTitle: 'Channel Test',
|
|
408
|
+
contentText: 'Testing notification channels',
|
|
409
|
+
// ... other properties
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
Ti.Android.NotificationManager.notify(1, notification);
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Clearing Notifications
|
|
416
|
+
|
|
417
|
+
```javascript
|
|
418
|
+
// Cancel specific notification
|
|
419
|
+
Ti.Android.NotificationManager.cancel(1);
|
|
420
|
+
|
|
421
|
+
// Clear all notifications
|
|
422
|
+
Ti.Android.NotificationManager.cancelAll();
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## 5. Progress Bars
|
|
426
|
+
|
|
427
|
+
### Horizontal Progress Bar
|
|
428
|
+
|
|
429
|
+
```javascript
|
|
430
|
+
const progressBar = Ti.UI.createProgressBar({
|
|
431
|
+
min: 0,
|
|
432
|
+
max: 100,
|
|
433
|
+
value: 0,
|
|
434
|
+
width: Ti.UI.FILL,
|
|
435
|
+
height: Ti.UI.SIZE,
|
|
436
|
+
style: Ti.UI.Android.PROGRESS_BAR_STYLE_HORIZONTAL,
|
|
437
|
+
top: 10
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
// Update progress
|
|
441
|
+
progressBar.value = 50;
|
|
442
|
+
|
|
443
|
+
// Indeterminate progress
|
|
444
|
+
progressBar.message = 'Loading...';
|
|
445
|
+
progressBar.show();
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Spinner (Indeterminate Progress)
|
|
449
|
+
|
|
450
|
+
```javascript
|
|
451
|
+
const activityIndicator = Ti.UI.createActivityIndicator({
|
|
452
|
+
message: 'Loading...',
|
|
453
|
+
location: Ti.UI.Android.ACTIVITY_INDICATOR_DIALOG,
|
|
454
|
+
cancelable: false
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
activityIndicator.show();
|
|
458
|
+
|
|
459
|
+
// Later:
|
|
460
|
+
activityIndicator.hide();
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## 6. Tab Groups and Tabs
|
|
464
|
+
|
|
465
|
+
### Native Android Tabs
|
|
466
|
+
|
|
467
|
+
```javascript
|
|
468
|
+
const tabGroup = Ti.UI.createTabGroup({
|
|
469
|
+
tabs: [tab1, tab2, tab3]
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
tabGroup.addEventListener('open', (e) => {
|
|
473
|
+
Ti.API.info(`Tab opened: ${e.index} (${e.tab.title})`);
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Tab Badges
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
const tab = Titanium.UI.createTab({
|
|
481
|
+
title: 'Inbox',
|
|
482
|
+
window: winInbox,
|
|
483
|
+
icon: Ti.Android.R.drawable.ic_menu_info
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// Set badge (number)
|
|
487
|
+
tab.badge = 5;
|
|
488
|
+
|
|
489
|
+
// Clear badge
|
|
490
|
+
tab.badge = null; // or tab.setBadge(null);
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## 7. Hardware Back Button Handling
|
|
494
|
+
|
|
495
|
+
### Handling Back Button
|
|
496
|
+
|
|
497
|
+
```javascript
|
|
498
|
+
const win = Ti.UI.createWindow();
|
|
499
|
+
|
|
500
|
+
win.addEventListener('androidback', (e) => {
|
|
501
|
+
e.cancelBubble = true; // Prevent default behavior
|
|
502
|
+
|
|
503
|
+
// Check if can go back
|
|
504
|
+
if (canGoBack()) {
|
|
505
|
+
closeCurrentWindow();
|
|
506
|
+
} else {
|
|
507
|
+
showExitConfirmation();
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
function canGoBack() {
|
|
512
|
+
// Your logic here
|
|
513
|
+
return true; // or false
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Exit Confirmation Dialog
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
function showExitConfirmation() {
|
|
521
|
+
const dialog = Ti.UI.createAlertDialog({
|
|
522
|
+
title: 'Exit?',
|
|
523
|
+
message: 'Do you want to exit?',
|
|
524
|
+
buttonNames: ['Yes', 'No'],
|
|
525
|
+
cancel: 1
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
dialog.addEventListener('click', (e) => {
|
|
529
|
+
if (e.index === 0) {
|
|
530
|
+
const activity = Ti.Android.currentActivity;
|
|
531
|
+
activity.finish(); // Close app
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
dialog.show();
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## 8. Notification Drawer
|
|
540
|
+
|
|
541
|
+
### Display Notification
|
|
542
|
+
|
|
543
|
+
```javascript
|
|
544
|
+
const notification = Ti.Android.createNotification({
|
|
545
|
+
contentTitle: 'Download Complete',
|
|
546
|
+
contentText: 'Your file has been downloaded',
|
|
547
|
+
contentIntent: Ti.Android.createIntent({
|
|
548
|
+
url: 'myapp://download/complete'
|
|
549
|
+
}),
|
|
550
|
+
largeIcon: Ti.App.Android.R.drawable.app_icon,
|
|
551
|
+
bigTextStyle: { bold: true, italic: false }
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
Ti.Android.NotificationManager.notify(1, notification);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## 9. Android UI Conventions
|
|
558
|
+
|
|
559
|
+
### Back Button Behavior
|
|
560
|
+
|
|
561
|
+
Standard Android conventions:
|
|
562
|
+
- **Back button** = Navigate back in hierarchy
|
|
563
|
+
- **Long press back** = Show recent apps menu (system behavior)
|
|
564
|
+
- Apps should handle back button unless:
|
|
565
|
+
|
|
566
|
+
1. It's the root activity (app would exit)
|
|
567
|
+
2. User is in a task that shouldn't be interrupted
|
|
568
|
+
3. Confirmation needed (destructive action)
|
|
569
|
+
|
|
570
|
+
### Up/Down Navigation
|
|
571
|
+
|
|
572
|
+
Traditional Android navigation uses:
|
|
573
|
+
- **Up button** = Navigate up in hierarchy
|
|
574
|
+
- **Menu button** = Show options menu
|
|
575
|
+
- **Home button** = Go to home (backgrounds app)
|
|
576
|
+
|
|
577
|
+
Modern apps may:
|
|
578
|
+
- Use Navigation Component (jetpack)
|
|
579
|
+
- Use up button for "back" navigation pattern
|
|
580
|
+
- Implement custom up navigation
|
|
581
|
+
|
|
582
|
+
### App Shortcuts
|
|
583
|
+
|
|
584
|
+
Android 7.1+ app shortcuts:
|
|
585
|
+
|
|
586
|
+
```xml
|
|
587
|
+
<activity
|
|
588
|
+
android:name=".MainActivity"
|
|
589
|
+
android:launchMode="singleTask">
|
|
590
|
+
<!-- Define shortcuts -->
|
|
591
|
+
<intent-filter>
|
|
592
|
+
<action android:name="android.intent.action.VIEW" />
|
|
593
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
594
|
+
<data android:scheme="myapp" />
|
|
595
|
+
</intent-filter>
|
|
596
|
+
</activity>
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## 10. Material Design Components
|
|
600
|
+
|
|
601
|
+
### Using AppCompat v7
|
|
602
|
+
|
|
603
|
+
```xml
|
|
604
|
+
<android>
|
|
605
|
+
<manifest>
|
|
606
|
+
<application>
|
|
607
|
+
<!-- Use AppCompat for Material Design support -->
|
|
608
|
+
<meta-data android:name="android:theme"
|
|
609
|
+
android:resource="@style/Theme.AppCompat.Light" />
|
|
610
|
+
</application>
|
|
611
|
+
</manifest>
|
|
612
|
+
</android>
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Material Design Components
|
|
616
|
+
|
|
617
|
+
- `Toolbar` - Replaces Action Bar (recommended)
|
|
618
|
+
- `CardView` - Cards with elevation
|
|
619
|
+
- `RecyclerView` - Advanced list component
|
|
620
|
+
- `CoordinatorLayout` - Complex layout coordination
|
|
621
|
+
- `TextInputLayout` - Floating label hints
|
|
622
|
+
- `FloatingActionButton` - Circular action button
|
|
623
|
+
|
|
624
|
+
These can be accessed via Hyperloop or custom modules.
|
|
625
|
+
|
|
626
|
+
## Best Practices
|
|
627
|
+
|
|
628
|
+
1. **Follow Material Design guidelines** for modern Android apps
|
|
629
|
+
2. **Use AppCompat v7** for consistent styling across Android versions
|
|
630
|
+
3. **Handle back button** to prevent unexpected app exits
|
|
631
|
+
4. **Use appropriate themes** that match your brand/design
|
|
632
|
+
5. **Test on multiple Android versions** - Theme support varies
|
|
633
|
+
6. **Consider accessibility** - Ensure content descriptions are set
|
|
634
|
+
7. **Use notification channels** for Android 8.0+ apps
|
|
635
|
+
8. **Test on physical devices** - Some features don't work in emulator
|