1 |
|
2 | import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common';
|
3 | import { hiddenProperty } from '../view-base';
|
4 | import { Trace } from '../../../trace';
|
5 | import { layout, iOSNativeHelper } from '../../../utils';
|
6 | import { IOSHelper } from './view-helper';
|
7 | import { ios as iosBackground } from '../../styling/background';
|
8 | import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties';
|
9 | import { profile } from '../../../profiling';
|
10 | import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
|
11 | import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties } from '../../../accessibility';
|
12 | import { CoreTypes } from '../../../core-types';
|
13 | export * from './view-common';
|
14 |
|
15 | export * from './view-helper';
|
16 |
|
17 | export * from '../properties';
|
18 | const PFLAG_FORCE_LAYOUT = 1;
|
19 | const PFLAG_MEASURED_DIMENSION_SET = 1 << 1;
|
20 | const PFLAG_LAYOUT_REQUIRED = 1 << 2;
|
21 | const majorVersion = iOSNativeHelper.MajorVersion;
|
22 | export class View extends ViewCommon {
|
23 | constructor() {
|
24 | super();
|
25 | this._isLaidOut = false;
|
26 | this._hasTransform = false;
|
27 | this._hasPendingTransform = false;
|
28 | this._privateFlags = PFLAG_LAYOUT_REQUIRED | PFLAG_FORCE_LAYOUT;
|
29 | this._suspendCATransaction = false;
|
30 | this.once(View.loadedEvent, () => setupAccessibleView(this));
|
31 | }
|
32 | get isLayoutRequired() {
|
33 | return (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED;
|
34 | }
|
35 | get isLayoutRequested() {
|
36 | return (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
|
37 | }
|
38 | disposeNativeView() {
|
39 | super.disposeNativeView();
|
40 | this._cachedFrame = null;
|
41 | this._isLaidOut = false;
|
42 | this._hasTransform = false;
|
43 | this._hasPendingTransform = false;
|
44 | }
|
45 | requestLayout() {
|
46 | super.requestLayout();
|
47 | this._privateFlags |= PFLAG_FORCE_LAYOUT;
|
48 | const nativeView = this.nativeViewProtected;
|
49 | if (nativeView && nativeView.setNeedsLayout) {
|
50 | nativeView.setNeedsLayout();
|
51 | }
|
52 | if (this.viewController && this.viewController.view !== nativeView) {
|
53 | this.viewController.view.setNeedsLayout();
|
54 | }
|
55 | }
|
56 | measure(widthMeasureSpec, heightMeasureSpec) {
|
57 | const measureSpecsChanged = this._setCurrentMeasureSpecs(widthMeasureSpec, heightMeasureSpec);
|
58 | const forceLayout = (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
|
59 | if (this.nativeViewProtected && (forceLayout || measureSpecsChanged)) {
|
60 |
|
61 | this._privateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
|
62 |
|
63 | this.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
64 | this._privateFlags |= PFLAG_LAYOUT_REQUIRED;
|
65 |
|
66 |
|
67 | if ((this._privateFlags & PFLAG_MEASURED_DIMENSION_SET) !== PFLAG_MEASURED_DIMENSION_SET) {
|
68 | if (Trace.isEnabled()) {
|
69 | Trace.write('onMeasure() did not set the measured dimension by calling setMeasuredDimension() ' + this, Trace.categories.Layout, Trace.messageType.error);
|
70 | }
|
71 | }
|
72 | }
|
73 | }
|
74 | layout(left, top, right, bottom, setFrame = true) {
|
75 | const { boundsChanged, sizeChanged } = this._setCurrentLayoutBounds(left, top, right, bottom);
|
76 | if (setFrame) {
|
77 | this.layoutNativeView(left, top, right, bottom);
|
78 | }
|
79 | if (boundsChanged || (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED) {
|
80 | let position = { left, top, right, bottom };
|
81 | if (this.nativeViewProtected && majorVersion > 10) {
|
82 |
|
83 |
|
84 | const frame = this.nativeViewProtected.frame;
|
85 | position = IOSHelper.getPositionFromFrame(frame);
|
86 | }
|
87 | this.onLayout(position.left, position.top, position.right, position.bottom);
|
88 | this._privateFlags &= ~PFLAG_LAYOUT_REQUIRED;
|
89 | }
|
90 | this.updateBackground(sizeChanged);
|
91 | if (this._hasPendingTransform) {
|
92 | this.updateNativeTransform();
|
93 | this._hasPendingTransform = false;
|
94 | }
|
95 | this._privateFlags &= ~PFLAG_FORCE_LAYOUT;
|
96 | }
|
97 | updateBackground(sizeChanged) {
|
98 | if (sizeChanged) {
|
99 | this._onSizeChanged();
|
100 | }
|
101 | else if (this._nativeBackgroundState === 'invalid') {
|
102 | const background = this.style.backgroundInternal;
|
103 | this._redrawNativeBackground(background);
|
104 | }
|
105 | }
|
106 | setMeasuredDimension(measuredWidth, measuredHeight) {
|
107 | super.setMeasuredDimension(measuredWidth, measuredHeight);
|
108 | this._privateFlags |= PFLAG_MEASURED_DIMENSION_SET;
|
109 | }
|
110 | onMeasure(widthMeasureSpec, heightMeasureSpec) {
|
111 | const view = this.nativeViewProtected;
|
112 | const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
113 | const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
114 | const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
115 | const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
116 | let nativeWidth = 0;
|
117 | let nativeHeight = 0;
|
118 | if (view) {
|
119 | const nativeSize = layout.measureNativeView(view, width, widthMode, height, heightMode);
|
120 | nativeWidth = nativeSize.width;
|
121 | nativeHeight = nativeSize.height;
|
122 | }
|
123 | const measureWidth = Math.max(nativeWidth, this.effectiveMinWidth);
|
124 | const measureHeight = Math.max(nativeHeight, this.effectiveMinHeight);
|
125 | const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
126 | const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
127 | this.setMeasuredDimension(widthAndState, heightAndState);
|
128 | }
|
129 | onLayout(left, top, right, bottom) {
|
130 |
|
131 | }
|
132 | _setNativeViewFrame(nativeView, frame) {
|
133 | const oldFrame = this._cachedFrame || nativeView.frame;
|
134 | if (!CGRectEqualToRect(oldFrame, frame)) {
|
135 | if (Trace.isEnabled()) {
|
136 | Trace.write(this + ' :_setNativeViewFrame: ' + JSON.stringify(IOSHelper.getPositionFromFrame(frame)), Trace.categories.Layout);
|
137 | }
|
138 | this._cachedFrame = frame;
|
139 | let adjustedFrame = null;
|
140 | let transform = null;
|
141 | if (this._hasTransform) {
|
142 |
|
143 | transform = nativeView.layer.transform;
|
144 | nativeView.layer.transform = CATransform3DIdentity;
|
145 | nativeView.frame = frame;
|
146 | }
|
147 | else {
|
148 | nativeView.frame = frame;
|
149 | }
|
150 | adjustedFrame = this.applySafeAreaInsets(frame);
|
151 | if (adjustedFrame) {
|
152 | nativeView.frame = adjustedFrame;
|
153 | }
|
154 | if (this._hasTransform) {
|
155 |
|
156 | nativeView.layer.transform = transform;
|
157 | }
|
158 | const boundsOrigin = nativeView.bounds.origin;
|
159 | const boundsFrame = adjustedFrame || frame;
|
160 | nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, boundsFrame.size.width, boundsFrame.size.height);
|
161 | nativeView.layoutIfNeeded();
|
162 | this._raiseLayoutChangedEvent();
|
163 | this._isLaidOut = true;
|
164 | }
|
165 | else if (!this._isLaidOut) {
|
166 |
|
167 | this._raiseLayoutChangedEvent();
|
168 |
|
169 |
|
170 | this._isLaidOut = true;
|
171 | }
|
172 | }
|
173 | get isLayoutValid() {
|
174 | if (this.nativeViewProtected) {
|
175 | return this._isLayoutValid;
|
176 | }
|
177 | return false;
|
178 | }
|
179 | layoutNativeView(left, top, right, bottom) {
|
180 | if (!this.nativeViewProtected) {
|
181 | return;
|
182 | }
|
183 | const nativeView = this.nativeViewProtected;
|
184 | const frame = IOSHelper.getFrameFromPosition({
|
185 | left,
|
186 | top,
|
187 | right,
|
188 | bottom,
|
189 | });
|
190 | this._setNativeViewFrame(nativeView, frame);
|
191 | }
|
192 | _layoutParent() {
|
193 | if (this.nativeViewProtected) {
|
194 | const frame = this.nativeViewProtected.frame;
|
195 | const origin = frame.origin;
|
196 | const size = frame.size;
|
197 | const left = layout.toDevicePixels(origin.x);
|
198 | const top = layout.toDevicePixels(origin.y);
|
199 | const width = layout.toDevicePixels(size.width);
|
200 | const height = layout.toDevicePixels(size.height);
|
201 | this._setLayoutFlags(left, top, width + left, height + top);
|
202 | }
|
203 | super._layoutParent();
|
204 | }
|
205 | _setLayoutFlags(left, top, right, bottom) {
|
206 | const width = right - left;
|
207 | const height = bottom - top;
|
208 | const widthSpec = layout.makeMeasureSpec(width, layout.EXACTLY);
|
209 | const heightSpec = layout.makeMeasureSpec(height, layout.EXACTLY);
|
210 | this._setCurrentMeasureSpecs(widthSpec, heightSpec);
|
211 | this._privateFlags &= ~PFLAG_FORCE_LAYOUT;
|
212 | this.setMeasuredDimension(width, height);
|
213 | const { sizeChanged } = this._setCurrentLayoutBounds(left, top, right, bottom);
|
214 | this.updateBackground(sizeChanged);
|
215 | this._privateFlags &= ~PFLAG_LAYOUT_REQUIRED;
|
216 | }
|
217 | focus() {
|
218 | if (this.ios) {
|
219 | return this.ios.becomeFirstResponder();
|
220 | }
|
221 | return false;
|
222 | }
|
223 | applySafeAreaInsets(frame) {
|
224 | if (majorVersion <= 10) {
|
225 | return null;
|
226 | }
|
227 | if (this.iosIgnoreSafeArea) {
|
228 | return frame;
|
229 | }
|
230 | if (!this.iosOverflowSafeArea || !this.iosOverflowSafeAreaEnabled) {
|
231 | return IOSHelper.shrinkToSafeArea(this, frame);
|
232 | }
|
233 | else if (this.nativeViewProtected && this.nativeViewProtected.window) {
|
234 | return IOSHelper.expandBeyondSafeArea(this, frame);
|
235 | }
|
236 | return null;
|
237 | }
|
238 | getSafeAreaInsets() {
|
239 | const safeAreaInsets = this.nativeViewProtected && this.nativeViewProtected.safeAreaInsets;
|
240 | const insets = { left: 0, top: 0, right: 0, bottom: 0 };
|
241 | if (this.iosIgnoreSafeArea) {
|
242 | return insets;
|
243 | }
|
244 | if (safeAreaInsets) {
|
245 | insets.left = layout.round(layout.toDevicePixels(safeAreaInsets.left));
|
246 | insets.top = layout.round(layout.toDevicePixels(safeAreaInsets.top));
|
247 | insets.right = layout.round(layout.toDevicePixels(safeAreaInsets.right));
|
248 | insets.bottom = layout.round(layout.toDevicePixels(safeAreaInsets.bottom));
|
249 | }
|
250 | return insets;
|
251 | }
|
252 | getLocationInWindow() {
|
253 | if (!this.nativeViewProtected || !this.nativeViewProtected.window) {
|
254 | return undefined;
|
255 | }
|
256 | const pointInWindow = this.nativeViewProtected.convertPointToView(this.nativeViewProtected.bounds.origin, null);
|
257 | return {
|
258 | x: pointInWindow.x,
|
259 | y: pointInWindow.y,
|
260 | };
|
261 | }
|
262 | getLocationOnScreen() {
|
263 | if (!this.nativeViewProtected || !this.nativeViewProtected.window) {
|
264 | return undefined;
|
265 | }
|
266 | const pointInWindow = this.nativeViewProtected.convertPointToView(this.nativeViewProtected.bounds.origin, null);
|
267 | const pointOnScreen = this.nativeViewProtected.window.convertPointToWindow(pointInWindow, null);
|
268 | return {
|
269 | x: pointOnScreen.x,
|
270 | y: pointOnScreen.y,
|
271 | };
|
272 | }
|
273 | getLocationRelativeTo(otherView) {
|
274 | if (!this.nativeViewProtected || !this.nativeViewProtected.window || !otherView.nativeViewProtected || !otherView.nativeViewProtected.window || this.nativeViewProtected.window !== otherView.nativeViewProtected.window) {
|
275 | return undefined;
|
276 | }
|
277 | const myPointInWindow = this.nativeViewProtected.convertPointToView(this.nativeViewProtected.bounds.origin, null);
|
278 | const otherPointInWindow = otherView.nativeViewProtected.convertPointToView(otherView.nativeViewProtected.bounds.origin, null);
|
279 | return {
|
280 | x: myPointInWindow.x - otherPointInWindow.x,
|
281 | y: myPointInWindow.y - otherPointInWindow.y,
|
282 | };
|
283 | }
|
284 | _onSizeChanged() {
|
285 | const nativeView = this.nativeViewProtected;
|
286 | if (!nativeView) {
|
287 | return;
|
288 | }
|
289 | const background = this.style.backgroundInternal;
|
290 | const backgroundDependsOnSize = (background.image && background.image !== 'none') || !background.hasUniformBorder() || background.hasBorderRadius();
|
291 | if (this._nativeBackgroundState === 'invalid' || (this._nativeBackgroundState === 'drawn' && backgroundDependsOnSize)) {
|
292 | this._redrawNativeBackground(background);
|
293 | }
|
294 | const clipPath = this.style.clipPath;
|
295 | if (clipPath !== '' && this[clipPathProperty.setNative]) {
|
296 | this[clipPathProperty.setNative](clipPath);
|
297 | }
|
298 | }
|
299 | updateNativeTransform() {
|
300 | if (!this.isLayoutValid) {
|
301 | this._hasPendingTransform = true;
|
302 | return;
|
303 | }
|
304 | const scaleX = this.scaleX || 1e-6;
|
305 | const scaleY = this.scaleY || 1e-6;
|
306 | const perspective = this.perspective || 300;
|
307 | let transform = new CATransform3D(CATransform3DIdentity);
|
308 |
|
309 | if (this.rotateX || this.rotateY) {
|
310 | transform.m34 = -1 / perspective;
|
311 | }
|
312 | transform = CATransform3DTranslate(transform, this.translateX, this.translateY, 0);
|
313 | transform = iOSNativeHelper.applyRotateTransform(transform, this.rotateX, this.rotateY, this.rotate);
|
314 | transform = CATransform3DScale(transform, scaleX, scaleY, 1);
|
315 | if (!CATransform3DEqualToTransform(this.nativeViewProtected.layer.transform, transform)) {
|
316 | const updateSuspended = this._isPresentationLayerUpdateSuspended();
|
317 | if (!updateSuspended) {
|
318 | CATransaction.begin();
|
319 | }
|
320 | this.nativeViewProtected.layer.transform = transform;
|
321 | this._hasTransform = this.nativeViewProtected && !CATransform3DEqualToTransform(this.nativeViewProtected.transform3D, CATransform3DIdentity);
|
322 | if (!updateSuspended) {
|
323 | CATransaction.commit();
|
324 | }
|
325 | }
|
326 | }
|
327 | updateOriginPoint(originX, originY) {
|
328 | const newPoint = CGPointMake(originX, originY);
|
329 | this.nativeViewProtected.layer.anchorPoint = newPoint;
|
330 | if (this._cachedFrame) {
|
331 | this._setNativeViewFrame(this.nativeViewProtected, this._cachedFrame);
|
332 | }
|
333 | }
|
334 |
|
335 |
|
336 |
|
337 | _suspendPresentationLayerUpdates() {
|
338 | this._suspendCATransaction = true;
|
339 | }
|
340 | _resumePresentationLayerUpdates() {
|
341 | this._suspendCATransaction = false;
|
342 | }
|
343 | _isPresentationLayerUpdateSuspended() {
|
344 | return this._suspendCATransaction || this._suspendNativeUpdatesCount > 0;
|
345 | }
|
346 | _showNativeModalView(parent, options) {
|
347 | const parentWithController = IOSHelper.getParentWithViewController(parent);
|
348 | if (!parentWithController) {
|
349 | Trace.write(`Could not find parent with viewController for ${parent} while showing modal view.`, Trace.categories.ViewHierarchy, Trace.messageType.error);
|
350 | return;
|
351 | }
|
352 | const parentController = parentWithController.viewController;
|
353 | if (parentController.presentedViewController) {
|
354 | Trace.write('Parent is already presenting view controller. Close the current modal page before showing another one!', Trace.categories.ViewHierarchy, Trace.messageType.error);
|
355 | return;
|
356 | }
|
357 | if (!parentController.view || !parentController.view.window) {
|
358 | Trace.write('Parent page is not part of the window hierarchy.', Trace.categories.ViewHierarchy, Trace.messageType.error);
|
359 | return;
|
360 | }
|
361 | this._setupAsRootView({});
|
362 | super._showNativeModalView(parentWithController, options);
|
363 | let controller = this.viewController;
|
364 | if (!controller) {
|
365 | const nativeView = this.ios || this.nativeViewProtected;
|
366 | controller = IOSHelper.UILayoutViewController.initWithOwner(new WeakRef(this));
|
367 | if (nativeView instanceof UIView) {
|
368 | controller.view.addSubview(nativeView);
|
369 | }
|
370 | this.viewController = controller;
|
371 | }
|
372 | if (options.fullscreen) {
|
373 | controller.modalPresentationStyle = 0 ;
|
374 | }
|
375 | else {
|
376 | controller.modalPresentationStyle = 2 ;
|
377 |
|
378 |
|
379 | if (options.ios && options.ios.width > 0 && options.ios.height > 0) {
|
380 | controller.preferredContentSize = CGSizeMake(options.ios.width, options.ios.height);
|
381 | }
|
382 | else {
|
383 |
|
384 | const handler = () => {
|
385 | const w = (this.width || this.style.width);
|
386 | const h = (this.height || this.style.height);
|
387 |
|
388 | if (w > 0 && h > 0) {
|
389 | controller.preferredContentSize = CGSizeMake(w, h);
|
390 | }
|
391 | this.off(View.loadedEvent, handler);
|
392 | };
|
393 | this.on(View.loadedEvent, handler);
|
394 | }
|
395 | }
|
396 | if (options.ios && options.ios.presentationStyle) {
|
397 | const presentationStyle = options.ios.presentationStyle;
|
398 | controller.modalPresentationStyle = presentationStyle;
|
399 | if (presentationStyle === 7 ) {
|
400 | this._setupPopoverControllerDelegate(controller, parent);
|
401 | }
|
402 | }
|
403 | const cancelable = options.cancelable !== undefined ? !!options.cancelable : true;
|
404 | if (majorVersion >= 13) {
|
405 | if (cancelable) {
|
406 |
|
407 | this._setupAdaptiveControllerDelegate(controller);
|
408 | }
|
409 | else {
|
410 |
|
411 | controller.modalInPresentation = true;
|
412 | }
|
413 | }
|
414 | this.horizontalAlignment = 'stretch';
|
415 | this.verticalAlignment = 'stretch';
|
416 | this._raiseShowingModallyEvent();
|
417 | const animated = options.animated === undefined ? true : !!options.animated;
|
418 | if (!this._modalAnimatedOptions) {
|
419 |
|
420 | this._modalAnimatedOptions = [];
|
421 | }
|
422 | this._modalAnimatedOptions.push(animated);
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 | parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
|
430 | const transitionCoordinator = parentController.transitionCoordinator;
|
431 | if (transitionCoordinator) {
|
432 | transitionCoordinator.animateAlongsideTransitionCompletion(null, () => this._raiseShownModallyEvent());
|
433 | }
|
434 | else {
|
435 |
|
436 |
|
437 |
|
438 | this._raiseShownModallyEvent();
|
439 | }
|
440 | controller = null;
|
441 | }
|
442 | _hideNativeModalView(parent, whenClosedCallback) {
|
443 | if (!parent || !parent.viewController) {
|
444 | Trace.error('Trying to hide modal view but no parent with viewController specified.');
|
445 | return;
|
446 | }
|
447 |
|
448 | if (!parent.viewController.presentedViewController) {
|
449 | whenClosedCallback();
|
450 | return;
|
451 | }
|
452 | const parentController = parent.viewController;
|
453 | const animated = this._modalAnimatedOptions ? !!this._modalAnimatedOptions.pop() : true;
|
454 | parentController.dismissViewControllerAnimatedCompletion(animated, whenClosedCallback);
|
455 | }
|
456 | [isEnabledProperty.getDefault]() {
|
457 | const nativeView = this.nativeViewProtected;
|
458 | return nativeView instanceof UIControl ? nativeView.enabled : true;
|
459 | }
|
460 | [isEnabledProperty.setNative](value) {
|
461 | const nativeView = this.nativeViewProtected;
|
462 | if (nativeView instanceof UIControl) {
|
463 | nativeView.enabled = value;
|
464 | }
|
465 | }
|
466 | [originXProperty.getDefault]() {
|
467 | return this.nativeViewProtected.layer.anchorPoint.x;
|
468 | }
|
469 | [originXProperty.setNative](value) {
|
470 | this.updateOriginPoint(value, this.originY);
|
471 | }
|
472 | [originYProperty.getDefault]() {
|
473 | return this.nativeViewProtected.layer.anchorPoint.y;
|
474 | }
|
475 | [originYProperty.setNative](value) {
|
476 | this.updateOriginPoint(this.originX, value);
|
477 | }
|
478 | [testIDProperty.setNative](value) {
|
479 | this.setTestID(this.nativeViewProtected, value);
|
480 | }
|
481 | setTestID(view, value) {
|
482 | if (typeof __USE_TEST_ID__ !== 'undefined' && __USE_TEST_ID__) {
|
483 | view.accessibilityIdentifier = value;
|
484 | }
|
485 | }
|
486 | [accessibilityEnabledProperty.setNative](value) {
|
487 | this.nativeViewProtected.isAccessibilityElement = !!value;
|
488 | updateAccessibilityProperties(this);
|
489 | }
|
490 | [accessibilityIdentifierProperty.getDefault]() {
|
491 | return this.nativeViewProtected.accessibilityLabel;
|
492 | }
|
493 | [accessibilityIdentifierProperty.setNative](value) {
|
494 | if (typeof __USE_TEST_ID__ !== 'undefined' && __USE_TEST_ID__ && this.testID) {
|
495 |
|
496 | }
|
497 | else {
|
498 | this.nativeViewProtected.accessibilityIdentifier = value;
|
499 | }
|
500 | }
|
501 | [accessibilityRoleProperty.setNative](value) {
|
502 | this.accessibilityRole = value;
|
503 | updateAccessibilityProperties(this);
|
504 | }
|
505 | [accessibilityValueProperty.setNative](value) {
|
506 | value = value == null ? null : `${value}`;
|
507 | this.nativeViewProtected.accessibilityValue = value;
|
508 | }
|
509 | [accessibilityLabelProperty.setNative](value) {
|
510 | value = value == null ? null : `${value}`;
|
511 |
|
512 |
|
513 |
|
514 |
|
515 | this.nativeViewProtected.accessibilityLabel = value;
|
516 |
|
517 | }
|
518 | [accessibilityHintProperty.setNative](value) {
|
519 | value = value == null ? null : `${value}`;
|
520 | this.nativeViewProtected.accessibilityHint = value;
|
521 | }
|
522 | [accessibilityIgnoresInvertColorsProperty.setNative](value) {
|
523 | this.nativeViewProtected.accessibilityIgnoresInvertColors = !!value;
|
524 | }
|
525 | [accessibilityLanguageProperty.setNative](value) {
|
526 | value = value == null ? null : `${value}`;
|
527 | this.nativeViewProtected.accessibilityLanguage = value;
|
528 | }
|
529 | [accessibilityHiddenProperty.setNative](value) {
|
530 | this.nativeViewProtected.accessibilityElementsHidden = !!value;
|
531 | updateAccessibilityProperties(this);
|
532 | }
|
533 | [accessibilityLiveRegionProperty.setNative]() {
|
534 | updateAccessibilityProperties(this);
|
535 | }
|
536 | [accessibilityStateProperty.setNative](value) {
|
537 | this.accessibilityState = value;
|
538 | updateAccessibilityProperties(this);
|
539 | }
|
540 | [accessibilityMediaSessionProperty.setNative]() {
|
541 | updateAccessibilityProperties(this);
|
542 | }
|
543 | [isUserInteractionEnabledProperty.getDefault]() {
|
544 | return this.nativeViewProtected.userInteractionEnabled;
|
545 | }
|
546 | [isUserInteractionEnabledProperty.setNative](value) {
|
547 | this.nativeViewProtected.userInteractionEnabled = value;
|
548 | }
|
549 | [hiddenProperty.getDefault]() {
|
550 | return this.nativeViewProtected.hidden;
|
551 | }
|
552 | [hiddenProperty.setNative](value) {
|
553 | this.nativeViewProtected.hidden = value;
|
554 | }
|
555 | [visibilityProperty.getDefault]() {
|
556 | return this.nativeViewProtected.hidden ? CoreTypes.Visibility.collapse : CoreTypes.Visibility.visible;
|
557 | }
|
558 | [visibilityProperty.setNative](value) {
|
559 | switch (value) {
|
560 | case CoreTypes.Visibility.visible:
|
561 | this.nativeViewProtected.hidden = false;
|
562 | break;
|
563 | case CoreTypes.Visibility.hidden:
|
564 | case CoreTypes.Visibility.collapse:
|
565 | this.nativeViewProtected.hidden = true;
|
566 | break;
|
567 | default:
|
568 | throw new Error(`Invalid visibility value: ${value}. Valid values are: "${CoreTypes.Visibility.visible}", "${CoreTypes.Visibility.hidden}", "${CoreTypes.Visibility.collapse}".`);
|
569 | }
|
570 | }
|
571 | [opacityProperty.getDefault]() {
|
572 | return this.nativeViewProtected.alpha;
|
573 | }
|
574 | [opacityProperty.setNative](value) {
|
575 | const nativeView = this.nativeViewProtected;
|
576 | const updateSuspended = this._isPresentationLayerUpdateSuspended();
|
577 | if (!updateSuspended) {
|
578 | CATransaction.begin();
|
579 | }
|
580 | nativeView.alpha = value;
|
581 | if (!updateSuspended) {
|
582 | CATransaction.commit();
|
583 | }
|
584 | }
|
585 | [rotateProperty.getDefault]() {
|
586 | return 0;
|
587 | }
|
588 | [rotateProperty.setNative](value) {
|
589 | this.updateNativeTransform();
|
590 | }
|
591 | [rotateXProperty.getDefault]() {
|
592 | return 0;
|
593 | }
|
594 | [rotateXProperty.setNative](value) {
|
595 | this.updateNativeTransform();
|
596 | }
|
597 | [rotateYProperty.getDefault]() {
|
598 | return 0;
|
599 | }
|
600 | [rotateYProperty.setNative](value) {
|
601 | this.updateNativeTransform();
|
602 | }
|
603 | [perspectiveProperty.getDefault]() {
|
604 | return 300;
|
605 | }
|
606 | [perspectiveProperty.setNative](value) {
|
607 | this.updateNativeTransform();
|
608 | }
|
609 | [scaleXProperty.getDefault]() {
|
610 | return 1;
|
611 | }
|
612 | [scaleXProperty.setNative](value) {
|
613 | this.updateNativeTransform();
|
614 | }
|
615 | [scaleYProperty.getDefault]() {
|
616 | return 1;
|
617 | }
|
618 | [scaleYProperty.setNative](value) {
|
619 | this.updateNativeTransform();
|
620 | }
|
621 | [translateXProperty.getDefault]() {
|
622 | return 0;
|
623 | }
|
624 | [translateXProperty.setNative](value) {
|
625 | this.updateNativeTransform();
|
626 | }
|
627 | [translateYProperty.getDefault]() {
|
628 | return 0;
|
629 | }
|
630 | [translateYProperty.setNative](value) {
|
631 | this.updateNativeTransform();
|
632 | }
|
633 | [zIndexProperty.getDefault]() {
|
634 | return 0;
|
635 | }
|
636 | [zIndexProperty.setNative](value) {
|
637 | this.nativeViewProtected.layer.zPosition = value;
|
638 | }
|
639 | [backgroundInternalProperty.getDefault]() {
|
640 | return this.nativeViewProtected.backgroundColor;
|
641 | }
|
642 | [backgroundInternalProperty.setNative](value) {
|
643 | this._nativeBackgroundState = 'invalid';
|
644 | if (this.isLayoutValid) {
|
645 | this._redrawNativeBackground(value);
|
646 | }
|
647 | }
|
648 | sendAccessibilityEvent(options) {
|
649 | if (!isAccessibilityServiceEnabled()) {
|
650 | return;
|
651 | }
|
652 | if (!options.iosNotificationType) {
|
653 | return;
|
654 | }
|
655 | let notification;
|
656 | let args = this.nativeViewProtected;
|
657 | if (typeof msg === 'string' && msg) {
|
658 | args = msg;
|
659 | }
|
660 | switch (options.iosNotificationType) {
|
661 | case IOSPostAccessibilityNotificationType.Announcement: {
|
662 | notification = UIAccessibilityAnnouncementNotification;
|
663 | break;
|
664 | }
|
665 | case IOSPostAccessibilityNotificationType.Layout: {
|
666 | notification = UIAccessibilityLayoutChangedNotification;
|
667 | break;
|
668 | }
|
669 | case IOSPostAccessibilityNotificationType.Screen: {
|
670 | notification = UIAccessibilityScreenChangedNotification;
|
671 | break;
|
672 | }
|
673 | default: {
|
674 | return;
|
675 | }
|
676 | }
|
677 | UIAccessibilityPostNotification(notification, args !== null && args !== void 0 ? args : null);
|
678 | }
|
679 | accessibilityAnnouncement(msg = this.accessibilityLabel) {
|
680 | this.sendAccessibilityEvent({
|
681 | iosNotificationType: IOSPostAccessibilityNotificationType.Announcement,
|
682 | message: msg,
|
683 | });
|
684 | }
|
685 | accessibilityScreenChanged() {
|
686 | this.sendAccessibilityEvent({
|
687 | iosNotificationType: IOSPostAccessibilityNotificationType.Screen,
|
688 | });
|
689 | }
|
690 | _getCurrentLayoutBounds() {
|
691 | const nativeView = this.nativeViewProtected;
|
692 | if (nativeView && !this.isCollapsed) {
|
693 | const frame = nativeView.frame;
|
694 | const origin = frame.origin;
|
695 | const size = frame.size;
|
696 | return {
|
697 | left: Math.round(layout.toDevicePixels(origin.x)),
|
698 | top: Math.round(layout.toDevicePixels(origin.y)),
|
699 | right: Math.round(layout.toDevicePixels(origin.x + size.width)),
|
700 | bottom: Math.round(layout.toDevicePixels(origin.y + size.height)),
|
701 | };
|
702 | }
|
703 | else {
|
704 | return { left: 0, top: 0, right: 0, bottom: 0 };
|
705 | }
|
706 | }
|
707 | _redrawNativeBackground(value) {
|
708 | const updateSuspended = this._isPresentationLayerUpdateSuspended();
|
709 | if (!updateSuspended) {
|
710 | CATransaction.begin();
|
711 | }
|
712 | if (value instanceof UIColor) {
|
713 | this.nativeViewProtected.backgroundColor = value;
|
714 | }
|
715 | else {
|
716 | iosBackground.createBackgroundUIColor(this, (color) => {
|
717 | this.nativeViewProtected.backgroundColor = color;
|
718 | });
|
719 | this._setNativeClipToBounds();
|
720 | }
|
721 | if (!updateSuspended) {
|
722 | CATransaction.commit();
|
723 | }
|
724 | this._nativeBackgroundState = 'drawn';
|
725 | }
|
726 | _setNativeClipToBounds() {
|
727 | const backgroundInternal = this.style.backgroundInternal;
|
728 | this.nativeViewProtected.clipsToBounds = (this.nativeViewProtected instanceof UIScrollView || backgroundInternal.hasBorderWidth() || backgroundInternal.hasBorderRadius()) && !backgroundInternal.hasBoxShadow();
|
729 | }
|
730 | _setupPopoverControllerDelegate(controller, parent) {
|
731 | const popoverPresentationController = controller.popoverPresentationController;
|
732 | this._popoverPresentationDelegate = IOSHelper.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
|
733 | popoverPresentationController.delegate = this._popoverPresentationDelegate;
|
734 | const view = parent.nativeViewProtected;
|
735 |
|
736 |
|
737 | popoverPresentationController.sourceView = view;
|
738 | popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
|
739 | }
|
740 | _setupAdaptiveControllerDelegate(controller) {
|
741 | this._adaptivePresentationDelegate = IOSHelper.UIAdaptivePresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
|
742 | controller.presentationController.delegate = this._adaptivePresentationDelegate;
|
743 | }
|
744 | }
|
745 | __decorate([
|
746 | profile,
|
747 | __metadata("design:type", Function),
|
748 | __metadata("design:paramtypes", [Number, Number, Number, Number, Object]),
|
749 | __metadata("design:returntype", void 0)
|
750 | ], View.prototype, "layout", null);
|
751 | __decorate([
|
752 | profile,
|
753 | __metadata("design:type", Function),
|
754 | __metadata("design:paramtypes", [Number, Number]),
|
755 | __metadata("design:returntype", void 0)
|
756 | ], View.prototype, "onMeasure", null);
|
757 | View.prototype._nativeBackgroundState = 'unset';
|
758 | export class ContainerView extends View {
|
759 | constructor() {
|
760 | super();
|
761 | this.iosOverflowSafeArea = true;
|
762 | }
|
763 | }
|
764 | export class CustomLayoutView extends ContainerView {
|
765 | createNativeView() {
|
766 | return UIView.alloc().initWithFrame(UIScreen.mainScreen.bounds);
|
767 | }
|
768 | get ios() {
|
769 | return this.nativeViewProtected;
|
770 | }
|
771 | onMeasure(widthMeasureSpec, heightMeasureSpec) {
|
772 |
|
773 | }
|
774 | _addViewToNativeVisualTree(child, atIndex) {
|
775 | super._addViewToNativeVisualTree(child, atIndex);
|
776 | const parentNativeView = this.nativeViewProtected;
|
777 | const childNativeView = child.nativeViewProtected;
|
778 | if (parentNativeView && childNativeView) {
|
779 | if (typeof atIndex !== 'number' || atIndex >= parentNativeView.subviews.count) {
|
780 | parentNativeView.addSubview(childNativeView);
|
781 | }
|
782 | else {
|
783 | parentNativeView.insertSubviewAtIndex(childNativeView, atIndex);
|
784 | }
|
785 | return true;
|
786 | }
|
787 | return false;
|
788 | }
|
789 | _removeViewFromNativeVisualTree(child) {
|
790 | super._removeViewFromNativeVisualTree(child);
|
791 | if (child.nativeViewProtected) {
|
792 | child.nativeViewProtected.removeFromSuperview();
|
793 | }
|
794 | }
|
795 | }
|
796 |
|
\ | No newline at end of file |