UNPKG

@nativescript/core

Version:

A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.

121 lines 5.41 kB
import { iosGlassEffectProperty } from '../../core/view'; import { LiquidGlassContainerCommon } from './liquid-glass-container-common'; import { toUIGlassStyle } from '../liquid-glass'; export class LiquidGlassContainer extends LiquidGlassContainerCommon { constructor() { super(...arguments); this._normalizing = false; } createNativeView() { // Keep UIVisualEffectView as the root to preserve interactive container effect const effect = UIGlassContainerEffect.alloc().init(); effect.spacing = 8; const effectView = UIVisualEffectView.alloc().initWithEffect(effect); effectView.overrideUserInterfaceStyle = 2 /* UIUserInterfaceStyle.Dark */; effectView.clipsToBounds = true; effectView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */; // Add a host view for children so parent can lay them out normally const host = UIView.new(); host.frame = effectView.bounds; host.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */; host.userInteractionEnabled = true; effectView.contentView.addSubview(host); this._contentHost = host; return effectView; } _addViewToNativeVisualTree(child, atIndex) { const parentNativeView = this._contentHost; const childNativeView = child.nativeViewProtected; if (parentNativeView && childNativeView) { if (typeof atIndex !== 'number' || atIndex >= parentNativeView.subviews.count) { parentNativeView.addSubview(childNativeView); } else { parentNativeView.insertSubviewAtIndex(childNativeView, atIndex); } // Add outer shadow layer manually as it belongs to parent layer tree (this is needed for reusable views) if (childNativeView.outerShadowContainerLayer && !childNativeView.outerShadowContainerLayer.superlayer) { this.nativeViewProtected.layer.insertSublayerBelow(childNativeView.outerShadowContainerLayer, childNativeView.layer); } // Normalize in case the child comes in with a residual translate from a previous state this._scheduleNormalize(); return true; } return false; } // When children animate with translate (layer transform), UIVisualEffectView-based // container effects may recompute based on the underlying frames (not transforms), // which can cause jumps. Normalize any residual translation into the // child's frame so the effect uses the final visual positions. onLayout(left, top, right, bottom) { super.onLayout(left, top, right, bottom); // Try to fold any pending translates into frames on each layout pass this._normalizeChildrenTransforms(); } // Allow callers to stabilize layout after custom animations stabilizeLayout() { this._normalizeChildrenTransforms(true); } _scheduleNormalize() { if (this._normalizing) return; this._normalizing = true; // Next tick to allow any pending frame/transform updates to settle setTimeout(() => { try { this._normalizeChildrenTransforms(); } finally { this._normalizing = false; } }); } _normalizeChildrenTransforms(force = false) { let changed = false; const count = this.getChildrenCount?.() ?? 0; for (let i = 0; i < count; i++) { const child = this.getChildAt(i); if (!child) continue; const tx = child.translateX || 0; const ty = child.translateY || 0; if (!tx && !ty) continue; const native = child.nativeViewProtected; if (!native) continue; // Skip if the child is still animating (unless forced) if (!force) { const keys = native.layer.animationKeys ? native.layer.animationKeys() : null; const hasAnimations = !!(keys && keys.count > 0); if (hasAnimations) continue; } const frame = native.frame; native.transform = CGAffineTransformIdentity; native.frame = CGRectMake(frame.origin.x + tx, frame.origin.y + ty, frame.size.width, frame.size.height); child.translateX = 0; child.translateY = 0; changed = true; } if (changed) { // Ask the effect view to re-evaluate its internal state using updated frames const nv = this.nativeViewProtected; if (nv) { nv.setNeedsLayout(); nv.layoutIfNeeded(); // Also request layout on contentView in case the effect inspects it directly nv.contentView?.setNeedsLayout?.(); nv.contentView?.layoutIfNeeded?.(); } } } [iosGlassEffectProperty.setNative](value) { this._applyGlassEffect(value, { effectType: 'container', targetView: this.nativeViewProtected, toGlassStyleFn: toUIGlassStyle, }); } } //# sourceMappingURL=index.ios.js.map