UNPKG

35.2 kBJavaScriptView Raw
1// Requires
2import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common';
3import { hiddenProperty } from '../view-base';
4import { Trace } from '../../../trace';
5import { layout, iOSNativeHelper } from '../../../utils';
6import { IOSHelper } from './view-helper';
7import { ios as iosBackground } from '../../styling/background';
8import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties';
9import { profile } from '../../../profiling';
10import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
11import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties } from '../../../accessibility';
12import { CoreTypes } from '../../../core-types';
13export * from './view-common';
14// helpers (these are okay re-exported here)
15export * from './view-helper';
16// This one can eventually be cleaned up but causes issues with a lot of ui-suite plugins in particular if not exported here
17export * from '../properties';
18const PFLAG_FORCE_LAYOUT = 1;
19const PFLAG_MEASURED_DIMENSION_SET = 1 << 1;
20const PFLAG_LAYOUT_REQUIRED = 1 << 2;
21const majorVersion = iOSNativeHelper.MajorVersion;
22export 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 // first clears the measured dimension flag
61 this._privateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
62 // measure ourselves, this should set the measured dimension flag back
63 this.onMeasure(widthMeasureSpec, heightMeasureSpec);
64 this._privateFlags |= PFLAG_LAYOUT_REQUIRED;
65 // flag not set, setMeasuredDimension() was not invoked, we trace
66 // the exception to warn the developer
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 // on iOS 11+ it is possible to have a changed layout frame due to safe area insets
83 // get the frame and adjust the position, so that onLayout works correctly
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 // Always set identity transform before setting frame;
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 // re-apply the transform after the frame is adjusted
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 // Rects could be equal on the first layout and an event should be raised.
167 this._raiseLayoutChangedEvent();
168 // But make sure event is raised only once if rects are equal on the first layout as
169 // this method is called twice with equal rects in landscape mode (vs only once in portrait)
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 // Only set perspective if there is 3D rotation
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 // By default we update the view's presentation layer when setting backgroundColor and opacity properties.
335 // This is done by calling CATransaction begin and commit methods.
336 // This action should be disabled when updating those properties during an animation.
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 /* UIModalPresentationStyle.FullScreen */;
374 }
375 else {
376 controller.modalPresentationStyle = 2 /* UIModalPresentationStyle.FormSheet */;
377 //check whether both height and width is provided and are positive numbers
378 // set it has prefered content size to the controller presenting the dialog
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 //use CSS & attribute width & height if option is not provided
384 const handler = () => {
385 const w = (this.width || this.style.width);
386 const h = (this.height || this.style.height);
387 //TODO: only numeric value is supported, percentage value is not supported like Android
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 /* UIModalPresentationStyle.Popover */) {
400 this._setupPopoverControllerDelegate(controller, parent);
401 }
402 }
403 const cancelable = options.cancelable !== undefined ? !!options.cancelable : true;
404 if (majorVersion >= 13) {
405 if (cancelable) {
406 // Listen for dismiss modal callback.
407 this._setupAdaptiveControllerDelegate(controller);
408 }
409 else {
410 // Prevent users from dismissing the modal.
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 // track the user's animated options to use upon close as well
420 this._modalAnimatedOptions = [];
421 }
422 this._modalAnimatedOptions.push(animated);
423 // TODO: a11y
424 // controller.accessibilityViewIsModal = true;
425 // controller.accessibilityPerformEscape = () => {
426 // console.log('accessibilityPerformEscape!!')
427 // return true;
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 // Apparently iOS 9+ stops all transitions and animations upon application suspend and transitionCoordinator becomes null here in this case.
436 // Since we are not waiting for any transition to complete, i.e. transitionCoordinator is null, we can directly raise our shownModally event.
437 // Take a look at https://github.com/NativeScript/NativeScript/issues/2173 for more info and a sample project.
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 // modal view has already been closed by UI, probably as a popover
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 // ignore when using testID
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 // not sure if needed for Label:
512 // if ((<any>this).nativeTextViewProtected) {
513 // (<any>this).nativeTextViewProtected.accessibilityLabel = value;
514 // } else {
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 // Note: sourceView and sourceRect are needed to specify the anchor location for the popover.
736 // Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content
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);
757View.prototype._nativeBackgroundState = 'unset';
758export class ContainerView extends View {
759 constructor() {
760 super();
761 this.iosOverflowSafeArea = true;
762 }
763}
764export 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 // Don't call super because it will set MeasureDimension. This method must be overridden and calculate its measuredDimensions.
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//# sourceMappingURL=index.ios.js.map
\No newline at end of file