@nativescript/core 9.0.0-alpha.24 → 9.0.0-alpha.26
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/application/application-common.d.ts +29 -10
- package/application/application-common.js +58 -5
- package/application/application-common.js.map +1 -1
- package/application/application-interfaces.d.ts +10 -0
- package/application/application-shims.d.ts +27 -0
- package/application/application-shims.js +27 -0
- package/application/application-shims.js.map +1 -1
- package/application/application.android.d.ts +12 -2
- package/application/application.android.js +418 -342
- package/application/application.android.js.map +1 -1
- package/application/application.d.ts +8 -1
- package/application/application.ios.d.ts +16 -1
- package/application/application.ios.js +59 -21
- package/application/application.ios.js.map +1 -1
- package/application/helpers.android.d.ts +0 -9
- package/application/helpers.android.js +0 -54
- package/application/helpers.android.js.map +1 -1
- package/application/helpers.d.ts +0 -10
- package/application/helpers.ios.d.ts +0 -19
- package/application/helpers.ios.js +0 -38
- package/application/helpers.ios.js.map +1 -1
- package/config/config.interface.d.ts +21 -0
- package/connectivity/index.android.js +25 -25
- package/connectivity/index.android.js.map +1 -1
- package/core-types/index.d.ts +77 -63
- package/core-types/index.js +10 -1
- package/core-types/index.js.map +1 -1
- package/core-types/validators.js +12 -6
- package/core-types/validators.js.map +1 -1
- package/data/observable/index.d.ts +2 -1
- package/data/observable/index.js +31 -19
- package/data/observable/index.js.map +1 -1
- package/fps-meter/fps-native.ios.js +1 -1
- package/fps-meter/fps-native.ios.js.map +1 -1
- package/http/http-request/index.ios.js +1 -1
- package/http/http-request/index.ios.js.map +1 -1
- package/image-source/index.d.ts +2 -2
- package/index.js +0 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/platform/screen/index.d.ts +5 -0
- package/platforms/android/widgets-release.aar +0 -0
- package/references.d.ts +1 -1
- package/timer/index.ios.js +1 -1
- package/timer/index.ios.js.map +1 -1
- package/ui/action-bar/index.android.js +18 -18
- package/ui/action-bar/index.android.js.map +1 -1
- package/ui/action-bar/index.ios.js +2 -4
- package/ui/action-bar/index.ios.js.map +1 -1
- package/ui/animation/index.ios.js +2 -3
- package/ui/animation/index.ios.js.map +1 -1
- package/ui/button/index.android.js +20 -20
- package/ui/button/index.android.js.map +1 -1
- package/ui/button/index.ios.d.ts +2 -1
- package/ui/button/index.ios.js +28 -10
- package/ui/button/index.ios.js.map +1 -1
- package/ui/core/control-state-change/index.ios.js +1 -1
- package/ui/core/control-state-change/index.ios.js.map +1 -1
- package/ui/core/view/index.android.d.ts +6 -6
- package/ui/core/view/index.android.js +337 -455
- package/ui/core/view/index.android.js.map +1 -1
- package/ui/core/view/index.d.ts +18 -5
- package/ui/core/view/index.ios.d.ts +10 -2
- package/ui/core/view/index.ios.js +99 -46
- package/ui/core/view/index.ios.js.map +1 -1
- package/ui/core/view/view-common.d.ts +46 -12
- package/ui/core/view/view-common.js +28 -0
- package/ui/core/view/view-common.js.map +1 -1
- package/ui/core/view/view-helper/index.d.ts +5 -0
- package/ui/core/view/view-helper/index.ios.d.ts +5 -4
- package/ui/core/view/view-helper/index.ios.js +20 -23
- package/ui/core/view/view-helper/index.ios.js.map +1 -1
- package/ui/core/view/view-helper/view-helper-common.js +7 -0
- package/ui/core/view/view-helper/view-helper-common.js.map +1 -1
- package/ui/core/view/view-interfaces.d.ts +3 -0
- package/ui/core/view-base/index.d.ts +4 -0
- package/ui/core/view-base/index.js +4 -0
- package/ui/core/view-base/index.js.map +1 -1
- package/ui/date-picker/index.android.js +38 -38
- package/ui/date-picker/index.android.js.map +1 -1
- package/ui/date-picker/index.ios.js +1 -1
- package/ui/date-picker/index.ios.js.map +1 -1
- package/ui/editable-text-base/index.android.js +34 -34
- package/ui/editable-text-base/index.android.js.map +1 -1
- package/ui/frame/fragment.transitions.android.d.ts +2 -1
- package/ui/frame/fragment.transitions.android.js +106 -104
- package/ui/frame/fragment.transitions.android.js.map +1 -1
- package/ui/frame/fragment.transitions.d.ts +3 -2
- package/ui/frame/index.android.js +57 -4
- package/ui/frame/index.android.js.map +1 -1
- package/ui/frame/index.ios.d.ts +2 -1
- package/ui/frame/index.ios.js +83 -43
- package/ui/frame/index.ios.js.map +1 -1
- package/ui/gestures/index.android.js +129 -130
- package/ui/gestures/index.android.js.map +1 -1
- package/ui/gestures/index.ios.js +3 -5
- package/ui/gestures/index.ios.js.map +1 -1
- package/ui/gestures/touch-manager.js +32 -32
- package/ui/gestures/touch-manager.js.map +1 -1
- package/ui/image/index.android.js +19 -19
- package/ui/image/index.android.js.map +1 -1
- package/ui/image-cache/index.android.js +12 -14
- package/ui/image-cache/index.android.js.map +1 -1
- package/ui/image-cache/index.ios.js +6 -6
- package/ui/image-cache/index.ios.js.map +1 -1
- package/ui/index.d.ts +2 -1
- package/ui/index.js +1 -0
- package/ui/index.js.map +1 -1
- package/ui/label/index.android.js +4 -1
- package/ui/label/index.android.js.map +1 -1
- package/ui/label/index.ios.d.ts +2 -1
- package/ui/label/index.ios.js +12 -2
- package/ui/label/index.ios.js.map +1 -1
- package/ui/layouts/flexbox-layout/index.ios.js +3 -6
- package/ui/layouts/flexbox-layout/index.ios.js.map +1 -1
- package/ui/layouts/index.d.ts +2 -0
- package/ui/layouts/index.js +2 -0
- package/ui/layouts/index.js.map +1 -1
- package/ui/layouts/liquid-glass/index.android.d.ts +5 -0
- package/ui/layouts/liquid-glass/index.android.js +8 -0
- package/ui/layouts/liquid-glass/index.android.js.map +1 -0
- package/ui/layouts/liquid-glass/index.d.ts +10 -0
- package/ui/layouts/liquid-glass/index.ios.d.ts +10 -0
- package/ui/layouts/liquid-glass/index.ios.js +59 -0
- package/ui/layouts/liquid-glass/index.ios.js.map +1 -0
- package/ui/layouts/liquid-glass/liquid-glass-common.d.ts +3 -0
- package/ui/layouts/liquid-glass/liquid-glass-common.js +4 -0
- package/ui/layouts/liquid-glass/liquid-glass-common.js.map +1 -0
- package/ui/layouts/liquid-glass-container/index.android.d.ts +3 -0
- package/ui/layouts/liquid-glass-container/index.android.js +4 -0
- package/ui/layouts/liquid-glass-container/index.android.js.map +1 -0
- package/ui/layouts/liquid-glass-container/index.d.ts +3 -0
- package/ui/layouts/liquid-glass-container/index.ios.d.ts +14 -0
- package/ui/layouts/liquid-glass-container/index.ios.js +121 -0
- package/ui/layouts/liquid-glass-container/index.ios.js.map +1 -0
- package/ui/layouts/liquid-glass-container/liquid-glass-container-common.d.ts +4 -0
- package/ui/layouts/liquid-glass-container/liquid-glass-container-common.js +5 -0
- package/ui/layouts/liquid-glass-container/liquid-glass-container-common.js.map +1 -0
- package/ui/layouts/stack-layout/index.ios.js +6 -0
- package/ui/layouts/stack-layout/index.ios.js.map +1 -1
- package/ui/list-picker/index.android.js +35 -35
- package/ui/list-picker/index.android.js.map +1 -1
- package/ui/list-picker/index.ios.js +2 -2
- package/ui/list-picker/index.ios.js.map +1 -1
- package/ui/list-view/index.android.d.ts +26 -1
- package/ui/list-view/index.android.js +765 -129
- package/ui/list-view/index.android.js.map +1 -1
- package/ui/list-view/index.d.ts +127 -0
- package/ui/list-view/index.ios.d.ts +34 -2
- package/ui/list-view/index.ios.js +557 -21
- package/ui/list-view/index.ios.js.map +1 -1
- package/ui/list-view/list-view-common.d.ts +22 -1
- package/ui/list-view/list-view-common.js +85 -0
- package/ui/list-view/list-view-common.js.map +1 -1
- package/ui/page/index.ios.js +25 -64
- package/ui/page/index.ios.js.map +1 -1
- package/ui/scroll-view/index.d.ts +1 -1
- package/ui/scroll-view/index.ios.d.ts +2 -0
- package/ui/scroll-view/index.ios.js +31 -12
- package/ui/scroll-view/index.ios.js.map +1 -1
- package/ui/scroll-view/scroll-view-common.d.ts +3 -8
- package/ui/scroll-view/scroll-view-common.js +4 -4
- package/ui/scroll-view/scroll-view-common.js.map +1 -1
- package/ui/search-bar/index.android.js +48 -52
- package/ui/search-bar/index.android.js.map +1 -1
- package/ui/search-bar/index.ios.js +3 -6
- package/ui/search-bar/index.ios.js.map +1 -1
- package/ui/segmented-bar/index.android.js +56 -58
- package/ui/segmented-bar/index.android.js.map +1 -1
- package/ui/segmented-bar/index.ios.js +1 -1
- package/ui/segmented-bar/index.ios.js.map +1 -1
- package/ui/slider/index.android.js +23 -25
- package/ui/slider/index.android.js.map +1 -1
- package/ui/slider/index.ios.js +2 -2
- package/ui/slider/index.ios.js.map +1 -1
- package/ui/split-view/index.android.d.ts +4 -0
- package/ui/split-view/index.android.js +4 -0
- package/ui/split-view/index.android.js.map +1 -0
- package/ui/split-view/index.d.ts +11 -0
- package/ui/split-view/index.ios.d.ts +39 -0
- package/ui/split-view/index.ios.js +368 -0
- package/ui/split-view/index.ios.js.map +1 -0
- package/ui/split-view/split-view-common.d.ts +51 -0
- package/ui/split-view/split-view-common.js +111 -0
- package/ui/split-view/split-view-common.js.map +1 -0
- package/ui/styling/background-common.d.ts +4 -4
- package/ui/styling/background-common.js +8 -8
- package/ui/styling/background-common.js.map +1 -1
- package/ui/styling/background.d.ts +0 -3
- package/ui/styling/background.ios.d.ts +2 -1
- package/ui/styling/background.ios.js +47 -38
- package/ui/styling/background.ios.js.map +1 -1
- package/ui/styling/css-utils.d.ts +1 -0
- package/ui/styling/css-utils.js +15 -4
- package/ui/styling/css-utils.js.map +1 -1
- package/ui/styling/style/index.d.ts +3 -1
- package/ui/styling/style/index.js.map +1 -1
- package/ui/styling/style-properties.d.ts +1 -0
- package/ui/styling/style-properties.js +30 -11
- package/ui/styling/style-properties.js.map +1 -1
- package/ui/switch/index.android.js +18 -18
- package/ui/switch/index.android.js.map +1 -1
- package/ui/switch/index.ios.d.ts +1 -0
- package/ui/switch/index.ios.js +62 -12
- package/ui/switch/index.ios.js.map +1 -1
- package/ui/tab-view/index.android.js +185 -187
- package/ui/tab-view/index.android.js.map +1 -1
- package/ui/tab-view/index.d.ts +17 -1
- package/ui/tab-view/index.ios.d.ts +13 -5
- package/ui/tab-view/index.ios.js +253 -49
- package/ui/tab-view/index.ios.js.map +1 -1
- package/ui/tab-view/tab-view-common.d.ts +14 -0
- package/ui/tab-view/tab-view-common.js +15 -0
- package/ui/tab-view/tab-view-common.js.map +1 -1
- package/ui/text-base/index.android.d.ts +2 -1
- package/ui/text-base/index.android.js +133 -101
- package/ui/text-base/index.android.js.map +1 -1
- package/ui/text-base/index.d.ts +5 -0
- package/ui/text-base/index.ios.js +12 -18
- package/ui/text-base/index.ios.js.map +1 -1
- package/ui/text-base/text-base-common.d.ts +2 -1
- package/ui/text-base/text-base-common.js +1 -0
- package/ui/text-base/text-base-common.js.map +1 -1
- package/ui/text-field/index.ios.d.ts +2 -1
- package/ui/text-field/index.ios.js +9 -5
- package/ui/text-field/index.ios.js.map +1 -1
- package/ui/text-view/index.ios.d.ts +2 -1
- package/ui/text-view/index.ios.js +12 -7
- package/ui/text-view/index.ios.js.map +1 -1
- package/ui/time-picker/index.android.js +21 -21
- package/ui/time-picker/index.android.js.map +1 -1
- package/ui/time-picker/index.ios.js +1 -1
- package/ui/time-picker/index.ios.js.map +1 -1
- package/ui/transition/fade-transition.ios.js +5 -6
- package/ui/transition/fade-transition.ios.js.map +1 -1
- package/ui/transition/modal-transition.ios.js +19 -26
- package/ui/transition/modal-transition.ios.js.map +1 -1
- package/ui/transition/page-transition.android.js +3 -12
- package/ui/transition/page-transition.android.js.map +1 -1
- package/ui/transition/page-transition.ios.js +19 -25
- package/ui/transition/page-transition.ios.js.map +1 -1
- package/ui/transition/slide-transition.ios.js +5 -6
- package/ui/transition/slide-transition.ios.js.map +1 -1
- package/ui/web-view/index.android.js +58 -62
- package/ui/web-view/index.android.js.map +1 -1
- package/ui/web-view/index.ios.js +18 -18
- package/ui/web-view/index.ios.js.map +1 -1
- package/utils/common.d.ts +3 -1
- package/utils/common.js +9 -3
- package/utils/common.js.map +1 -1
- package/utils/index.d.ts +6 -0
- package/utils/layout-helper/index.android.d.ts +1 -0
- package/utils/layout-helper/index.android.js +9 -0
- package/utils/layout-helper/index.android.js.map +1 -1
- package/utils/layout-helper/index.d.ts +5 -0
- package/utils/layout-helper/index.ios.d.ts +1 -0
- package/utils/layout-helper/index.ios.js +4 -0
- package/utils/layout-helper/index.ios.js.map +1 -1
- package/utils/native-helper-for-android.d.ts +14 -3
- package/utils/native-helper-for-android.js +57 -54
- package/utils/native-helper-for-android.js.map +1 -1
- package/utils/native-helper.android.d.ts +3 -3
- package/utils/native-helper.android.js +2 -2
- package/utils/native-helper.android.js.map +1 -1
- package/utils/native-helper.d.ts +22 -5
- package/utils/native-helper.ios.js +20 -20
- package/utils/native-helper.ios.js.map +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { ListViewBase, separatorColorProperty, itemTemplatesProperty } from './list-view-common';
|
|
1
|
+
import { ListViewBase, separatorColorProperty, itemTemplatesProperty, stickyHeaderProperty, stickyHeaderTemplateProperty, sectionedProperty, showSearchProperty } from './list-view-common';
|
|
2
|
+
import { View } from '../core/view';
|
|
3
|
+
import { PercentLength } from '../styling/length-shared';
|
|
2
4
|
import { unsetValue } from '../core/properties/property-shared';
|
|
3
5
|
import { Color } from '../../color';
|
|
4
6
|
import { Observable } from '../../data/observable';
|
|
@@ -6,39 +8,47 @@ import { StackLayout } from '../layouts/stack-layout';
|
|
|
6
8
|
import { ProxyViewContainer } from '../proxy-view-container';
|
|
7
9
|
import { LayoutBase } from '../layouts/layout-base';
|
|
8
10
|
import { profile } from '../../profiling';
|
|
11
|
+
import { Trace } from '../../trace';
|
|
12
|
+
import { Builder } from '../builder';
|
|
13
|
+
import { Label } from '../label';
|
|
9
14
|
export * from './list-view-common';
|
|
10
15
|
const ITEMLOADING = ListViewBase.itemLoadingEvent;
|
|
11
16
|
const LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
|
|
12
17
|
const ITEMTAP = ListViewBase.itemTapEvent;
|
|
18
|
+
const SEARCHCHANGE = ListViewBase.searchChangeEvent;
|
|
19
|
+
const STICKY_HEADER_Z_INDEX = 1000;
|
|
20
|
+
const SEARCH_VIEW_Z_INDEX = 2000;
|
|
21
|
+
// View type constants for sectioned lists
|
|
22
|
+
const ITEM_VIEW_TYPE = 0;
|
|
13
23
|
let ItemClickListener;
|
|
14
24
|
function initializeItemClickListener() {
|
|
15
25
|
if (ItemClickListener) {
|
|
16
26
|
return;
|
|
17
27
|
}
|
|
18
|
-
var ItemClickListenerImpl =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}(java.lang.Object));
|
|
28
|
+
var ItemClickListenerImpl = (function (_super) {
|
|
29
|
+
__extends(ItemClickListenerImpl, _super);
|
|
30
|
+
function ItemClickListenerImpl(owner) {
|
|
31
|
+
var _this = _super.call(this) || this;
|
|
32
|
+
_this.owner = owner;
|
|
33
|
+
return global.__native(_this);
|
|
34
|
+
}
|
|
35
|
+
ItemClickListenerImpl.prototype.onItemClick = function (parent, convertView, index, id) {
|
|
36
|
+
var owner = this.owner;
|
|
37
|
+
var view = owner._realizedItems.get(convertView).view;
|
|
38
|
+
owner.notify({
|
|
39
|
+
eventName: ITEMTAP,
|
|
40
|
+
object: owner,
|
|
41
|
+
index: index,
|
|
42
|
+
view: view,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var _a;
|
|
46
|
+
ItemClickListenerImpl = __decorate([
|
|
47
|
+
Interfaces([android.widget.AdapterView.OnItemClickListener]),
|
|
48
|
+
__metadata("design:paramtypes", [typeof (_a = typeof ListView !== "undefined" && ListView) === "function" ? _a : Object])
|
|
49
|
+
], ItemClickListenerImpl);
|
|
50
|
+
return ItemClickListenerImpl;
|
|
51
|
+
}(java.lang.Object));
|
|
42
52
|
ItemClickListener = ItemClickListenerImpl;
|
|
43
53
|
}
|
|
44
54
|
export class ListView extends ListViewBase {
|
|
@@ -48,6 +58,11 @@ export class ListView extends ListViewBase {
|
|
|
48
58
|
this._realizedItems = new Map();
|
|
49
59
|
this._availableViews = new Map();
|
|
50
60
|
this._realizedTemplates = new Map();
|
|
61
|
+
this._stickyHeaderHeight = 0;
|
|
62
|
+
this._hiddenHeaderPositions = new Set(); // Track which headers to hide
|
|
63
|
+
}
|
|
64
|
+
get hasSearchView() {
|
|
65
|
+
return !!this._searchView;
|
|
51
66
|
}
|
|
52
67
|
_ensureAvailableViews(templateKey) {
|
|
53
68
|
if (!this._availableViews.has(templateKey)) {
|
|
@@ -122,6 +137,7 @@ export class ListView extends ListViewBase {
|
|
|
122
137
|
this._androidViewId = android.view.View.generateViewId();
|
|
123
138
|
}
|
|
124
139
|
nativeView.setId(this._androidViewId);
|
|
140
|
+
// Don't setup search here - wait for onLoaded when context is properly available
|
|
125
141
|
}
|
|
126
142
|
disposeNativeView() {
|
|
127
143
|
const nativeView = this.nativeViewProtected;
|
|
@@ -132,13 +148,40 @@ export class ListView extends ListViewBase {
|
|
|
132
148
|
if (nativeView.adapter) {
|
|
133
149
|
nativeView.adapter.owner = null;
|
|
134
150
|
}
|
|
151
|
+
// Cleanup search
|
|
152
|
+
this._cleanupSearchView();
|
|
153
|
+
// Cleanup sticky header
|
|
154
|
+
this._cleanupStickyHeader();
|
|
135
155
|
this.clearRealizedCells();
|
|
136
156
|
super.disposeNativeView();
|
|
137
157
|
}
|
|
158
|
+
_cleanupStickyHeader() {
|
|
159
|
+
// Remove scroll listener
|
|
160
|
+
if (this._scrollListener) {
|
|
161
|
+
this.nativeViewProtected.setOnScrollListener(null);
|
|
162
|
+
this._scrollListener = null;
|
|
163
|
+
}
|
|
164
|
+
// Remove sticky header from parent
|
|
165
|
+
if (this._stickyHeaderView && this._stickyHeaderView.parent) {
|
|
166
|
+
this._stickyHeaderView.parent._removeView(this._stickyHeaderView);
|
|
167
|
+
}
|
|
168
|
+
this._stickyHeaderView = null;
|
|
169
|
+
this._stickyHeaderHeight = 0;
|
|
170
|
+
// Clear hidden headers
|
|
171
|
+
this._hiddenHeaderPositions.clear();
|
|
172
|
+
}
|
|
138
173
|
onLoaded() {
|
|
139
174
|
super.onLoaded();
|
|
140
175
|
// Without this call itemClick won't be fired... :(
|
|
141
176
|
this.requestLayout();
|
|
177
|
+
// Setup sticky header if enabled
|
|
178
|
+
if (this.stickyHeader && this.sectioned && this.stickyHeaderTemplate) {
|
|
179
|
+
this._setupStickyHeader();
|
|
180
|
+
}
|
|
181
|
+
// Setup search if enabled and not already set up
|
|
182
|
+
if (this.showSearch && !this._searchView && this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
|
|
183
|
+
this._setupSearchView();
|
|
184
|
+
}
|
|
142
185
|
}
|
|
143
186
|
refresh() {
|
|
144
187
|
const nativeView = this.nativeViewProtected;
|
|
@@ -151,7 +194,19 @@ export class ListView extends ListViewBase {
|
|
|
151
194
|
view.bindingContext = null;
|
|
152
195
|
}
|
|
153
196
|
});
|
|
154
|
-
|
|
197
|
+
// Safely refresh the adapter - no HeaderViewListAdapter issues since we don't use headers
|
|
198
|
+
const adapter = nativeView.getAdapter();
|
|
199
|
+
if (adapter instanceof android.widget.BaseAdapter) {
|
|
200
|
+
try {
|
|
201
|
+
adapter.notifyDataSetChanged();
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
if (Trace.isEnabled()) {
|
|
205
|
+
Trace.error('Error refreshing adapter, recreating: ' + error);
|
|
206
|
+
}
|
|
207
|
+
nativeView.setAdapter(new ListViewAdapterClass(this));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
155
210
|
}
|
|
156
211
|
scrollToIndex(index) {
|
|
157
212
|
const nativeView = this.nativeViewProtected;
|
|
@@ -212,6 +267,217 @@ export class ListView extends ListViewBase {
|
|
|
212
267
|
const end = nativeView.getLastVisiblePosition();
|
|
213
268
|
return index >= start && index <= end;
|
|
214
269
|
}
|
|
270
|
+
// Sticky header methods
|
|
271
|
+
_setupStickyHeader() {
|
|
272
|
+
if (!this.stickyHeader || !this.sectioned || !this.stickyHeaderTemplate) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// Create the sticky header view
|
|
276
|
+
this._createStickyHeaderView();
|
|
277
|
+
// Add it as an overlay to the parent
|
|
278
|
+
this._addStickyHeaderToParent();
|
|
279
|
+
// Add padding to ListView so content doesn't hide behind sticky header
|
|
280
|
+
this._addListViewPadding();
|
|
281
|
+
// Setup scroll listener to update header content
|
|
282
|
+
this._setupScrollListener();
|
|
283
|
+
}
|
|
284
|
+
_createStickyHeaderView() {
|
|
285
|
+
if (this._stickyHeaderView) {
|
|
286
|
+
return; // Already created
|
|
287
|
+
}
|
|
288
|
+
// Create header view using the same template as section headers
|
|
289
|
+
if (typeof this.stickyHeaderTemplate === 'string') {
|
|
290
|
+
try {
|
|
291
|
+
this._stickyHeaderView = Builder.parse(this.stickyHeaderTemplate, this);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
// Fallback to simple label
|
|
295
|
+
this._stickyHeaderView = new Label();
|
|
296
|
+
this._stickyHeaderView.text = 'Header Error';
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (!this._stickyHeaderView) {
|
|
300
|
+
// Default header
|
|
301
|
+
this._stickyHeaderView = new Label();
|
|
302
|
+
this._stickyHeaderView.text = 'Section 0';
|
|
303
|
+
}
|
|
304
|
+
// Set initial binding context (section 0)
|
|
305
|
+
this._updateStickyHeader(0);
|
|
306
|
+
}
|
|
307
|
+
_addStickyHeaderToParent() {
|
|
308
|
+
if (!this._stickyHeaderView || !this.parent) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
// Remove from current parent if it has one (likely the ListView from Builder.parse)
|
|
312
|
+
if (this._stickyHeaderView.parent) {
|
|
313
|
+
this._stickyHeaderView.parent._removeView(this._stickyHeaderView);
|
|
314
|
+
}
|
|
315
|
+
// Set proper sizing - don't stretch to fill parent
|
|
316
|
+
this._stickyHeaderView.width = { unit: '%', value: 100 };
|
|
317
|
+
this._stickyHeaderView.height = 'auto'; // Let it size to content
|
|
318
|
+
this._stickyHeaderView.verticalAlignment = 'top';
|
|
319
|
+
this._stickyHeaderView.horizontalAlignment = 'stretch';
|
|
320
|
+
// Add sticky header to the parent layout
|
|
321
|
+
// If search view exists, position sticky header after it (index 1), otherwise at top (index 0)
|
|
322
|
+
const parentLayout = this.parent;
|
|
323
|
+
const hasSearchView = this.showSearch && this._searchView && this._searchView._wrapper;
|
|
324
|
+
if (parentLayout instanceof StackLayout) {
|
|
325
|
+
const insertIndex = hasSearchView ? 1 : 0;
|
|
326
|
+
parentLayout.insertChild(this._stickyHeaderView, insertIndex);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
parentLayout._addView(this._stickyHeaderView);
|
|
330
|
+
}
|
|
331
|
+
// When search is enabled, position sticky header below search view with proper top margin
|
|
332
|
+
if (this.showSearch && this._searchView) {
|
|
333
|
+
// Add top margin to push sticky header below search view
|
|
334
|
+
this._stickyHeaderView.marginTop = 0; // Reset any previous margin
|
|
335
|
+
// Position sticky header with proper offset using native positioning
|
|
336
|
+
if (this._stickyHeaderView.nativeViewProtected) {
|
|
337
|
+
this._stickyHeaderView.nativeViewProtected.setZ(STICKY_HEADER_Z_INDEX);
|
|
338
|
+
// Use a timeout to ensure search view is measured first
|
|
339
|
+
setTimeout(() => {
|
|
340
|
+
if (this._searchView && this._searchView._wrapper) {
|
|
341
|
+
const searchWrapper = this._searchView._wrapper;
|
|
342
|
+
if (searchWrapper.nativeViewProtected) {
|
|
343
|
+
const searchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight() || 50;
|
|
344
|
+
// Position sticky header below search view using translation
|
|
345
|
+
if (this._stickyHeaderView.nativeViewProtected) {
|
|
346
|
+
this._stickyHeaderView.nativeViewProtected.setTranslationY(searchHeight);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}, 100);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
// No search view - position at top
|
|
355
|
+
if (this._stickyHeaderView.nativeViewProtected) {
|
|
356
|
+
this._stickyHeaderView.nativeViewProtected.setZ(STICKY_HEADER_Z_INDEX);
|
|
357
|
+
this._stickyHeaderView.nativeViewProtected.setTranslationY(0);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
_addListViewPadding() {
|
|
362
|
+
if (!this._stickyHeaderView) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
// Calculate total top padding: search view height + sticky header height
|
|
366
|
+
let searchViewHeight = 0;
|
|
367
|
+
if (this.showSearch && this._searchView && this._searchView._wrapper) {
|
|
368
|
+
const searchWrapper = this._searchView._wrapper;
|
|
369
|
+
if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
|
|
370
|
+
searchViewHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
searchViewHeight = 50; // Default search view height
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Apply immediate padding with defaults to prevent content hiding
|
|
377
|
+
const defaultHeaderHeight = 50; // Reasonable default height in dp
|
|
378
|
+
const totalPadding = searchViewHeight + defaultHeaderHeight;
|
|
379
|
+
this.nativeViewProtected.setPadding(0, totalPadding, 0, 0);
|
|
380
|
+
this._stickyHeaderHeight = defaultHeaderHeight;
|
|
381
|
+
// Request layout to ensure proper measurement
|
|
382
|
+
this._stickyHeaderView.requestLayout();
|
|
383
|
+
// Then measure and adjust padding if needed using a layout listener for determinism
|
|
384
|
+
const stickyHeaderNativeView = this._stickyHeaderView && this._stickyHeaderView.nativeViewProtected;
|
|
385
|
+
if (stickyHeaderNativeView) {
|
|
386
|
+
const layoutListener = new android.view.View.OnLayoutChangeListener({
|
|
387
|
+
onLayoutChange: (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) => {
|
|
388
|
+
if (v.getMeasuredHeight() > 0) {
|
|
389
|
+
const measuredHeaderHeight = v.getMeasuredHeight();
|
|
390
|
+
let finalSearchHeight = searchViewHeight;
|
|
391
|
+
// Re-measure search view if needed
|
|
392
|
+
if (this.showSearch && this._searchView && this._searchView._wrapper) {
|
|
393
|
+
const searchWrapper = this._searchView._wrapper;
|
|
394
|
+
if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
|
|
395
|
+
finalSearchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Calculate final padding: search height + sticky header height + small buffer
|
|
399
|
+
const totalPaddingHeight = finalSearchHeight + measuredHeaderHeight + 4;
|
|
400
|
+
this._stickyHeaderHeight = measuredHeaderHeight;
|
|
401
|
+
this.nativeViewProtected.setPadding(0, totalPaddingHeight, 0, 0);
|
|
402
|
+
this.scrollToIndex(0);
|
|
403
|
+
// Remove the listener after first valid layout
|
|
404
|
+
v.removeOnLayoutChangeListener(layoutListener);
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
stickyHeaderNativeView.addOnLayoutChangeListener(layoutListener);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
_setupScrollListener() {
|
|
412
|
+
if (this._scrollListener) {
|
|
413
|
+
return; // Already setup
|
|
414
|
+
}
|
|
415
|
+
const owner = this;
|
|
416
|
+
this._scrollListener = new android.widget.AbsListView.OnScrollListener({
|
|
417
|
+
onScrollStateChanged(view, scrollState) {
|
|
418
|
+
// Not needed for sticky headers
|
|
419
|
+
},
|
|
420
|
+
onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount) {
|
|
421
|
+
if (owner.sectioned && owner._stickyHeaderView) {
|
|
422
|
+
const currentSection = owner._getCurrentSection(firstVisibleItem);
|
|
423
|
+
owner._updateStickyHeader(currentSection);
|
|
424
|
+
// Hide section headers when they would appear right below sticky header
|
|
425
|
+
owner._updateHiddenHeaders(firstVisibleItem);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
this.nativeViewProtected.setOnScrollListener(this._scrollListener);
|
|
430
|
+
}
|
|
431
|
+
_getCurrentSection(firstVisibleItem) {
|
|
432
|
+
if (!this.sectioned) {
|
|
433
|
+
return 0;
|
|
434
|
+
}
|
|
435
|
+
// Convert the first visible list position to section number
|
|
436
|
+
let currentPosition = 0;
|
|
437
|
+
const sectionCount = this._getSectionCount();
|
|
438
|
+
for (let section = 0; section < sectionCount; section++) {
|
|
439
|
+
// Check if firstVisibleItem is in this section (header or items)
|
|
440
|
+
const sectionItems = this._getItemsInSection(section) || [];
|
|
441
|
+
const itemsInSection = sectionItems.length || 0;
|
|
442
|
+
const sectionEndPosition = currentPosition + 1 + itemsInSection; // +1 for header
|
|
443
|
+
if (firstVisibleItem < sectionEndPosition) {
|
|
444
|
+
return section;
|
|
445
|
+
}
|
|
446
|
+
currentPosition = sectionEndPosition;
|
|
447
|
+
}
|
|
448
|
+
return Math.max(0, sectionCount - 1); // Fallback to last section
|
|
449
|
+
}
|
|
450
|
+
_updateStickyHeader(section) {
|
|
451
|
+
if (!this._stickyHeaderView) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// Update binding context to match the current section
|
|
455
|
+
const sectionData = this._getSectionData(section);
|
|
456
|
+
if (sectionData) {
|
|
457
|
+
this._stickyHeaderView.bindingContext = sectionData;
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
this._stickyHeaderView.bindingContext = { title: `Section ${section}`, section: section };
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
_updateHiddenHeaders(firstVisibleItem) {
|
|
464
|
+
const previousHiddenHeaders = new Set(this._hiddenHeaderPositions);
|
|
465
|
+
this._hiddenHeaderPositions.clear();
|
|
466
|
+
// If we're at the very top (first item is position 0, which is the first section header),
|
|
467
|
+
// hide that section header to avoid duplication with sticky header
|
|
468
|
+
if (firstVisibleItem === 0) {
|
|
469
|
+
this._hiddenHeaderPositions.add(0); // Hide the first section header position
|
|
470
|
+
}
|
|
471
|
+
// If hidden headers changed, refresh the adapter
|
|
472
|
+
const hiddenHeadersChanged = previousHiddenHeaders.size !== this._hiddenHeaderPositions.size || [...previousHiddenHeaders].some((pos) => !this._hiddenHeaderPositions.has(pos));
|
|
473
|
+
if (hiddenHeadersChanged) {
|
|
474
|
+
// Refresh adapter to update visibility
|
|
475
|
+
const adapter = this.nativeViewProtected.getAdapter();
|
|
476
|
+
if (adapter instanceof android.widget.BaseAdapter) {
|
|
477
|
+
adapter.notifyDataSetChanged();
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
215
481
|
[separatorColorProperty.getDefault]() {
|
|
216
482
|
const nativeView = this.nativeViewProtected;
|
|
217
483
|
return {
|
|
@@ -238,8 +504,199 @@ export class ListView extends ListViewBase {
|
|
|
238
504
|
if (value) {
|
|
239
505
|
this._itemTemplatesInternal = this._itemTemplatesInternal.concat(value);
|
|
240
506
|
}
|
|
241
|
-
this.nativeViewProtected
|
|
242
|
-
|
|
507
|
+
if (this.nativeViewProtected) {
|
|
508
|
+
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
|
509
|
+
this.refresh();
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// Sticky header property handlers
|
|
513
|
+
[stickyHeaderProperty.setNative](value) {
|
|
514
|
+
// Refresh adapter to handle sectioned vs non-sectioned display
|
|
515
|
+
if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
|
|
516
|
+
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
|
517
|
+
}
|
|
518
|
+
// Setup or cleanup sticky header
|
|
519
|
+
if (value && this.sectioned && this.stickyHeaderTemplate && this.isLoaded) {
|
|
520
|
+
this._setupStickyHeader();
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
this._cleanupStickyHeader();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
[stickyHeaderTemplateProperty.setNative](value) {
|
|
527
|
+
// Refresh adapter when template changes
|
|
528
|
+
if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
|
|
529
|
+
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
|
530
|
+
}
|
|
531
|
+
// Recreate sticky header with new template
|
|
532
|
+
this._cleanupStickyHeader();
|
|
533
|
+
if (value && this.stickyHeader && this.sectioned && this.isLoaded) {
|
|
534
|
+
this._setupStickyHeader();
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
[sectionedProperty.setNative](value) {
|
|
538
|
+
// Refresh adapter to handle sectioned vs non-sectioned data
|
|
539
|
+
if (this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
|
|
540
|
+
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
|
541
|
+
}
|
|
542
|
+
// Setup or cleanup sticky header based on sectioned state
|
|
543
|
+
if (value && this.stickyHeader && this.stickyHeaderTemplate && this.isLoaded) {
|
|
544
|
+
this._setupStickyHeader();
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
this._cleanupStickyHeader();
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
// Search methods
|
|
551
|
+
_setupSearchView() {
|
|
552
|
+
if (this._searchView || !this.showSearch || !this.nativeViewProtected) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
// Create SearchView using the ListView's context
|
|
556
|
+
this._searchView = new android.widget.SearchView(this.nativeViewProtected.getContext());
|
|
557
|
+
this._searchView.setQueryHint('Search...');
|
|
558
|
+
this._searchView.setIconifiedByDefault(false);
|
|
559
|
+
this._searchView.setSubmitButtonEnabled(false);
|
|
560
|
+
// Setup search listener
|
|
561
|
+
const owner = this;
|
|
562
|
+
this._searchListener = new android.widget.SearchView.OnQueryTextListener({
|
|
563
|
+
onQueryTextChange(newText) {
|
|
564
|
+
const args = {
|
|
565
|
+
eventName: SEARCHCHANGE,
|
|
566
|
+
object: owner,
|
|
567
|
+
text: newText,
|
|
568
|
+
android: owner._searchView,
|
|
569
|
+
};
|
|
570
|
+
owner.notify(args);
|
|
571
|
+
return true;
|
|
572
|
+
},
|
|
573
|
+
onQueryTextSubmit(query) {
|
|
574
|
+
const args = {
|
|
575
|
+
eventName: SEARCHCHANGE,
|
|
576
|
+
object: owner,
|
|
577
|
+
text: query,
|
|
578
|
+
android: owner._searchView,
|
|
579
|
+
};
|
|
580
|
+
owner.notify(args);
|
|
581
|
+
return true;
|
|
582
|
+
},
|
|
583
|
+
});
|
|
584
|
+
this._searchView.setOnQueryTextListener(this._searchListener);
|
|
585
|
+
// Add search view to the parent container above the ListView
|
|
586
|
+
this._addSearchToParent();
|
|
587
|
+
// Add padding to ListView if no sticky header (otherwise sticky header method handles it)
|
|
588
|
+
if (!this.stickyHeader || !this._stickyHeaderView) {
|
|
589
|
+
this._addSearchPadding();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
_addSearchPadding() {
|
|
593
|
+
if (!this._searchView) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
// Add basic padding for search view
|
|
597
|
+
const defaultSearchHeight = 50; // Default search view height
|
|
598
|
+
this.nativeViewProtected.setPadding(0, defaultSearchHeight, 0, 0);
|
|
599
|
+
// Measure and adjust if needed
|
|
600
|
+
setTimeout(() => {
|
|
601
|
+
if (this._searchView && this._searchView._wrapper) {
|
|
602
|
+
const searchWrapper = this._searchView._wrapper;
|
|
603
|
+
if (searchWrapper.nativeViewProtected && searchWrapper.nativeViewProtected.getMeasuredHeight() > 0) {
|
|
604
|
+
const measuredHeight = searchWrapper.nativeViewProtected.getMeasuredHeight();
|
|
605
|
+
this.nativeViewProtected.setPadding(0, measuredHeight + 4, 0, 0);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}, 100);
|
|
609
|
+
}
|
|
610
|
+
_addSearchToParent() {
|
|
611
|
+
if (!this._searchView || !this.parent) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
// Get the parent layout
|
|
615
|
+
const parentLayout = this.parent;
|
|
616
|
+
// Create a simple NativeScript wrapper for the native SearchView
|
|
617
|
+
const searchView = this._searchView;
|
|
618
|
+
const searchViewWrapper = new (class extends View {
|
|
619
|
+
createNativeView() {
|
|
620
|
+
return searchView;
|
|
621
|
+
}
|
|
622
|
+
})();
|
|
623
|
+
// Set layout properties - ensure it's at the top
|
|
624
|
+
searchViewWrapper.height = 'auto';
|
|
625
|
+
searchViewWrapper.width = { unit: '%', value: 100 };
|
|
626
|
+
searchViewWrapper.verticalAlignment = 'top';
|
|
627
|
+
searchViewWrapper.horizontalAlignment = 'stretch';
|
|
628
|
+
// Always insert at position 0 (top) regardless of ListView position
|
|
629
|
+
if (parentLayout instanceof StackLayout) {
|
|
630
|
+
parentLayout.insertChild(searchViewWrapper, 0);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
// For other layout types, add as first child
|
|
634
|
+
parentLayout._addView(searchViewWrapper);
|
|
635
|
+
}
|
|
636
|
+
// Ensure search view appears above everything else
|
|
637
|
+
if (searchViewWrapper.nativeViewProtected) {
|
|
638
|
+
searchViewWrapper.nativeViewProtected.setZ(SEARCH_VIEW_Z_INDEX);
|
|
639
|
+
}
|
|
640
|
+
// Store reference for cleanup
|
|
641
|
+
this._searchView._wrapper = searchViewWrapper;
|
|
642
|
+
}
|
|
643
|
+
_cleanupSearchView() {
|
|
644
|
+
if (this._searchView) {
|
|
645
|
+
// Remove search view wrapper from parent
|
|
646
|
+
const wrapper = this._searchView._wrapper;
|
|
647
|
+
if (wrapper && wrapper.parent) {
|
|
648
|
+
wrapper.parent._removeView(wrapper);
|
|
649
|
+
}
|
|
650
|
+
// Clear listener
|
|
651
|
+
if (this._searchListener) {
|
|
652
|
+
this._searchView.setOnQueryTextListener(null);
|
|
653
|
+
this._searchListener = null;
|
|
654
|
+
}
|
|
655
|
+
this._searchView = null;
|
|
656
|
+
// Reset ListView padding if no sticky header
|
|
657
|
+
if (!this.stickyHeader || !this._stickyHeaderView) {
|
|
658
|
+
this.nativeViewProtected.setPadding(0, 0, 0, 0);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
[showSearchProperty.setNative](value) {
|
|
663
|
+
if (value) {
|
|
664
|
+
if (this.isLoaded && this.nativeViewProtected && this.nativeViewProtected.getAdapter()) {
|
|
665
|
+
this._setupSearchView();
|
|
666
|
+
// Reposition sticky header if it exists
|
|
667
|
+
if (this._stickyHeaderView) {
|
|
668
|
+
this._repositionStickyHeader();
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
this._cleanupSearchView();
|
|
674
|
+
// Reposition sticky header if it exists
|
|
675
|
+
if (this._stickyHeaderView) {
|
|
676
|
+
this._repositionStickyHeader();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
_repositionStickyHeader() {
|
|
681
|
+
if (!this._stickyHeaderView || !this._stickyHeaderView.nativeViewProtected) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
// Reset positioning
|
|
685
|
+
this._stickyHeaderView.nativeViewProtected.setTranslationY(0);
|
|
686
|
+
// If search is enabled, position below search view
|
|
687
|
+
if (this.showSearch && this._searchView && this._searchView._wrapper) {
|
|
688
|
+
setTimeout(() => {
|
|
689
|
+
const searchWrapper = this._searchView._wrapper;
|
|
690
|
+
if (searchWrapper.nativeViewProtected) {
|
|
691
|
+
const searchHeight = searchWrapper.nativeViewProtected.getMeasuredHeight() || 50;
|
|
692
|
+
this._stickyHeaderView.nativeViewProtected.setTranslationY(searchHeight);
|
|
693
|
+
}
|
|
694
|
+
}, 100);
|
|
695
|
+
}
|
|
696
|
+
// Update ListView padding
|
|
697
|
+
if (this.stickyHeader && this._stickyHeaderView) {
|
|
698
|
+
this._addListViewPadding();
|
|
699
|
+
}
|
|
243
700
|
}
|
|
244
701
|
}
|
|
245
702
|
__decorate([
|
|
@@ -253,116 +710,295 @@ function ensureListViewAdapterClass() {
|
|
|
253
710
|
if (ListViewAdapterClass) {
|
|
254
711
|
return;
|
|
255
712
|
}
|
|
256
|
-
var ListViewAdapter =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
ListViewAdapter.prototype.getCount = function () {
|
|
264
|
-
return this.owner && this.owner.items && this.owner.items.length ? this.owner.items.length : 0;
|
|
265
|
-
};
|
|
266
|
-
ListViewAdapter.prototype.getItem = function (i) {
|
|
267
|
-
if (this.owner && this.owner.items && i < this.owner.items.length) {
|
|
268
|
-
var getItem = this.owner.items.getItem;
|
|
269
|
-
return getItem ? getItem.call(this.owner.items, i) : this.owner.items[i];
|
|
713
|
+
var ListViewAdapter = (function (_super) {
|
|
714
|
+
__extends(ListViewAdapter, _super);
|
|
715
|
+
function ListViewAdapter(owner) {
|
|
716
|
+
var _this = _super.call(this) || this;
|
|
717
|
+
_this.owner = owner;
|
|
718
|
+
return global.__native(_this);
|
|
270
719
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
720
|
+
ListViewAdapter.prototype.getCount = function () {
|
|
721
|
+
if (!this.owner) {
|
|
722
|
+
return 0;
|
|
723
|
+
}
|
|
724
|
+
var count = 0;
|
|
725
|
+
if (this.owner.sectioned) {
|
|
726
|
+
var sectionCount = this.owner._getSectionCount();
|
|
727
|
+
if (!this.owner.items || sectionCount <= 0) {
|
|
728
|
+
return 0;
|
|
729
|
+
}
|
|
730
|
+
for (var i = 0; i < sectionCount; i++) {
|
|
731
|
+
var itemsInSection = this.owner._getItemsInSection(i) || [];
|
|
732
|
+
if (itemsInSection.length > 0) {
|
|
733
|
+
count += 1;
|
|
734
|
+
count += itemsInSection.length;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
var src = this.owner.items;
|
|
740
|
+
count = src && typeof src.length === "number" ? src.length : 0;
|
|
741
|
+
}
|
|
742
|
+
return Math.max(0, count);
|
|
743
|
+
};
|
|
744
|
+
ListViewAdapter.prototype.getItem = function (i) {
|
|
745
|
+
if (!this.owner || !this.owner.items) {
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
var totalCount = this.getCount();
|
|
749
|
+
if (i < 0 || i >= totalCount) {
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
if (this.owner.sectioned) {
|
|
753
|
+
var positionInfo = this._getPositionInfo(i);
|
|
754
|
+
if (positionInfo.isHeader) {
|
|
755
|
+
return this.owner._getSectionData(positionInfo.section);
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
return this.owner._getDataItemInSection(positionInfo.section, positionInfo.itemIndex);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
var src = this.owner.items;
|
|
763
|
+
if (src && typeof src.length === "number" && i < src.length) {
|
|
764
|
+
var getItem = src.getItem;
|
|
765
|
+
return getItem ? getItem.call(src, i) : src[i];
|
|
766
|
+
}
|
|
767
|
+
}
|
|
295
768
|
return null;
|
|
296
|
-
}
|
|
297
|
-
var totalItemCount = this.owner.items ? this.owner.items.length : 0;
|
|
298
|
-
if (index === totalItemCount - 1) {
|
|
299
|
-
this.owner.notify({
|
|
300
|
-
eventName: LOADMOREITEMS,
|
|
301
|
-
object: this.owner,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
// Recycle an existing view or create a new one if needed.
|
|
305
|
-
var template = this.owner._getItemTemplate(index);
|
|
306
|
-
var view;
|
|
307
|
-
// convertView is of the wrong type
|
|
308
|
-
if (convertView && this.owner._getKeyFromView(convertView) !== template.key) {
|
|
309
|
-
this.owner._markViewUnused(convertView); // release this view
|
|
310
|
-
convertView = this.owner._getAvailableView(template.key); // get a view from the right type or null
|
|
311
|
-
}
|
|
312
|
-
if (convertView) {
|
|
313
|
-
view = this.owner._realizedItems.get(convertView).view;
|
|
314
|
-
}
|
|
315
|
-
if (!view) {
|
|
316
|
-
view = template.createView();
|
|
317
|
-
}
|
|
318
|
-
var args = {
|
|
319
|
-
eventName: ITEMLOADING,
|
|
320
|
-
object: this.owner,
|
|
321
|
-
index: index,
|
|
322
|
-
view: view,
|
|
323
|
-
android: parent,
|
|
324
|
-
ios: undefined,
|
|
325
769
|
};
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
770
|
+
ListViewAdapter.prototype._getPositionInfo = function (position) {
|
|
771
|
+
if (!this.owner.sectioned) {
|
|
772
|
+
return { isHeader: false, section: 0, itemIndex: position };
|
|
773
|
+
}
|
|
774
|
+
var currentPosition = 0;
|
|
775
|
+
var sectionCount = this.owner._getSectionCount();
|
|
776
|
+
for (var section = 0; section < sectionCount; section++) {
|
|
777
|
+
var itemsInSection = this.owner._getItemsInSection(section) || [];
|
|
778
|
+
if (itemsInSection.length === 0) {
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (currentPosition === position) {
|
|
782
|
+
return { isHeader: true, section: section, itemIndex: -1 };
|
|
783
|
+
}
|
|
784
|
+
currentPosition++;
|
|
785
|
+
if (position < currentPosition + itemsInSection.length) {
|
|
786
|
+
var itemIndex = position - currentPosition;
|
|
787
|
+
return { isHeader: false, section: section, itemIndex: itemIndex };
|
|
788
|
+
}
|
|
789
|
+
currentPosition += itemsInSection.length;
|
|
790
|
+
}
|
|
791
|
+
return { isHeader: false, section: 0, itemIndex: 0 };
|
|
792
|
+
};
|
|
793
|
+
ListViewAdapter.prototype.getItemId = function (i) {
|
|
794
|
+
var item = this.getItem(i);
|
|
795
|
+
var id = i;
|
|
796
|
+
if (this.owner && item && this.owner.items) {
|
|
797
|
+
id = this.owner.itemIdGenerator(item, i, this.owner.items);
|
|
798
|
+
}
|
|
799
|
+
return long(id);
|
|
800
|
+
};
|
|
801
|
+
ListViewAdapter.prototype.hasStableIds = function () {
|
|
802
|
+
return true;
|
|
803
|
+
};
|
|
804
|
+
ListViewAdapter.prototype.isEnabled = function (position) {
|
|
805
|
+
var totalCount = this.getCount();
|
|
806
|
+
if (totalCount === 0 || position < 0 || position >= totalCount) {
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
if (this.owner.sectioned) {
|
|
810
|
+
var positionInfo = this._getPositionInfo(position);
|
|
811
|
+
return !positionInfo.isHeader;
|
|
812
|
+
}
|
|
813
|
+
return true;
|
|
814
|
+
};
|
|
815
|
+
ListViewAdapter.prototype.getViewTypeCount = function () {
|
|
816
|
+
var count = this.owner._itemTemplatesInternal.length;
|
|
817
|
+
if (this.owner.sectioned && this.owner.stickyHeaderTemplate) {
|
|
818
|
+
count += 1;
|
|
819
|
+
}
|
|
820
|
+
return count;
|
|
821
|
+
};
|
|
822
|
+
ListViewAdapter.prototype.getItemViewType = function (index) {
|
|
823
|
+
if (this.owner.sectioned) {
|
|
824
|
+
var positionInfo = this._getPositionInfo(index);
|
|
825
|
+
if (positionInfo.isHeader) {
|
|
826
|
+
return this.owner._itemTemplatesInternal.length;
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
var template = this.owner._getItemTemplate(positionInfo.itemIndex);
|
|
830
|
+
return this.owner._itemTemplatesInternal.indexOf(template);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
var template = this.owner._getItemTemplate(index);
|
|
835
|
+
return this.owner._itemTemplatesInternal.indexOf(template);
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
ListViewAdapter.prototype.getView = function (index, convertView, parent) {
|
|
839
|
+
if (!this.owner) {
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
842
|
+
var totalCount = this.getCount();
|
|
843
|
+
if (index < 0 || index >= totalCount) {
|
|
844
|
+
var emptyView = new android.view.View(this.owner._context);
|
|
845
|
+
var layoutParams = new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 0);
|
|
846
|
+
emptyView.setLayoutParams(layoutParams);
|
|
847
|
+
return emptyView;
|
|
848
|
+
}
|
|
849
|
+
if (index === totalCount - 1) {
|
|
850
|
+
this.owner.notify({
|
|
851
|
+
eventName: LOADMOREITEMS,
|
|
852
|
+
object: this.owner,
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
if (this.owner.sectioned) {
|
|
856
|
+
var positionInfo = this._getPositionInfo(index);
|
|
857
|
+
if (positionInfo.isHeader) {
|
|
858
|
+
return this._createHeaderView(positionInfo.section, convertView, parent, index);
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
return this._createItemView(positionInfo.section, positionInfo.itemIndex, convertView, parent);
|
|
862
|
+
}
|
|
333
863
|
}
|
|
334
864
|
else {
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
865
|
+
return this._createItemView(0, index, convertView, parent);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
ListViewAdapter.prototype._createHeaderView = function (section, convertView, parent, index) {
|
|
869
|
+
if (this.owner._hiddenHeaderPositions.has(index)) {
|
|
870
|
+
var emptyView = new android.view.View(this.owner._context);
|
|
871
|
+
var layoutParams = new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 0);
|
|
872
|
+
emptyView.setLayoutParams(layoutParams);
|
|
873
|
+
return emptyView;
|
|
874
|
+
}
|
|
875
|
+
var headerView = null;
|
|
876
|
+
var headerViewType = this.owner._itemTemplatesInternal.length;
|
|
877
|
+
if (convertView) {
|
|
878
|
+
var existingData = this.owner._realizedItems.get(convertView);
|
|
879
|
+
if (existingData && existingData.templateKey === "header_".concat(headerViewType)) {
|
|
880
|
+
headerView = existingData.view;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
if (!headerView) {
|
|
884
|
+
if (this.owner.stickyHeaderTemplate) {
|
|
885
|
+
if (typeof this.owner.stickyHeaderTemplate === "string") {
|
|
886
|
+
try {
|
|
887
|
+
headerView = Builder.parse(this.owner.stickyHeaderTemplate, this.owner);
|
|
888
|
+
}
|
|
889
|
+
catch (error) {
|
|
890
|
+
headerView = new Label();
|
|
891
|
+
headerView.text = "Header Error";
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
if (!headerView) {
|
|
896
|
+
headerView = new Label();
|
|
897
|
+
headerView.text = "Section ".concat(section);
|
|
898
|
+
}
|
|
899
|
+
if (!headerView.parent) {
|
|
900
|
+
if (headerView instanceof LayoutBase && !(headerView instanceof ProxyViewContainer)) {
|
|
901
|
+
this.owner._addView(headerView);
|
|
902
|
+
convertView = headerView.nativeViewProtected;
|
|
903
|
+
}
|
|
904
|
+
else {
|
|
905
|
+
var sp = new StackLayout();
|
|
906
|
+
sp.addChild(headerView);
|
|
907
|
+
this.owner._addView(sp);
|
|
908
|
+
convertView = sp.nativeViewProtected;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
this.owner._realizedItems.set(convertView, {
|
|
912
|
+
view: headerView,
|
|
913
|
+
templateKey: "header_".concat(headerViewType),
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
var sectionData = this.owner._getSectionData(section);
|
|
917
|
+
if (sectionData) {
|
|
918
|
+
headerView.bindingContext = sectionData;
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
headerView.bindingContext = { title: "Section ".concat(section), section: section };
|
|
922
|
+
}
|
|
923
|
+
return convertView;
|
|
924
|
+
};
|
|
925
|
+
ListViewAdapter.prototype._createItemView = function (section, itemIndex, convertView, parent) {
|
|
926
|
+
var template = this.owner._getItemTemplate(itemIndex);
|
|
927
|
+
var view;
|
|
928
|
+
if (convertView && this.owner._getKeyFromView(convertView) !== template.key) {
|
|
929
|
+
this.owner._markViewUnused(convertView);
|
|
930
|
+
convertView = this.owner._getAvailableView(template.key);
|
|
931
|
+
}
|
|
932
|
+
if (convertView) {
|
|
933
|
+
view = this.owner._realizedItems.get(convertView).view;
|
|
934
|
+
}
|
|
935
|
+
if (!view) {
|
|
936
|
+
view = template.createView();
|
|
937
|
+
}
|
|
938
|
+
var args = {
|
|
939
|
+
eventName: ITEMLOADING,
|
|
940
|
+
object: this.owner,
|
|
941
|
+
index: itemIndex,
|
|
942
|
+
view: view,
|
|
943
|
+
android: parent,
|
|
944
|
+
ios: undefined,
|
|
945
|
+
};
|
|
946
|
+
this.owner.notify(args);
|
|
947
|
+
if (!args.view) {
|
|
948
|
+
args.view = this.owner._getDefaultItemContent(itemIndex);
|
|
949
|
+
}
|
|
950
|
+
if (args.view) {
|
|
951
|
+
if (this.owner._effectiveRowHeight > -1) {
|
|
952
|
+
args.view.height = this.owner.rowHeight;
|
|
344
953
|
}
|
|
345
954
|
else {
|
|
346
|
-
|
|
347
|
-
sp.addChild(args.view);
|
|
348
|
-
this.owner._addView(sp);
|
|
349
|
-
convertView = sp.nativeViewProtected;
|
|
955
|
+
args.view.height = unsetValue;
|
|
350
956
|
}
|
|
957
|
+
if (this.owner.sectioned) {
|
|
958
|
+
this.owner._prepareItemInSection(args.view, section, itemIndex);
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
this.owner._prepareItem(args.view, itemIndex);
|
|
962
|
+
}
|
|
963
|
+
if (!args.view.parent) {
|
|
964
|
+
if (args.view instanceof LayoutBase && !(args.view instanceof ProxyViewContainer)) {
|
|
965
|
+
var mt = PercentLength.toDevicePixels(args.view.marginTop, 0, Number.NaN);
|
|
966
|
+
var mb = PercentLength.toDevicePixels(args.view.marginBottom, 0, Number.NaN);
|
|
967
|
+
var ml = PercentLength.toDevicePixels(args.view.marginLeft, 0, Number.NaN);
|
|
968
|
+
var mr = PercentLength.toDevicePixels(args.view.marginRight, 0, Number.NaN);
|
|
969
|
+
var hasMargins = mt > 0 || mb > 0 || ml > 0 || mr > 0;
|
|
970
|
+
if (hasMargins) {
|
|
971
|
+
var outer = new StackLayout();
|
|
972
|
+
outer.addChild(args.view);
|
|
973
|
+
this.owner._addView(outer);
|
|
974
|
+
convertView = outer.nativeViewProtected;
|
|
975
|
+
}
|
|
976
|
+
else {
|
|
977
|
+
this.owner._addView(args.view);
|
|
978
|
+
convertView = args.view.nativeViewProtected;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
var sp = new StackLayout();
|
|
983
|
+
sp.addChild(args.view);
|
|
984
|
+
this.owner._addView(sp);
|
|
985
|
+
convertView = sp.nativeViewProtected;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
this.owner._registerViewToTemplate(template.key, convertView, args.view);
|
|
989
|
+
this.owner._markViewUsed(convertView);
|
|
351
990
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
], ListViewAdapter.prototype, "getView", null);
|
|
364
|
-
return ListViewAdapter;
|
|
365
|
-
}(android.widget.BaseAdapter));
|
|
991
|
+
return convertView;
|
|
992
|
+
};
|
|
993
|
+
var _a, _b, _c, _d, _e, _f;
|
|
994
|
+
__decorate([
|
|
995
|
+
profile,
|
|
996
|
+
__metadata("design:type", Function),
|
|
997
|
+
__metadata("design:paramtypes", [Number, typeof (_b = typeof android !== "undefined" && (_a = android.view) !== void 0 && _a.View) === "function" ? _b : Object, typeof (_d = typeof android !== "undefined" && (_c = android.view) !== void 0 && _c.ViewGroup) === "function" ? _d : Object]),
|
|
998
|
+
__metadata("design:returntype", typeof (_f = typeof android !== "undefined" && (_e = android.view) !== void 0 && _e.View) === "function" ? _f : Object)
|
|
999
|
+
], ListViewAdapter.prototype, "getView", null);
|
|
1000
|
+
return ListViewAdapter;
|
|
1001
|
+
}(android.widget.BaseAdapter));
|
|
366
1002
|
ListViewAdapterClass = ListViewAdapter;
|
|
367
1003
|
}
|
|
368
1004
|
//# sourceMappingURL=index.android.js.map
|