@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,40 +1,40 @@
|
|
|
1
|
-
import { ListViewBase, separatorColorProperty, itemTemplatesProperty, iosEstimatedRowHeightProperty } from './list-view-common';
|
|
1
|
+
import { ListViewBase, separatorColorProperty, itemTemplatesProperty, iosEstimatedRowHeightProperty, stickyHeaderProperty, stickyHeaderTemplateProperty, stickyHeaderHeightProperty, sectionedProperty, showSearchProperty, searchAutoHideProperty } from './list-view-common';
|
|
2
2
|
import { View } from '../core/view';
|
|
3
3
|
import { Length } from '../styling/length-shared';
|
|
4
4
|
import { Observable } from '../../data/observable';
|
|
5
5
|
import { Color } from '../../color';
|
|
6
6
|
import { layout } from '../../utils';
|
|
7
|
+
import { SDK_VERSION } from '../../utils/constants';
|
|
7
8
|
import { StackLayout } from '../layouts/stack-layout';
|
|
8
9
|
import { ProxyViewContainer } from '../proxy-view-container';
|
|
9
10
|
import { profile } from '../../profiling';
|
|
10
11
|
import { Trace } from '../../trace';
|
|
12
|
+
import { Builder } from '../builder';
|
|
13
|
+
import { Label } from '../label';
|
|
14
|
+
import { isFunction } from '../../utils/types';
|
|
11
15
|
export * from './list-view-common';
|
|
12
16
|
const ITEMLOADING = ListViewBase.itemLoadingEvent;
|
|
13
17
|
const LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
|
|
14
18
|
const ITEMTAP = ListViewBase.itemTapEvent;
|
|
15
19
|
const DEFAULT_HEIGHT = 44;
|
|
16
20
|
const infinity = layout.makeMeasureSpec(0, layout.UNSPECIFIED);
|
|
17
|
-
var ListViewCell =
|
|
21
|
+
var ListViewCell = (function (_super) {
|
|
18
22
|
__extends(ListViewCell, _super);
|
|
19
23
|
function ListViewCell() {
|
|
20
24
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
21
25
|
}
|
|
22
26
|
ListViewCell.initWithEmptyBackground = function () {
|
|
23
27
|
var cell = ListViewCell.new();
|
|
24
|
-
// Clear background by default - this will make cells transparent
|
|
25
28
|
cell.backgroundColor = UIColor.clearColor;
|
|
26
29
|
return cell;
|
|
27
30
|
};
|
|
28
31
|
ListViewCell.prototype.initWithStyleReuseIdentifier = function (style, reuseIdentifier) {
|
|
29
32
|
var cell = _super.prototype.initWithStyleReuseIdentifier.call(this, style, reuseIdentifier);
|
|
30
|
-
// Clear background by default - this will make cells transparent
|
|
31
33
|
cell.backgroundColor = UIColor.clearColor;
|
|
32
34
|
return cell;
|
|
33
35
|
};
|
|
34
36
|
ListViewCell.prototype.willMoveToSuperview = function (newSuperview) {
|
|
35
37
|
var parent = (this.view ? this.view.parent : null);
|
|
36
|
-
// When inside ListView and there is no newSuperview this cell is
|
|
37
|
-
// removed from native visual tree so we remove it from our tree too.
|
|
38
38
|
if (parent && !newSuperview) {
|
|
39
39
|
parent._removeContainer(this);
|
|
40
40
|
}
|
|
@@ -48,11 +48,42 @@ var ListViewCell = /** @class */ (function (_super) {
|
|
|
48
48
|
});
|
|
49
49
|
return ListViewCell;
|
|
50
50
|
}(UITableViewCell));
|
|
51
|
+
var ListViewHeaderCell = (function (_super) {
|
|
52
|
+
__extends(ListViewHeaderCell, _super);
|
|
53
|
+
function ListViewHeaderCell() {
|
|
54
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
55
|
+
}
|
|
56
|
+
ListViewHeaderCell.initWithEmptyBackground = function () {
|
|
57
|
+
var cell = ListViewHeaderCell.new();
|
|
58
|
+
cell.backgroundColor = UIColor.clearColor;
|
|
59
|
+
return cell;
|
|
60
|
+
};
|
|
61
|
+
ListViewHeaderCell.prototype.initWithReuseIdentifier = function (reuseIdentifier) {
|
|
62
|
+
var cell = _super.prototype.initWithReuseIdentifier.call(this, reuseIdentifier);
|
|
63
|
+
cell.backgroundColor = UIColor.clearColor;
|
|
64
|
+
return cell;
|
|
65
|
+
};
|
|
66
|
+
ListViewHeaderCell.prototype.willMoveToSuperview = function (newSuperview) {
|
|
67
|
+
var parent = (this.view ? this.view.parent : null);
|
|
68
|
+
if (parent && !newSuperview) {
|
|
69
|
+
parent._removeHeaderContainer(this);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
Object.defineProperty(ListViewHeaderCell.prototype, "view", {
|
|
73
|
+
get: function () {
|
|
74
|
+
return this.owner ? this.owner.deref() : null;
|
|
75
|
+
},
|
|
76
|
+
enumerable: true,
|
|
77
|
+
configurable: true
|
|
78
|
+
});
|
|
79
|
+
return ListViewHeaderCell;
|
|
80
|
+
}(UITableViewHeaderFooterView));
|
|
51
81
|
function notifyForItemAtIndex(listView, cell, view, eventName, indexPath) {
|
|
52
82
|
const args = {
|
|
53
83
|
eventName: eventName,
|
|
54
84
|
object: listView,
|
|
55
85
|
index: indexPath.row,
|
|
86
|
+
section: indexPath.section,
|
|
56
87
|
view: view,
|
|
57
88
|
ios: cell,
|
|
58
89
|
android: undefined,
|
|
@@ -60,7 +91,7 @@ function notifyForItemAtIndex(listView, cell, view, eventName, indexPath) {
|
|
|
60
91
|
listView.notify(args);
|
|
61
92
|
return args;
|
|
62
93
|
}
|
|
63
|
-
var DataSource =
|
|
94
|
+
var DataSource = (function (_super) {
|
|
64
95
|
__extends(DataSource, _super);
|
|
65
96
|
function DataSource() {
|
|
66
97
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
@@ -70,14 +101,33 @@ var DataSource = /** @class */ (function (_super) {
|
|
|
70
101
|
dataSource._owner = owner;
|
|
71
102
|
return dataSource;
|
|
72
103
|
};
|
|
104
|
+
DataSource.prototype.numberOfSectionsInTableView = function (tableView) {
|
|
105
|
+
var _a;
|
|
106
|
+
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
107
|
+
if (!owner) {
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
var sections = owner._getSectionCount();
|
|
111
|
+
if (Trace.isEnabled()) {
|
|
112
|
+
Trace.write("ListView: numberOfSections = ".concat(sections, " (sectioned: ").concat(owner.sectioned, ")"), Trace.categories.Debug);
|
|
113
|
+
}
|
|
114
|
+
return sections;
|
|
115
|
+
};
|
|
73
116
|
DataSource.prototype.tableViewNumberOfRowsInSection = function (tableView, section) {
|
|
74
117
|
var _a;
|
|
75
118
|
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
76
|
-
|
|
119
|
+
if (!owner) {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
var sectionItems = owner._getItemsInSection(section);
|
|
123
|
+
var rowCount = sectionItems ? sectionItems.length : 0;
|
|
124
|
+
if (Trace.isEnabled()) {
|
|
125
|
+
Trace.write("ListView: numberOfRows in section ".concat(section, " = ").concat(rowCount), Trace.categories.Debug);
|
|
126
|
+
}
|
|
127
|
+
return rowCount;
|
|
77
128
|
};
|
|
78
129
|
DataSource.prototype.tableViewCellForRowAtIndexPath = function (tableView, indexPath) {
|
|
79
130
|
var _a;
|
|
80
|
-
// We call this method because ...ForIndexPath calls tableViewHeightForRowAtIndexPath immediately (before we can prepare and measure it).
|
|
81
131
|
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
82
132
|
var cell;
|
|
83
133
|
if (owner) {
|
|
@@ -86,8 +136,6 @@ var DataSource = /** @class */ (function (_super) {
|
|
|
86
136
|
owner._prepareCell(cell, indexPath);
|
|
87
137
|
var cellView = cell.view;
|
|
88
138
|
if (cellView && cellView.isLayoutRequired) {
|
|
89
|
-
// Arrange cell views. We do it here instead of _layoutCell because _layoutCell is called
|
|
90
|
-
// from 'tableViewHeightForRowAtIndexPath' method too (in iOS 7.1) and we don't want to arrange the fake cell.
|
|
91
139
|
var width = layout.getMeasureSpecSize(owner.widthMeasureSpec);
|
|
92
140
|
var rowHeight = owner._effectiveRowHeight;
|
|
93
141
|
var cellHeight = rowHeight > 0 ? rowHeight : owner.getHeight(indexPath.row);
|
|
@@ -103,7 +151,7 @@ var DataSource = /** @class */ (function (_super) {
|
|
|
103
151
|
DataSource.ObjCProtocols = [UITableViewDataSource];
|
|
104
152
|
return DataSource;
|
|
105
153
|
}(NSObject));
|
|
106
|
-
var UITableViewDelegateImpl =
|
|
154
|
+
var UITableViewDelegateImpl = (function (_super) {
|
|
107
155
|
__extends(UITableViewDelegateImpl, _super);
|
|
108
156
|
function UITableViewDelegateImpl() {
|
|
109
157
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
@@ -145,7 +193,6 @@ var UITableViewDelegateImpl = /** @class */ (function (_super) {
|
|
|
145
193
|
}
|
|
146
194
|
var height = owner.getHeight(indexPath.row);
|
|
147
195
|
if (height === undefined) {
|
|
148
|
-
// in iOS8+ after call to scrollToRowAtIndexPath:atScrollPosition:animated: this method is called before tableViewCellForRowAtIndexPath so we need fake cell to measure its content.
|
|
149
196
|
var template = owner._getItemTemplate(indexPath.row);
|
|
150
197
|
var cell = this._measureCellMap.get(template.key);
|
|
151
198
|
if (!cell) {
|
|
@@ -156,10 +203,49 @@ var UITableViewDelegateImpl = /** @class */ (function (_super) {
|
|
|
156
203
|
}
|
|
157
204
|
return layout.toDeviceIndependentPixels(height);
|
|
158
205
|
};
|
|
206
|
+
UITableViewDelegateImpl.prototype.tableViewViewForHeaderInSection = function (tableView, section) {
|
|
207
|
+
var _a;
|
|
208
|
+
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
209
|
+
if (!owner || !owner.stickyHeader || !owner.stickyHeaderTemplate) {
|
|
210
|
+
if (Trace.isEnabled()) {
|
|
211
|
+
Trace.write("ListView: No sticky header (stickyHeader: ".concat(owner === null || owner === void 0 ? void 0 : owner.stickyHeader, ", hasTemplate: ").concat(!!(owner === null || owner === void 0 ? void 0 : owner.stickyHeaderTemplate), ")"), Trace.categories.Debug);
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
if (Trace.isEnabled()) {
|
|
216
|
+
Trace.write("ListView: Creating sticky header", Trace.categories.Debug);
|
|
217
|
+
}
|
|
218
|
+
var headerReuseIdentifier = "stickyHeader";
|
|
219
|
+
var headerCell = tableView.dequeueReusableHeaderFooterViewWithIdentifier(headerReuseIdentifier);
|
|
220
|
+
if (!headerCell) {
|
|
221
|
+
headerCell = ListViewHeaderCell.alloc().initWithReuseIdentifier(headerReuseIdentifier);
|
|
222
|
+
headerCell.backgroundColor = UIColor.clearColor;
|
|
223
|
+
}
|
|
224
|
+
owner._prepareHeader(headerCell, section);
|
|
225
|
+
return headerCell;
|
|
226
|
+
};
|
|
227
|
+
UITableViewDelegateImpl.prototype.tableViewHeightForHeaderInSection = function (tableView, section) {
|
|
228
|
+
var _a;
|
|
229
|
+
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
230
|
+
if (!owner || !owner.stickyHeader) {
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
var height;
|
|
234
|
+
if (owner.stickyHeaderHeight === "auto") {
|
|
235
|
+
height = 44;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
height = layout.toDeviceIndependentPixels(Length.toDevicePixels(owner.stickyHeaderHeight, 44));
|
|
239
|
+
}
|
|
240
|
+
if (Trace.isEnabled()) {
|
|
241
|
+
Trace.write("ListView: Sticky header height: ".concat(height), Trace.categories.Debug);
|
|
242
|
+
}
|
|
243
|
+
return height;
|
|
244
|
+
};
|
|
159
245
|
UITableViewDelegateImpl.ObjCProtocols = [UITableViewDelegate];
|
|
160
246
|
return UITableViewDelegateImpl;
|
|
161
247
|
}(NSObject));
|
|
162
|
-
var UITableViewRowHeightDelegateImpl =
|
|
248
|
+
var UITableViewRowHeightDelegateImpl = (function (_super) {
|
|
163
249
|
__extends(UITableViewRowHeightDelegateImpl, _super);
|
|
164
250
|
function UITableViewRowHeightDelegateImpl() {
|
|
165
251
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
@@ -200,14 +286,83 @@ var UITableViewRowHeightDelegateImpl = /** @class */ (function (_super) {
|
|
|
200
286
|
}
|
|
201
287
|
return layout.toDeviceIndependentPixels(owner._effectiveRowHeight);
|
|
202
288
|
};
|
|
289
|
+
UITableViewRowHeightDelegateImpl.prototype.tableViewViewForHeaderInSection = function (tableView, section) {
|
|
290
|
+
var _a;
|
|
291
|
+
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
292
|
+
if (!owner || !owner.stickyHeader || !owner.stickyHeaderTemplate) {
|
|
293
|
+
if (Trace.isEnabled()) {
|
|
294
|
+
Trace.write("ListView: No sticky header (stickyHeader: ".concat(owner === null || owner === void 0 ? void 0 : owner.stickyHeader, ", hasTemplate: ").concat(!!(owner === null || owner === void 0 ? void 0 : owner.stickyHeaderTemplate), ")"), Trace.categories.Debug);
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
if (Trace.isEnabled()) {
|
|
299
|
+
Trace.write("ListView: Creating sticky header", Trace.categories.Debug);
|
|
300
|
+
}
|
|
301
|
+
var headerReuseIdentifier = "stickyHeader";
|
|
302
|
+
var headerCell = tableView.dequeueReusableHeaderFooterViewWithIdentifier(headerReuseIdentifier);
|
|
303
|
+
if (!headerCell) {
|
|
304
|
+
headerCell = ListViewHeaderCell.alloc().initWithReuseIdentifier(headerReuseIdentifier);
|
|
305
|
+
headerCell.backgroundColor = UIColor.clearColor;
|
|
306
|
+
}
|
|
307
|
+
owner._prepareHeader(headerCell, section);
|
|
308
|
+
return headerCell;
|
|
309
|
+
};
|
|
310
|
+
UITableViewRowHeightDelegateImpl.prototype.tableViewHeightForHeaderInSection = function (tableView, section) {
|
|
311
|
+
var _a;
|
|
312
|
+
var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
|
|
313
|
+
if (!owner || !owner.stickyHeader) {
|
|
314
|
+
return 0;
|
|
315
|
+
}
|
|
316
|
+
var height;
|
|
317
|
+
if (owner.stickyHeaderHeight === "auto") {
|
|
318
|
+
height = 44;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
height = layout.toDeviceIndependentPixels(Length.toDevicePixels(owner.stickyHeaderHeight, 44));
|
|
322
|
+
}
|
|
323
|
+
if (Trace.isEnabled()) {
|
|
324
|
+
Trace.write("ListView: Sticky header height: ".concat(height), Trace.categories.Debug);
|
|
325
|
+
}
|
|
326
|
+
return height;
|
|
327
|
+
};
|
|
203
328
|
UITableViewRowHeightDelegateImpl.ObjCProtocols = [UITableViewDelegate];
|
|
204
329
|
return UITableViewRowHeightDelegateImpl;
|
|
205
330
|
}(NSObject));
|
|
331
|
+
var UISearchResultsUpdatingImpl = (function (_super) {
|
|
332
|
+
__extends(UISearchResultsUpdatingImpl, _super);
|
|
333
|
+
function UISearchResultsUpdatingImpl() {
|
|
334
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
335
|
+
}
|
|
336
|
+
UISearchResultsUpdatingImpl.initWithOwner = function (owner) {
|
|
337
|
+
var handler = UISearchResultsUpdatingImpl.new();
|
|
338
|
+
handler._owner = owner;
|
|
339
|
+
return handler;
|
|
340
|
+
};
|
|
341
|
+
UISearchResultsUpdatingImpl.prototype.updateSearchResultsForSearchController = function (searchController) {
|
|
342
|
+
var owner = this._owner ? this._owner.get() : null;
|
|
343
|
+
if (!owner) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
var searchText = searchController.searchBar.text || "";
|
|
347
|
+
owner._isSearchActive = searchController.active;
|
|
348
|
+
var eventData = {
|
|
349
|
+
eventName: ListViewBase.searchChangeEvent,
|
|
350
|
+
object: owner,
|
|
351
|
+
text: searchText,
|
|
352
|
+
ios: searchController,
|
|
353
|
+
};
|
|
354
|
+
owner.notify(eventData);
|
|
355
|
+
};
|
|
356
|
+
UISearchResultsUpdatingImpl.ObjCProtocols = [UISearchResultsUpdating];
|
|
357
|
+
return UISearchResultsUpdatingImpl;
|
|
358
|
+
}(NSObject));
|
|
206
359
|
export class ListView extends ListViewBase {
|
|
207
360
|
constructor() {
|
|
208
361
|
super();
|
|
362
|
+
this._isSearchActive = false;
|
|
209
363
|
this.widthMeasureSpec = 0;
|
|
210
364
|
this._map = new Map();
|
|
365
|
+
this._headerMap = new Map();
|
|
211
366
|
this._heights = new Array();
|
|
212
367
|
}
|
|
213
368
|
createNativeView() {
|
|
@@ -217,17 +372,125 @@ export class ListView extends ListViewBase {
|
|
|
217
372
|
super.initNativeView();
|
|
218
373
|
const nativeView = this.nativeViewProtected;
|
|
219
374
|
nativeView.registerClassForCellReuseIdentifier(ListViewCell.class(), this._defaultTemplate.key);
|
|
375
|
+
nativeView.registerClassForHeaderFooterViewReuseIdentifier(ListViewHeaderCell.class(), 'stickyHeader');
|
|
220
376
|
nativeView.estimatedRowHeight = DEFAULT_HEIGHT;
|
|
221
377
|
nativeView.rowHeight = UITableViewAutomaticDimension;
|
|
222
378
|
nativeView.dataSource = this._dataSource = DataSource.initWithOwner(new WeakRef(this));
|
|
223
379
|
this._delegate = UITableViewDelegateImpl.initWithOwner(new WeakRef(this));
|
|
380
|
+
// Control section header top padding (iOS 15+)
|
|
381
|
+
if (nativeView.respondsToSelector('setSectionHeaderTopPadding:')) {
|
|
382
|
+
if (!this.stickyHeaderTopPadding) {
|
|
383
|
+
nativeView.sectionHeaderTopPadding = 0;
|
|
384
|
+
}
|
|
385
|
+
// When stickyHeaderTopPadding is true, don't set the property to use iOS default
|
|
386
|
+
}
|
|
224
387
|
this._setNativeClipToBounds();
|
|
225
388
|
}
|
|
226
389
|
disposeNativeView() {
|
|
390
|
+
this._cleanupSearchController();
|
|
227
391
|
this._delegate = null;
|
|
228
392
|
this._dataSource = null;
|
|
229
393
|
super.disposeNativeView();
|
|
230
394
|
}
|
|
395
|
+
_setupSearchController() {
|
|
396
|
+
if (!this.showSearch || this._searchController) {
|
|
397
|
+
return; // Already setup or not needed
|
|
398
|
+
}
|
|
399
|
+
// 1. Create UISearchController with nil (show results in this table)
|
|
400
|
+
this._searchController = UISearchController.alloc().initWithSearchResultsController(null);
|
|
401
|
+
this._searchDelegate = UISearchResultsUpdatingImpl.initWithOwner(new WeakRef(this));
|
|
402
|
+
// 2. Tell it who will update results
|
|
403
|
+
this._searchController.searchResultsUpdater = this._searchDelegate;
|
|
404
|
+
// 3. Critical: Don't dim or obscure the table, and prevent extra content
|
|
405
|
+
this._searchController.obscuresBackgroundDuringPresentation = false;
|
|
406
|
+
this._searchController.dimsBackgroundDuringPresentation = false;
|
|
407
|
+
this._searchController.hidesNavigationBarDuringPresentation = false;
|
|
408
|
+
// 4. Placeholder text and styling
|
|
409
|
+
this._searchController.searchBar.placeholder = 'Search';
|
|
410
|
+
this._searchController.searchBar.searchBarStyle = 2 /* UISearchBarStyle.Minimal */;
|
|
411
|
+
// 5. CRITICAL: Proper presentation context setup
|
|
412
|
+
const viewController = this._getViewController();
|
|
413
|
+
if (viewController) {
|
|
414
|
+
viewController.definesPresentationContext = true;
|
|
415
|
+
viewController.providesPresentationContextTransitionStyle = true;
|
|
416
|
+
// 6a. If we're in a UINavigationController (iOS 11+)...
|
|
417
|
+
if (SDK_VERSION >= 11.0 && viewController.navigationItem) {
|
|
418
|
+
viewController.navigationItem.searchController = this._searchController;
|
|
419
|
+
// Set auto-hide behavior based on searchAutoHide property
|
|
420
|
+
viewController.navigationItem.hidesSearchBarWhenScrolling = this.searchAutoHide;
|
|
421
|
+
// Optional: Enable large titles for better auto-hide effect when searchAutoHide is true
|
|
422
|
+
// if (this.searchAutoHide && viewController.navigationController && viewController.navigationController.navigationBar) {
|
|
423
|
+
// // Only set large titles if not already configured
|
|
424
|
+
// if (!viewController.navigationController.navigationBar.prefersLargeTitles) {
|
|
425
|
+
// viewController.navigationController.navigationBar.prefersLargeTitles = true;
|
|
426
|
+
// }
|
|
427
|
+
// // Set large title display mode for this specific view controller
|
|
428
|
+
// if (viewController.navigationItem.largeTitleDisplayMode === UINavigationItemLargeTitleDisplayMode.Automatic) {
|
|
429
|
+
// viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Always;
|
|
430
|
+
// }
|
|
431
|
+
// }
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
// 6b. Fallback: put it at the top of our table
|
|
435
|
+
this.nativeViewProtected.tableHeaderView = this._searchController.searchBar;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
// Fallback: no view controller found, use table header
|
|
440
|
+
this.nativeViewProtected.tableHeaderView = this._searchController.searchBar;
|
|
441
|
+
}
|
|
442
|
+
// 7. Ensure search bar is properly sized and prevent content inset issues
|
|
443
|
+
this._searchController.searchBar.sizeToFit();
|
|
444
|
+
// 8. Disable automatic content inset adjustment that can cause spacing issues
|
|
445
|
+
if (this.nativeViewProtected.respondsToSelector('setContentInsetAdjustmentBehavior:')) {
|
|
446
|
+
// iOS 11+ - prevent automatic content inset adjustments
|
|
447
|
+
this.nativeViewProtected.contentInsetAdjustmentBehavior = 2 /* UIScrollViewContentInsetAdjustmentBehavior.Never */;
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
// iOS 10 and below - disable automatic content inset
|
|
451
|
+
this.nativeViewProtected.automaticallyAdjustsScrollIndicatorInsets = false;
|
|
452
|
+
}
|
|
453
|
+
if (Trace.isEnabled()) {
|
|
454
|
+
Trace.write(`ListView: UISearchController setup complete with searchAutoHide: ${this.searchAutoHide}`, Trace.categories.Debug);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
_cleanupSearchController() {
|
|
458
|
+
if (!this._searchController) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
// Remove search controller from navigation item or table header
|
|
462
|
+
const viewController = this._getViewController();
|
|
463
|
+
if (viewController && viewController.navigationItem && viewController.navigationItem.searchController === this._searchController) {
|
|
464
|
+
viewController.navigationItem.searchController = null;
|
|
465
|
+
}
|
|
466
|
+
else if (this.nativeViewProtected.tableHeaderView === this._searchController.searchBar) {
|
|
467
|
+
this.nativeViewProtected.tableHeaderView = null;
|
|
468
|
+
}
|
|
469
|
+
// Reset content inset adjustment behavior
|
|
470
|
+
if (this.nativeViewProtected.respondsToSelector('setContentInsetAdjustmentBehavior:')) {
|
|
471
|
+
// iOS 11+ - restore automatic content inset adjustments
|
|
472
|
+
this.nativeViewProtected.contentInsetAdjustmentBehavior = 0 /* UIScrollViewContentInsetAdjustmentBehavior.Automatic */;
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
// iOS 10 and below - restore automatic content inset
|
|
476
|
+
this.nativeViewProtected.automaticallyAdjustsScrollIndicatorInsets = true;
|
|
477
|
+
}
|
|
478
|
+
// Cleanup references
|
|
479
|
+
this._searchController.searchResultsUpdater = null;
|
|
480
|
+
this._searchController = null;
|
|
481
|
+
this._searchDelegate = null;
|
|
482
|
+
}
|
|
483
|
+
_getViewController() {
|
|
484
|
+
// Helper to get the current view controller
|
|
485
|
+
let parent = this.parent;
|
|
486
|
+
while (parent) {
|
|
487
|
+
if (parent.viewController) {
|
|
488
|
+
return parent.viewController;
|
|
489
|
+
}
|
|
490
|
+
parent = parent.parent;
|
|
491
|
+
}
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
231
494
|
_setNativeClipToBounds() {
|
|
232
495
|
// Always set clipsToBounds for list-view
|
|
233
496
|
const view = this.nativeViewProtected;
|
|
@@ -241,18 +504,25 @@ export class ListView extends ListViewBase {
|
|
|
241
504
|
this.refresh();
|
|
242
505
|
}
|
|
243
506
|
this.nativeViewProtected.delegate = this._delegate;
|
|
507
|
+
// Setup search controller if enabled
|
|
508
|
+
if (this.showSearch) {
|
|
509
|
+
this._setupSearchController();
|
|
510
|
+
}
|
|
244
511
|
}
|
|
245
512
|
// @ts-ignore
|
|
246
513
|
get ios() {
|
|
247
514
|
return this.nativeViewProtected;
|
|
248
515
|
}
|
|
249
516
|
get _childrenCount() {
|
|
250
|
-
return this._map.size;
|
|
517
|
+
return this._map.size + this._headerMap.size;
|
|
251
518
|
}
|
|
252
519
|
eachChildView(callback) {
|
|
253
520
|
this._map.forEach((view, key) => {
|
|
254
521
|
callback(view);
|
|
255
522
|
});
|
|
523
|
+
this._headerMap.forEach((view, key) => {
|
|
524
|
+
callback(view);
|
|
525
|
+
});
|
|
256
526
|
}
|
|
257
527
|
scrollToIndex(index) {
|
|
258
528
|
this._scrollToIndex(index, false);
|
|
@@ -286,6 +556,11 @@ export class ListView extends ListViewBase {
|
|
|
286
556
|
view.bindingContext = null;
|
|
287
557
|
}
|
|
288
558
|
});
|
|
559
|
+
this._headerMap.forEach((view, nativeView, map) => {
|
|
560
|
+
if (!(view.bindingContext instanceof Observable)) {
|
|
561
|
+
view.bindingContext = null;
|
|
562
|
+
}
|
|
563
|
+
});
|
|
289
564
|
if (this.isLoaded) {
|
|
290
565
|
this.nativeViewProtected.reloadData();
|
|
291
566
|
this.requestLayout();
|
|
@@ -324,8 +599,8 @@ export class ListView extends ListViewBase {
|
|
|
324
599
|
super._onRowHeightPropertyChanged(oldValue, newValue);
|
|
325
600
|
}
|
|
326
601
|
requestLayout() {
|
|
327
|
-
// When preparing cell don't call super - no need to invalidate our measure when cell desiredSize is changed.
|
|
328
|
-
if (!this._preparingCell) {
|
|
602
|
+
// When preparing cell or header don't call super - no need to invalidate our measure when cell/header desiredSize is changed.
|
|
603
|
+
if (!this._preparingCell && !this._preparingHeader) {
|
|
329
604
|
super.requestLayout();
|
|
330
605
|
}
|
|
331
606
|
}
|
|
@@ -343,6 +618,9 @@ export class ListView extends ListViewBase {
|
|
|
343
618
|
this._map.forEach((childView, listViewCell) => {
|
|
344
619
|
View.measureChild(this, childView, childView._currentWidthMeasureSpec, childView._currentHeightMeasureSpec);
|
|
345
620
|
});
|
|
621
|
+
this._headerMap.forEach((childView, listViewHeaderCell) => {
|
|
622
|
+
View.measureChild(this, childView, childView._currentWidthMeasureSpec, childView._currentHeightMeasureSpec);
|
|
623
|
+
});
|
|
346
624
|
}
|
|
347
625
|
onLayout(left, top, right, bottom) {
|
|
348
626
|
super.onLayout(left, top, right, bottom);
|
|
@@ -355,6 +633,12 @@ export class ListView extends ListViewBase {
|
|
|
355
633
|
View.layoutChild(this, childView, 0, 0, width, cellHeight);
|
|
356
634
|
}
|
|
357
635
|
});
|
|
636
|
+
this._headerMap.forEach((childView, listViewHeaderCell) => {
|
|
637
|
+
const headerHeight = this.stickyHeaderHeight === 'auto' ? 44 : Length.toDevicePixels(this.stickyHeaderHeight, 44);
|
|
638
|
+
const width = layout.getMeasureSpecSize(this.widthMeasureSpec);
|
|
639
|
+
childView.iosOverflowSafeAreaEnabled = false;
|
|
640
|
+
View.layoutChild(this, childView, 0, 0, width, headerHeight);
|
|
641
|
+
});
|
|
358
642
|
}
|
|
359
643
|
_layoutCell(cellView, indexPath) {
|
|
360
644
|
if (cellView) {
|
|
@@ -373,10 +657,21 @@ export class ListView extends ListViewBase {
|
|
|
373
657
|
this._preparingCell = true;
|
|
374
658
|
let view = cell.view;
|
|
375
659
|
if (!view) {
|
|
376
|
-
|
|
660
|
+
if (this.sectioned) {
|
|
661
|
+
// For sectioned data, we need to calculate the absolute index for template selection
|
|
662
|
+
let absoluteIndex = 0;
|
|
663
|
+
for (let i = 0; i < indexPath.section; i++) {
|
|
664
|
+
absoluteIndex += this._getItemsInSection(i).length;
|
|
665
|
+
}
|
|
666
|
+
absoluteIndex += indexPath.row;
|
|
667
|
+
view = this._getItemTemplate(absoluteIndex).createView();
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
view = this._getItemTemplate(indexPath.row).createView();
|
|
671
|
+
}
|
|
377
672
|
}
|
|
378
673
|
const args = notifyForItemAtIndex(this, cell, view, ITEMLOADING, indexPath);
|
|
379
|
-
view = args.view || this._getDefaultItemContent(indexPath.row);
|
|
674
|
+
view = args.view || this._getDefaultItemContent(this.sectioned ? indexPath.row : indexPath.row);
|
|
380
675
|
// Proxy containers should not get treated as layouts.
|
|
381
676
|
// Wrap them in a real layout as well.
|
|
382
677
|
if (view instanceof ProxyViewContainer) {
|
|
@@ -394,8 +689,15 @@ export class ListView extends ListViewBase {
|
|
|
394
689
|
this._removeContainer(cell);
|
|
395
690
|
cell.owner = new WeakRef(view);
|
|
396
691
|
}
|
|
397
|
-
this.
|
|
398
|
-
|
|
692
|
+
if (this.sectioned) {
|
|
693
|
+
this._prepareItemInSection(view, indexPath.section, indexPath.row);
|
|
694
|
+
view._listViewItemIndex = indexPath.row; // Keep row index for compatibility
|
|
695
|
+
view._listViewSectionIndex = indexPath.section;
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
this._prepareItem(view, indexPath.row);
|
|
699
|
+
view._listViewItemIndex = indexPath.row;
|
|
700
|
+
}
|
|
399
701
|
this._map.set(cell, view);
|
|
400
702
|
// We expect that views returned from itemLoading are new (e.g. not reused).
|
|
401
703
|
if (view && !view.parent) {
|
|
@@ -423,6 +725,151 @@ export class ListView extends ListViewBase {
|
|
|
423
725
|
this._preparingCell = preparing;
|
|
424
726
|
this._map.delete(cell);
|
|
425
727
|
}
|
|
728
|
+
_prepareHeader(headerCell, section) {
|
|
729
|
+
let headerHeight;
|
|
730
|
+
try {
|
|
731
|
+
this._preparingHeader = true;
|
|
732
|
+
let view = headerCell.view;
|
|
733
|
+
if (!view) {
|
|
734
|
+
view = this._getHeaderTemplate();
|
|
735
|
+
if (!view) {
|
|
736
|
+
if (Trace.isEnabled()) {
|
|
737
|
+
Trace.write(`ListView: Failed to create header view for section ${section}`, Trace.categories.Debug);
|
|
738
|
+
}
|
|
739
|
+
// Create a fallback view
|
|
740
|
+
const lbl = new Label();
|
|
741
|
+
lbl.text = `Section ${section}`;
|
|
742
|
+
view = lbl;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
// Handle header cell reuse
|
|
746
|
+
if (!headerCell.view) {
|
|
747
|
+
headerCell.owner = new WeakRef(view);
|
|
748
|
+
}
|
|
749
|
+
else if (headerCell.view !== view) {
|
|
750
|
+
// Remove old view and set new one
|
|
751
|
+
headerCell.view.nativeViewProtected?.removeFromSuperview();
|
|
752
|
+
this._removeHeaderContainer(headerCell);
|
|
753
|
+
headerCell.owner = new WeakRef(view);
|
|
754
|
+
}
|
|
755
|
+
// Clear existing binding context and set new one
|
|
756
|
+
if (view.bindingContext) {
|
|
757
|
+
view.bindingContext = null;
|
|
758
|
+
}
|
|
759
|
+
if (this.sectioned) {
|
|
760
|
+
const sectionData = this._getSectionData(section);
|
|
761
|
+
if (sectionData) {
|
|
762
|
+
view.bindingContext = sectionData;
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
// Fallback if section data is missing
|
|
766
|
+
view.bindingContext = { title: `Section ${section}`, section: section };
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
view.bindingContext = this.bindingContext;
|
|
771
|
+
}
|
|
772
|
+
// Force immediate binding context evaluation
|
|
773
|
+
if (view && typeof view._onBindingContextChanged === 'function') {
|
|
774
|
+
view._onBindingContextChanged(null, view.bindingContext);
|
|
775
|
+
// Also trigger for child views
|
|
776
|
+
// @ts-ignore
|
|
777
|
+
if (view._childrenCount) {
|
|
778
|
+
view.eachChildView((child) => {
|
|
779
|
+
if (typeof child._onBindingContextChanged === 'function') {
|
|
780
|
+
child._onBindingContextChanged(null, view.bindingContext);
|
|
781
|
+
}
|
|
782
|
+
return true;
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
this._headerMap.set(headerCell, view);
|
|
787
|
+
// Add new header view to the cell
|
|
788
|
+
if (view && !view.parent) {
|
|
789
|
+
this._addView(view);
|
|
790
|
+
headerCell.contentView.addSubview(view.nativeViewProtected);
|
|
791
|
+
}
|
|
792
|
+
// Request layout and measure/layout the header
|
|
793
|
+
if (view && view.bindingContext) {
|
|
794
|
+
view.requestLayout();
|
|
795
|
+
}
|
|
796
|
+
headerHeight = this._layoutHeader(view);
|
|
797
|
+
}
|
|
798
|
+
finally {
|
|
799
|
+
this._preparingHeader = false;
|
|
800
|
+
}
|
|
801
|
+
return headerHeight;
|
|
802
|
+
}
|
|
803
|
+
_layoutHeader(headerView) {
|
|
804
|
+
if (headerView) {
|
|
805
|
+
const headerHeight = this.stickyHeaderHeight === 'auto' ? 44 : Length.toDevicePixels(this.stickyHeaderHeight, 44);
|
|
806
|
+
const heightMeasureSpec = layout.makeMeasureSpec(headerHeight, layout.EXACTLY);
|
|
807
|
+
const measuredSize = View.measureChild(this, headerView, this.widthMeasureSpec, heightMeasureSpec);
|
|
808
|
+
// Layout the header with the measured size
|
|
809
|
+
View.layoutChild(this, headerView, 0, 0, measuredSize.measuredWidth, measuredSize.measuredHeight);
|
|
810
|
+
return measuredSize.measuredHeight;
|
|
811
|
+
}
|
|
812
|
+
return 44;
|
|
813
|
+
}
|
|
814
|
+
_getHeaderTemplate() {
|
|
815
|
+
if (this.stickyHeaderTemplate) {
|
|
816
|
+
if (__UI_USE_EXTERNAL_RENDERER__) {
|
|
817
|
+
if (isFunction(this.stickyHeaderTemplate)) {
|
|
818
|
+
return this.stickyHeaderTemplate();
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
if (typeof this.stickyHeaderTemplate === 'string') {
|
|
823
|
+
try {
|
|
824
|
+
const parsed = Builder.parse(this.stickyHeaderTemplate, this);
|
|
825
|
+
if (!parsed) {
|
|
826
|
+
// Create a simple fallback
|
|
827
|
+
const fallbackLabel = new Label();
|
|
828
|
+
fallbackLabel.text = 'Parse Failed';
|
|
829
|
+
return fallbackLabel;
|
|
830
|
+
}
|
|
831
|
+
return parsed;
|
|
832
|
+
}
|
|
833
|
+
catch (error) {
|
|
834
|
+
if (Trace.isEnabled()) {
|
|
835
|
+
Trace.write(`ListView: Template parsing error: ${error}`, Trace.categories.Debug);
|
|
836
|
+
}
|
|
837
|
+
// Create a simple fallback
|
|
838
|
+
const errorLabel = new Label();
|
|
839
|
+
errorLabel.text = 'Template Error';
|
|
840
|
+
return errorLabel;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
const view = this.stickyHeaderTemplate();
|
|
845
|
+
if (Trace.isEnabled()) {
|
|
846
|
+
Trace.write(`ListView: Created header view from template function: ${!!view} (type: ${view?.constructor?.name})`, Trace.categories.Debug);
|
|
847
|
+
}
|
|
848
|
+
return view;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
if (Trace.isEnabled()) {
|
|
853
|
+
Trace.write(`ListView: No sticky header template, creating default`, Trace.categories.Debug);
|
|
854
|
+
}
|
|
855
|
+
// Return a default header if no template is provided
|
|
856
|
+
const lbl = new Label();
|
|
857
|
+
lbl.text = 'Default Header';
|
|
858
|
+
return lbl;
|
|
859
|
+
}
|
|
860
|
+
_removeHeaderContainer(headerCell) {
|
|
861
|
+
const view = headerCell.view;
|
|
862
|
+
// This is to clear the StackLayout that is used to wrap ProxyViewContainer instances.
|
|
863
|
+
if (!(view.parent instanceof ListView)) {
|
|
864
|
+
this._removeView(view.parent);
|
|
865
|
+
}
|
|
866
|
+
// No need to request layout when we are removing headers.
|
|
867
|
+
const preparing = this._preparingHeader;
|
|
868
|
+
this._preparingHeader = true;
|
|
869
|
+
view.parent._removeView(view);
|
|
870
|
+
this._preparingHeader = preparing;
|
|
871
|
+
this._headerMap.delete(headerCell);
|
|
872
|
+
}
|
|
426
873
|
[separatorColorProperty.getDefault]() {
|
|
427
874
|
return this.nativeViewProtected.separatorColor;
|
|
428
875
|
}
|
|
@@ -450,6 +897,95 @@ export class ListView extends ListViewBase {
|
|
|
450
897
|
const estimatedHeight = layout.toDeviceIndependentPixels(Length.toDevicePixels(value, 0));
|
|
451
898
|
nativeView.estimatedRowHeight = estimatedHeight < 0 ? DEFAULT_HEIGHT : estimatedHeight;
|
|
452
899
|
}
|
|
900
|
+
[stickyHeaderProperty.getDefault]() {
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
[stickyHeaderProperty.setNative](value) {
|
|
904
|
+
if (Trace.isEnabled()) {
|
|
905
|
+
Trace.write(`ListView: stickyHeader set to ${value}`, Trace.categories.Debug);
|
|
906
|
+
}
|
|
907
|
+
// Immediately refresh to apply changes
|
|
908
|
+
if (this.isLoaded) {
|
|
909
|
+
this.refresh();
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
[stickyHeaderTemplateProperty.getDefault]() {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
[stickyHeaderTemplateProperty.setNative](value) {
|
|
916
|
+
if (Trace.isEnabled()) {
|
|
917
|
+
Trace.write(`ListView: stickyHeaderTemplate set: ${typeof value} ${value ? '(has value)' : '(null)'}`, Trace.categories.Debug);
|
|
918
|
+
}
|
|
919
|
+
// Clear any cached template
|
|
920
|
+
this._headerTemplateCache = null;
|
|
921
|
+
// Immediately refresh to apply changes
|
|
922
|
+
if (this.isLoaded) {
|
|
923
|
+
this.refresh();
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
[stickyHeaderHeightProperty.getDefault]() {
|
|
927
|
+
return 'auto';
|
|
928
|
+
}
|
|
929
|
+
[stickyHeaderHeightProperty.setNative](value) {
|
|
930
|
+
if (Trace.isEnabled()) {
|
|
931
|
+
Trace.write(`ListView: stickyHeaderHeight set to ${value}`, Trace.categories.Debug);
|
|
932
|
+
}
|
|
933
|
+
// Immediately refresh to apply changes
|
|
934
|
+
if (this.isLoaded) {
|
|
935
|
+
this.refresh();
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
[sectionedProperty.getDefault]() {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
[sectionedProperty.setNative](value) {
|
|
942
|
+
if (Trace.isEnabled()) {
|
|
943
|
+
Trace.write(`ListView: sectioned set to ${value}`, Trace.categories.Debug);
|
|
944
|
+
}
|
|
945
|
+
// Immediately refresh to apply changes
|
|
946
|
+
if (this.isLoaded) {
|
|
947
|
+
this.refresh();
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
[showSearchProperty.getDefault]() {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
[showSearchProperty.setNative](value) {
|
|
954
|
+
if (Trace.isEnabled()) {
|
|
955
|
+
Trace.write(`ListView: showSearch set to ${value}`, Trace.categories.Debug);
|
|
956
|
+
}
|
|
957
|
+
if (value) {
|
|
958
|
+
this._setupSearchController();
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
this._cleanupSearchController();
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
[searchAutoHideProperty.getDefault]() {
|
|
965
|
+
return false;
|
|
966
|
+
}
|
|
967
|
+
[searchAutoHideProperty.setNative](value) {
|
|
968
|
+
if (Trace.isEnabled()) {
|
|
969
|
+
Trace.write(`ListView: searchAutoHide set to ${value}`, Trace.categories.Debug);
|
|
970
|
+
}
|
|
971
|
+
// If search is already enabled, update the existing search controller
|
|
972
|
+
if (this.showSearch && this._searchController) {
|
|
973
|
+
const viewController = this._getViewController();
|
|
974
|
+
if (viewController && viewController.navigationItem && SDK_VERSION >= 11.0) {
|
|
975
|
+
viewController.navigationItem.hidesSearchBarWhenScrolling = value;
|
|
976
|
+
// Enable large titles for better auto-hide effect when searchAutoHide is true
|
|
977
|
+
// if (value && viewController.navigationController && viewController.navigationController.navigationBar) {
|
|
978
|
+
// if (!viewController.navigationController.navigationBar.prefersLargeTitles) {
|
|
979
|
+
// viewController.navigationController.navigationBar.prefersLargeTitles = true;
|
|
980
|
+
// }
|
|
981
|
+
// if (viewController.navigationItem.largeTitleDisplayMode === UINavigationItemLargeTitleDisplayMode.Automatic) {
|
|
982
|
+
// viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Always;
|
|
983
|
+
// }
|
|
984
|
+
// }
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
// If search is not enabled yet, the property will be used when _setupSearchController is called
|
|
988
|
+
}
|
|
453
989
|
}
|
|
454
990
|
__decorate([
|
|
455
991
|
profile,
|