jsbox-cview 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/alert/input-alert.js +39 -0
- package/dist/components/alert/login-alert.js +45 -0
- package/dist/components/alert/plain-alert.js +25 -0
- package/dist/components/alert/uialert.js +89 -0
- package/dist/components/artificial-flowlayout.js +258 -0
- package/dist/components/base.js +43 -0
- package/dist/components/custom-navigation-bar.js +519 -0
- package/dist/components/dialogs/dialog-sheet.js +67 -0
- package/dist/components/dialogs/form-dialog.js +24 -0
- package/dist/components/dialogs/list-dialog.js +87 -0
- package/dist/components/dialogs/text-dialog.js +31 -0
- package/dist/components/dynamic-itemsize-matrix.js +129 -0
- package/dist/components/dynamic-preference-listview.js +557 -0
- package/dist/components/dynamic-rowheight-list.js +44 -0
- package/dist/components/enhanced-imageview.js +114 -0
- package/dist/components/image-pager.js +157 -0
- package/dist/components/page-control.js +76 -0
- package/dist/components/pageviewer-titlebar.js +143 -0
- package/dist/components/pageviewer.js +96 -0
- package/dist/components/rotating-view.js +102 -0
- package/dist/components/searchbar.js +322 -0
- package/dist/components/sheet.js +82 -0
- package/dist/components/single-views.js +429 -0
- package/dist/components/spinners/loading-double-rings.js +104 -0
- package/dist/components/spinners/loading-dual-ring.js +82 -0
- package/dist/components/spinners/loading-wedges.js +104 -0
- package/dist/components/spinners/spinner-androidstyle.js +248 -0
- package/dist/components/static-preference-listview.js +798 -0
- package/dist/components/symbol-button.js +79 -0
- package/dist/components/tabbar.js +357 -0
- package/dist/controller/base-controller.js +178 -0
- package/dist/controller/controller-router.js +68 -0
- package/dist/controller/pageviewer-controller.js +63 -0
- package/dist/controller/presented-page-controller.js +48 -0
- package/dist/controller/splitview-controller.js +252 -0
- package/dist/controller/tabbar-controller.js +74 -0
- package/dist/index.js +58 -0
- package/dist/test.js +1 -0
- package/dist/utils/colors.js +15 -0
- package/dist/utils/cvid.js +28 -0
- package/dist/utils/l10n.js +44 -0
- package/dist/utils/path.js +107 -0
- package/dist/utils/rect.js +72 -0
- package/dist/utils/uitools.js +95 -0
- package/index.ts +42 -0
- package/package.json +4 -3
- package/tsconfig.json +5 -3
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EnhancedImageView = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 此组件是为了加强 imageView,实现以下目的:
|
|
6
|
+
* 1. 点击实现上下翻页
|
|
7
|
+
* 2. 双指放大缩小(但不可以双击放大缩小)
|
|
8
|
+
*
|
|
9
|
+
* 请注意:此组件使用了Runtime代码重新设置了Tapped事件。
|
|
10
|
+
* 与以前使用touchesEnded事件来实现相比,可以避免在滑动手指时误触发。
|
|
11
|
+
* 但因此带来了副作用:必须在关闭前通过releaseGestureObject释放掉此视图中自定义的NSObject,否则再次启动可能会有问题。
|
|
12
|
+
*
|
|
13
|
+
* Props:
|
|
14
|
+
* src: string, 图片地址
|
|
15
|
+
* maxZoomScale: number, 最大缩放倍数,默认为2
|
|
16
|
+
*
|
|
17
|
+
* Events:
|
|
18
|
+
* upperLocationTouched: (sender: EnhancedImageView) => void, 上半部分被点击
|
|
19
|
+
* lowerLocationTouched: (sender: EnhancedImageView) => void, 下半部分被点击
|
|
20
|
+
*/
|
|
21
|
+
const base_1 = require("./base");
|
|
22
|
+
const single_views_1 = require("./single-views");
|
|
23
|
+
const cvid_1 = require("../utils/cvid");
|
|
24
|
+
class EnhancedImageView extends base_1.Base {
|
|
25
|
+
constructor({ props, layout, events = {} }) {
|
|
26
|
+
super();
|
|
27
|
+
this._props = Object.assign({ maxZoomScale: 2 }, props);
|
|
28
|
+
this._scroll = new single_views_1.Scroll({
|
|
29
|
+
props: {
|
|
30
|
+
zoomEnabled: true,
|
|
31
|
+
doubleTapToZoom: false,
|
|
32
|
+
maxZoomScale: this._props.maxZoomScale
|
|
33
|
+
},
|
|
34
|
+
layout: $layout.fill,
|
|
35
|
+
views: [
|
|
36
|
+
{
|
|
37
|
+
type: "image",
|
|
38
|
+
props: {
|
|
39
|
+
id: "image",
|
|
40
|
+
src: this._props.src,
|
|
41
|
+
contentMode: 1
|
|
42
|
+
},
|
|
43
|
+
layout: $layout.fill
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
events: {
|
|
47
|
+
ready: view => {
|
|
48
|
+
$delay(0.1, () => this._addGesture(view, (gesture) => {
|
|
49
|
+
const location = gesture.$locationInView(view.ocValue());
|
|
50
|
+
const realLocation = $point(location.x - view.bounds.x, location.y - view.bounds.y);
|
|
51
|
+
const frame = this.view.frame;
|
|
52
|
+
if (realLocation.y <= frame.height / 2) {
|
|
53
|
+
if (events.upperLocationTouched)
|
|
54
|
+
events.upperLocationTouched(this);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (events.lowerLocationTouched)
|
|
58
|
+
events.lowerLocationTouched(this);
|
|
59
|
+
}
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
this._defineView = () => {
|
|
65
|
+
return {
|
|
66
|
+
type: "view",
|
|
67
|
+
props: {
|
|
68
|
+
id: this.id
|
|
69
|
+
},
|
|
70
|
+
views: [this._scroll.definition],
|
|
71
|
+
layout,
|
|
72
|
+
events: {
|
|
73
|
+
layoutSubviews: sender => {
|
|
74
|
+
$delay(0.1, () => (this.src = this.src));
|
|
75
|
+
$delay(0.3, () => (this.src = this.src));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
_addGesture(view, event) {
|
|
82
|
+
const objectId = cvid_1.cvid.newId;
|
|
83
|
+
$define({
|
|
84
|
+
type: objectId + ": NSObject",
|
|
85
|
+
events: {
|
|
86
|
+
tapped: event
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const object = $objc(objectId).$new();
|
|
90
|
+
$objc_retain(object); // 此步骤是必须的,否则将很快被系统释放掉,但是必须在关闭时手动释放掉,否则再次启动可能会有问题
|
|
91
|
+
this._gestureObject = object;
|
|
92
|
+
const tapGestureRecognizer = $objc("UITapGestureRecognizer")
|
|
93
|
+
.$alloc()
|
|
94
|
+
.$initWithTarget_action(this._gestureObject, "tapped:");
|
|
95
|
+
view.ocValue().$addGestureRecognizer(tapGestureRecognizer);
|
|
96
|
+
}
|
|
97
|
+
releaseGestureObject() {
|
|
98
|
+
if (this._gestureObject)
|
|
99
|
+
$objc_release(this._gestureObject);
|
|
100
|
+
}
|
|
101
|
+
get src() {
|
|
102
|
+
return this._props.src;
|
|
103
|
+
}
|
|
104
|
+
set src(src) {
|
|
105
|
+
this._props.src = src;
|
|
106
|
+
const view = this._scroll.view.get("image");
|
|
107
|
+
view.src = src;
|
|
108
|
+
}
|
|
109
|
+
get image() {
|
|
110
|
+
const view = this._scroll.view.get("image");
|
|
111
|
+
return view.image;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.EnhancedImageView = EnhancedImageView;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImagePager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 与内置的Gallery组件相比,ImagePager组件可以动态刷新,适用于图片数量较多的场景,以及需要动态加载图片列表的场景
|
|
6
|
+
*
|
|
7
|
+
* # Props
|
|
8
|
+
* srcs: string[] - 图片地址列表
|
|
9
|
+
* page: number - 当前页码
|
|
10
|
+
*
|
|
11
|
+
* # Events
|
|
12
|
+
* changed: (page: number) => void - 页码变化时触发
|
|
13
|
+
* tapped: (sender: ImagePager) => void - 点击图片时触发
|
|
14
|
+
*/
|
|
15
|
+
const base_1 = require("./base");
|
|
16
|
+
const single_views_1 = require("./single-views");
|
|
17
|
+
class ImagePager extends base_1.Base {
|
|
18
|
+
constructor({ props, layout, events = {} }) {
|
|
19
|
+
super();
|
|
20
|
+
this._props = Object.assign({ srcs: [], page: 0 }, props);
|
|
21
|
+
this._pageLoadRecorder = {};
|
|
22
|
+
this._matrix = new single_views_1.Matrix({
|
|
23
|
+
props: {
|
|
24
|
+
direction: $scrollDirection.horizontal,
|
|
25
|
+
pagingEnabled: true,
|
|
26
|
+
alwaysBounceVertical: false,
|
|
27
|
+
showsVerticalIndicator: false,
|
|
28
|
+
showsHorizontalIndicator: false,
|
|
29
|
+
template: {
|
|
30
|
+
views: [
|
|
31
|
+
{
|
|
32
|
+
type: "scroll",
|
|
33
|
+
props: {
|
|
34
|
+
id: "scroll",
|
|
35
|
+
zoomEnabled: true,
|
|
36
|
+
maxZoomScale: 3,
|
|
37
|
+
doubleTapToZoom: true
|
|
38
|
+
},
|
|
39
|
+
layout: $layout.fill,
|
|
40
|
+
views: [
|
|
41
|
+
{
|
|
42
|
+
type: "image",
|
|
43
|
+
props: {
|
|
44
|
+
id: "image",
|
|
45
|
+
contentMode: $contentMode.scaleAspectFit
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
data: this._props.srcs.map(n => {
|
|
53
|
+
return { image: { src: n } };
|
|
54
|
+
})
|
|
55
|
+
},
|
|
56
|
+
layout: $layout.fill,
|
|
57
|
+
events: {
|
|
58
|
+
ready: sender => {
|
|
59
|
+
// 如果没有此处的relayout,则会出现莫名其妙的bug
|
|
60
|
+
sender.relayout();
|
|
61
|
+
this.page = this.page;
|
|
62
|
+
this.loadsrc(this.page);
|
|
63
|
+
},
|
|
64
|
+
itemSize: (sender, indexPath) => {
|
|
65
|
+
return $size(sender.frame.width, sender.frame.height);
|
|
66
|
+
},
|
|
67
|
+
forEachItem: (view, indexPath) => {
|
|
68
|
+
const scroll = view.get("scroll");
|
|
69
|
+
scroll.zoomScale = 0;
|
|
70
|
+
//$delay(0.01, () => {});
|
|
71
|
+
},
|
|
72
|
+
willEndDragging: (sender, velocity, target) => {
|
|
73
|
+
const oldPage = this.page;
|
|
74
|
+
this._props.page = Math.round(target.x / sender.frame.width);
|
|
75
|
+
//this.loadsrc(this.page, true);
|
|
76
|
+
if (oldPage !== this.page && events.changed)
|
|
77
|
+
events.changed(this.page);
|
|
78
|
+
},
|
|
79
|
+
didScroll: sender => {
|
|
80
|
+
this.loadsrc(this.page + 1, true);
|
|
81
|
+
this.loadsrc(this.page - 1, true);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
this._defineView = () => {
|
|
86
|
+
return {
|
|
87
|
+
type: "view",
|
|
88
|
+
props: {
|
|
89
|
+
id: this.id,
|
|
90
|
+
userInteractionEnabled: true
|
|
91
|
+
},
|
|
92
|
+
layout,
|
|
93
|
+
views: [this._matrix.definition],
|
|
94
|
+
events: {
|
|
95
|
+
layoutSubviews: sender => {
|
|
96
|
+
this._pageLoadRecorder = {};
|
|
97
|
+
sender.relayout();
|
|
98
|
+
this._matrix.view.reload();
|
|
99
|
+
this.page = this.page;
|
|
100
|
+
$delay(0.1, () => this.loadsrc(this.page, true));
|
|
101
|
+
$delay(0.3, () => this.loadsrc(this.page, true));
|
|
102
|
+
},
|
|
103
|
+
tapped: sender => {
|
|
104
|
+
const cell = this._matrix.view.cell($indexPath(0, this.page));
|
|
105
|
+
if (!cell)
|
|
106
|
+
return;
|
|
107
|
+
const scroll = cell.get("scroll");
|
|
108
|
+
const zoomScale = scroll.zoomScale;
|
|
109
|
+
$delay(0.3, () => {
|
|
110
|
+
const zoomScale1 = scroll.zoomScale;
|
|
111
|
+
if (zoomScale === zoomScale1 && events.tapped)
|
|
112
|
+
events.tapped(this);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
loadsrc(page, forced = false) {
|
|
120
|
+
if (page < 0 || page >= this._props.srcs.length)
|
|
121
|
+
return;
|
|
122
|
+
const cell = this._matrix.view.cell($indexPath(0, page));
|
|
123
|
+
if (!cell)
|
|
124
|
+
return;
|
|
125
|
+
const image = cell.get("image");
|
|
126
|
+
if (forced || !image.image || !this._pageLoadRecorder[page]) {
|
|
127
|
+
const scroll = cell.get("scroll");
|
|
128
|
+
scroll.zoomScale = 0;
|
|
129
|
+
this._pageLoadRecorder[page] = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
get page() {
|
|
133
|
+
return this._props.page;
|
|
134
|
+
}
|
|
135
|
+
get currentImage() {
|
|
136
|
+
const cell = this._matrix.view.cell($indexPath(0, this.page));
|
|
137
|
+
if (!cell)
|
|
138
|
+
return;
|
|
139
|
+
const image = cell.get("image");
|
|
140
|
+
return image.image;
|
|
141
|
+
}
|
|
142
|
+
set page(page) {
|
|
143
|
+
this._matrix.view.scrollTo({
|
|
144
|
+
indexPath: $indexPath(0, page),
|
|
145
|
+
animated: false
|
|
146
|
+
});
|
|
147
|
+
this._props.page = page;
|
|
148
|
+
}
|
|
149
|
+
scrollToPage(page) {
|
|
150
|
+
this._matrix.view.scrollTo({
|
|
151
|
+
indexPath: $indexPath(0, page),
|
|
152
|
+
animated: true
|
|
153
|
+
});
|
|
154
|
+
this._props.page = page;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.ImagePager = ImagePager;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* # CView PageControl
|
|
4
|
+
*
|
|
5
|
+
* 基于 Runtime 构建 PageControl
|
|
6
|
+
*
|
|
7
|
+
* 请注意本视图如果没有足够的横向宽度,会显示不全
|
|
8
|
+
* ## Props
|
|
9
|
+
*
|
|
10
|
+
* - 只写 numberOfPages: numnber
|
|
11
|
+
* - 读写 currentPage: number
|
|
12
|
+
* - 只写 pageIndicatorTintColor?: JSBoxColor
|
|
13
|
+
* - 只写 currentPageIndicatorTintColor?: JSBoxColor
|
|
14
|
+
* - 其他通用属性
|
|
15
|
+
*
|
|
16
|
+
* ## Events
|
|
17
|
+
*
|
|
18
|
+
* changed: (cview: Cview, currentPage: number) => void
|
|
19
|
+
*/
|
|
20
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
21
|
+
var t = {};
|
|
22
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
23
|
+
t[p] = s[p];
|
|
24
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
25
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
26
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
27
|
+
t[p[i]] = s[p[i]];
|
|
28
|
+
}
|
|
29
|
+
return t;
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.PageControl = void 0;
|
|
33
|
+
const single_views_1 = require("./single-views");
|
|
34
|
+
class PageControl extends single_views_1.Runtime {
|
|
35
|
+
constructor({ props, layout, events = {} }) {
|
|
36
|
+
const { numberOfPages = 3, currentPage = 0, pageIndicatorTintColor, currentPageIndicatorTintColor } = props, restProps = __rest(props, ["numberOfPages", "currentPage", "pageIndicatorTintColor", "currentPageIndicatorTintColor"]);
|
|
37
|
+
const { changed } = events, restEvents = __rest(events, ["changed"]);
|
|
38
|
+
super({ props: restProps, layout, events: restEvents });
|
|
39
|
+
this._numberOfPages = numberOfPages;
|
|
40
|
+
this._currentPage = currentPage;
|
|
41
|
+
this._pageIndicatorTintColor = pageIndicatorTintColor;
|
|
42
|
+
this._currentPageIndicatorTintColor = currentPageIndicatorTintColor;
|
|
43
|
+
this._changed = changed;
|
|
44
|
+
this._pageControl = this._createPageControl();
|
|
45
|
+
if (this._props)
|
|
46
|
+
this._props.view = this._pageControl;
|
|
47
|
+
}
|
|
48
|
+
_createPageControl() {
|
|
49
|
+
const pageControl = $objc("UIPageControl").$new();
|
|
50
|
+
pageControl.$setNumberOfPages(this._numberOfPages);
|
|
51
|
+
pageControl.$setCurrentPage(this._currentPage);
|
|
52
|
+
if (this._pageIndicatorTintColor)
|
|
53
|
+
pageControl.$setPageIndicatorTintColor(this._pageIndicatorTintColor.ocValue());
|
|
54
|
+
if (this._currentPageIndicatorTintColor)
|
|
55
|
+
pageControl.$setCurrentPageIndicatorTintColor(this._currentPageIndicatorTintColor.ocValue());
|
|
56
|
+
pageControl.$addEventHandler({
|
|
57
|
+
events: $UIEvent.valueChanged,
|
|
58
|
+
handler: $block("void", () => {
|
|
59
|
+
const currentPage = pageControl.$currentPage();
|
|
60
|
+
this._currentPage = currentPage;
|
|
61
|
+
if (this._changed)
|
|
62
|
+
this._changed(this, currentPage);
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
return pageControl;
|
|
66
|
+
}
|
|
67
|
+
get currentPage() {
|
|
68
|
+
return this._currentPage;
|
|
69
|
+
}
|
|
70
|
+
set currentPage(num) {
|
|
71
|
+
this._currentPage = num;
|
|
72
|
+
if (this._pageControl)
|
|
73
|
+
this._pageControl.$setCurrentPage(num);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.PageControl = PageControl;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* # CView PageViewer TitleBar
|
|
4
|
+
*
|
|
5
|
+
* props:
|
|
6
|
+
*
|
|
7
|
+
* - 只写 items: string[]
|
|
8
|
+
* - 读写 index: number
|
|
9
|
+
* - 只写 selectedItemColor
|
|
10
|
+
* - 只写 defaultItemColor
|
|
11
|
+
*
|
|
12
|
+
* events:
|
|
13
|
+
*
|
|
14
|
+
* - changed: (cview, index) => void 在点击变更 index 的时候回调
|
|
15
|
+
*/
|
|
16
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
17
|
+
var t = {};
|
|
18
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
19
|
+
t[p] = s[p];
|
|
20
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
21
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
22
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
23
|
+
t[p[i]] = s[p[i]];
|
|
24
|
+
}
|
|
25
|
+
return t;
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.PageViewerTitleBar = void 0;
|
|
29
|
+
const base_1 = require("./base");
|
|
30
|
+
const single_views_1 = require("./single-views");
|
|
31
|
+
//const { getTextWidth } = require("cview-util-ui");
|
|
32
|
+
function weightedAverageColors(c0, c1, w) {
|
|
33
|
+
const red = c0.components.red * w + c1.components.red * (1 - w);
|
|
34
|
+
const green = c0.components.green * w + c1.components.green * (1 - w);
|
|
35
|
+
const blue = c0.components.blue * w + c1.components.blue * (1 - w);
|
|
36
|
+
return $rgb(red, green, blue);
|
|
37
|
+
}
|
|
38
|
+
class PageViewerTitleBar extends base_1.Base {
|
|
39
|
+
constructor({ props, layout, events = {} }) {
|
|
40
|
+
super();
|
|
41
|
+
this._props = Object.assign({ index: 0, selectedItemColor: $color("systemLink"), defaultItemColor: $color("secondaryText") }, props);
|
|
42
|
+
const { changed } = events, restEvents = __rest(events, ["changed"]);
|
|
43
|
+
this._floatedIndex = this._props.index;
|
|
44
|
+
this._lineStartLocationPercentage = this._floatedIndex / this._props.items.length;
|
|
45
|
+
this.labels = this._props.items.map((n, i) => {
|
|
46
|
+
return new single_views_1.Label({
|
|
47
|
+
props: {
|
|
48
|
+
text: n,
|
|
49
|
+
font: $font("bold", 17),
|
|
50
|
+
textColor: i === this.index
|
|
51
|
+
? this._props.selectedItemColor
|
|
52
|
+
: this._props.defaultItemColor,
|
|
53
|
+
align: $align.center,
|
|
54
|
+
userInteractionEnabled: true
|
|
55
|
+
},
|
|
56
|
+
events: {
|
|
57
|
+
tapped: sender => {
|
|
58
|
+
this.index = i;
|
|
59
|
+
if (changed)
|
|
60
|
+
changed(this, i);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
this.stack = new single_views_1.Stack({
|
|
66
|
+
props: {
|
|
67
|
+
axis: $stackViewAxis.horizontal,
|
|
68
|
+
distribution: $stackViewDistribution.fillEqually,
|
|
69
|
+
stack: {
|
|
70
|
+
views: this.labels.map(n => n.definition)
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
layout: $layout.fill
|
|
74
|
+
});
|
|
75
|
+
this.placeholderView = new single_views_1.ContentView({
|
|
76
|
+
props: {
|
|
77
|
+
bgcolor: $color("clear")
|
|
78
|
+
},
|
|
79
|
+
layout: (make, view) => {
|
|
80
|
+
make.left.bottom.inset(0);
|
|
81
|
+
make.width.equalTo(view.super).multipliedBy(this._floatedIndex / this._props.items.length);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
this.line = new single_views_1.ContentView({
|
|
85
|
+
props: {
|
|
86
|
+
bgcolor: this._props.selectedItemColor
|
|
87
|
+
},
|
|
88
|
+
layout: (make, view) => {
|
|
89
|
+
make.height.equalTo(4);
|
|
90
|
+
make.width.equalTo(view.super).dividedBy(this._props.items.length);
|
|
91
|
+
make.bottom.inset(0);
|
|
92
|
+
make.left.equalTo(view.prev.right);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
this._defineView = () => {
|
|
96
|
+
return {
|
|
97
|
+
type: "view",
|
|
98
|
+
props: {
|
|
99
|
+
id: this.id
|
|
100
|
+
},
|
|
101
|
+
layout,
|
|
102
|
+
events: restEvents,
|
|
103
|
+
views: [
|
|
104
|
+
this.stack.definition,
|
|
105
|
+
this.placeholderView.definition,
|
|
106
|
+
this.line.definition
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
get lineStartLocationPercentage() {
|
|
112
|
+
return this._lineStartLocationPercentage;
|
|
113
|
+
}
|
|
114
|
+
set lineStartLocationPercentage(percent) {
|
|
115
|
+
this._lineStartLocationPercentage = percent;
|
|
116
|
+
this.placeholderView.view.remakeLayout((make, view) => {
|
|
117
|
+
make.left.bottom.inset(0);
|
|
118
|
+
make.width.equalTo(view.super).multipliedBy(percent);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
get floatedIndex() {
|
|
122
|
+
return this._floatedIndex;
|
|
123
|
+
}
|
|
124
|
+
set floatedIndex(floatedIndex) {
|
|
125
|
+
this._floatedIndex = floatedIndex;
|
|
126
|
+
this.lineStartLocationPercentage = floatedIndex / this._props.items.length;
|
|
127
|
+
this.labels.forEach((n, i) => {
|
|
128
|
+
if (Math.abs(floatedIndex - i) < 1) {
|
|
129
|
+
n.view.textColor = weightedAverageColors(this._props.selectedItemColor, this._props.defaultItemColor, floatedIndex - i > 0 ? 1 - (floatedIndex - i) : 1 - (i - floatedIndex));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
n.view.textColor = this._props.defaultItemColor;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
get index() {
|
|
137
|
+
return this._props.index;
|
|
138
|
+
}
|
|
139
|
+
set index(index) {
|
|
140
|
+
this._props.index = index;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.PageViewerTitleBar = PageViewerTitleBar;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* # CView PageViewer
|
|
4
|
+
*
|
|
5
|
+
* props:
|
|
6
|
+
* - 读写 page: number
|
|
7
|
+
* - 只写 cviews: cview[] cview的布局会被自动指定为占用一整页
|
|
8
|
+
*
|
|
9
|
+
* events:
|
|
10
|
+
* - changed: (cview, page) => void 页面改变时回调
|
|
11
|
+
* - floatPageChanged: (cview, floatPage) => void 滚动时回调(用于绑定其他联合滚动的控件)
|
|
12
|
+
*
|
|
13
|
+
* methods:
|
|
14
|
+
* - scrollToPage(page: number) 滚动到某一页(带有动画效果)
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PageViewer = void 0;
|
|
18
|
+
const base_1 = require("./base");
|
|
19
|
+
const single_views_1 = require("./single-views");
|
|
20
|
+
class PageViewer extends base_1.Base {
|
|
21
|
+
constructor({ props, layout, events = {} }) {
|
|
22
|
+
super();
|
|
23
|
+
this._props = Object.assign({ page: 0 }, props);
|
|
24
|
+
this._events = events;
|
|
25
|
+
this._pageWidth = 0;
|
|
26
|
+
this._floatPage = this._props.page;
|
|
27
|
+
const contentViews = this._props.cviews.map(n => {
|
|
28
|
+
n._layout = $layout.fill;
|
|
29
|
+
return new single_views_1.ContentView({
|
|
30
|
+
views: [n.definition],
|
|
31
|
+
layout: (make, view) => {
|
|
32
|
+
make.height.width.equalTo(view.super);
|
|
33
|
+
make.left.equalTo(view.prev ? view.prev.right : view.super);
|
|
34
|
+
make.top.equalTo(view.super);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
this.scroll = new single_views_1.Scroll({
|
|
39
|
+
props: {
|
|
40
|
+
alwaysBounceVertical: false,
|
|
41
|
+
alwaysBounceHorizontal: true,
|
|
42
|
+
showsHorizontalIndicator: false,
|
|
43
|
+
pagingEnabled: true
|
|
44
|
+
},
|
|
45
|
+
events: {
|
|
46
|
+
layoutSubviews: sender => {
|
|
47
|
+
this._pageWidth = sender.frame.width;
|
|
48
|
+
if (this._pageWidth)
|
|
49
|
+
sender.contentSize = $size(this._pageWidth * this._props.cviews.length, 0);
|
|
50
|
+
},
|
|
51
|
+
willEndDragging: (sender, velocity, target) => {
|
|
52
|
+
const oldPage = this.page;
|
|
53
|
+
this._props.page = Math.round(target.x / this._pageWidth);
|
|
54
|
+
if (oldPage !== this.page && this._events.changed)
|
|
55
|
+
this._events.changed(this, this.page);
|
|
56
|
+
},
|
|
57
|
+
didScroll: sender => {
|
|
58
|
+
const rawPage = sender.contentOffset.x / this._pageWidth;
|
|
59
|
+
this._floatPage = Math.min(Math.max(0, rawPage), this._props.cviews.length - 1);
|
|
60
|
+
if (this._events.floatPageChanged)
|
|
61
|
+
this._events.floatPageChanged(this, this._floatPage);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
layout: $layout.fill,
|
|
65
|
+
views: [...contentViews.map(n => n.definition)]
|
|
66
|
+
});
|
|
67
|
+
this._defineView = () => {
|
|
68
|
+
return {
|
|
69
|
+
type: "view",
|
|
70
|
+
props: { id: this.id },
|
|
71
|
+
layout: this._layout,
|
|
72
|
+
views: [this.scroll.definition],
|
|
73
|
+
events: {
|
|
74
|
+
layoutSubviews: sender => {
|
|
75
|
+
sender.relayout();
|
|
76
|
+
this.page = this.page;
|
|
77
|
+
$delay(0.2, () => (this.page = this.page));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
get page() {
|
|
84
|
+
return this._props.page;
|
|
85
|
+
}
|
|
86
|
+
set page(page) {
|
|
87
|
+
this._props.page = page;
|
|
88
|
+
if (this.scroll.view.contentOffset.x !== page * this._pageWidth)
|
|
89
|
+
this.scroll.view.contentOffset = $point(page * this._pageWidth, 0);
|
|
90
|
+
}
|
|
91
|
+
scrollToPage(page) {
|
|
92
|
+
this.scroll.view.scrollToOffset($point(page * this._pageWidth, 0));
|
|
93
|
+
this._props.page = page;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.PageViewer = PageViewer;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 创建一个可以旋转的视图。理论上来说,这个视图的布局必须是方形的。
|
|
4
|
+
*
|
|
5
|
+
* props:
|
|
6
|
+
* - image 图片
|
|
7
|
+
* - tintColor
|
|
8
|
+
* - contentMode = 1
|
|
9
|
+
* - cview 使用自定义的cview,上面两项将失效
|
|
10
|
+
* - rps = 0.5 每秒转多少圈
|
|
11
|
+
* - clockwise = true 是否顺时针旋转
|
|
12
|
+
*
|
|
13
|
+
* events:
|
|
14
|
+
* - ready: cview => void 可以在ready事件中启动旋转
|
|
15
|
+
*
|
|
16
|
+
* methods:
|
|
17
|
+
* - startRotating() 开始旋转
|
|
18
|
+
* - stopRotating() 结束旋转,请注意旋转是不能立即结束的,必须等到动画归位
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.RotatingView = void 0;
|
|
22
|
+
const base_1 = require("./base");
|
|
23
|
+
const single_views_1 = require("./single-views");
|
|
24
|
+
class RotatingView extends base_1.Base {
|
|
25
|
+
constructor({ props, layout, events = {} }) {
|
|
26
|
+
super();
|
|
27
|
+
this._props = Object.assign({ contentMode: 1, rps: 0.5, clockwise: true }, props);
|
|
28
|
+
this._rotatingFlag = false;
|
|
29
|
+
if (this._props.cview) {
|
|
30
|
+
this._innerView = this._props.cview;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
if (!this._props.image)
|
|
34
|
+
throw new Error("image is required");
|
|
35
|
+
this._innerView = new single_views_1.Image({
|
|
36
|
+
props: {
|
|
37
|
+
image: this._props.tintColor
|
|
38
|
+
? this._props.image.alwaysTemplate
|
|
39
|
+
: this._props.image,
|
|
40
|
+
tintColor: this._props.tintColor,
|
|
41
|
+
contentMode: this._props.contentMode
|
|
42
|
+
},
|
|
43
|
+
layout: $layout.fill
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
this._defineView = () => {
|
|
47
|
+
return {
|
|
48
|
+
type: "view",
|
|
49
|
+
props: Object.assign(Object.assign({}, this._props), { id: this.id }),
|
|
50
|
+
layout,
|
|
51
|
+
events: {
|
|
52
|
+
ready: sender => {
|
|
53
|
+
if (events.ready)
|
|
54
|
+
events.ready(this);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
views: [this._innerView.definition]
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
startRotating() {
|
|
62
|
+
this._rotatingFlag = true;
|
|
63
|
+
this._rotateView(this._innerView.view);
|
|
64
|
+
}
|
|
65
|
+
stopRotating() {
|
|
66
|
+
this._rotatingFlag = false;
|
|
67
|
+
}
|
|
68
|
+
_rotateView(view) {
|
|
69
|
+
const clockwiseMultiplier = this._props.clockwise ? 1 : -1;
|
|
70
|
+
const duration = 1 / 3 / (this._props.rps || 0.5);
|
|
71
|
+
$ui.animate({
|
|
72
|
+
duration,
|
|
73
|
+
options: 3 << 16,
|
|
74
|
+
animation: () => {
|
|
75
|
+
view.rotate(Math.PI * 2 / 3 * clockwiseMultiplier);
|
|
76
|
+
},
|
|
77
|
+
completion: () => {
|
|
78
|
+
$ui.animate({
|
|
79
|
+
duration,
|
|
80
|
+
options: 3 << 16,
|
|
81
|
+
animation: () => {
|
|
82
|
+
view.rotate(Math.PI * 4 / 3 * clockwiseMultiplier);
|
|
83
|
+
},
|
|
84
|
+
completion: () => {
|
|
85
|
+
$ui.animate({
|
|
86
|
+
duration,
|
|
87
|
+
options: 3 << 16,
|
|
88
|
+
animation: () => {
|
|
89
|
+
view.rotate(Math.PI * 2 * clockwiseMultiplier);
|
|
90
|
+
},
|
|
91
|
+
completion: () => {
|
|
92
|
+
if (this._rotatingFlag)
|
|
93
|
+
this._rotateView(view);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.RotatingView = RotatingView;
|