UNPKG

@nativescript/core

Version:

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

787 lines • 34.2 kB
import { Font } from '../styling/font'; import { IOSHelper, View } from '../core/view'; import { TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, tabTextColorProperty, tabTextFontSizeProperty, tabBackgroundColorProperty, selectedTabTextColorProperty, iosIconRenderingModeProperty, traceMissingIcon, iosBottomAccessoryProperty, iosTabBarMinimizeBehaviorProperty } from './tab-view-common'; import { Color } from '../../color'; import { Trace } from '../../trace'; import { fontInternalProperty } from '../styling/style-properties'; import { textTransformProperty, getTransformedText } from '../text-base'; import { ImageSource } from '../../image-source'; import { profile } from '../../profiling'; import { Frame } from '../frame'; import { layout } from '../../utils/layout-helper'; import { FONT_PREFIX, isFontIconURI, isSystemURI, SYSTEM_PREFIX } from '../../utils/common'; import { SDK_VERSION } from '../../utils/constants'; import { Device, Screen } from '../../platform'; export * from './tab-view-common'; var UITabBarControllerImpl = (function (_super) { __extends(UITabBarControllerImpl, _super); function UITabBarControllerImpl() { return _super !== null && _super.apply(this, arguments) || this; } UITabBarControllerImpl.initWithOwner = function (owner) { var handler = UITabBarControllerImpl.new(); handler._owner = owner; return handler; }; UITabBarControllerImpl.prototype.viewDidLoad = function () { _super.prototype.viewDidLoad.call(this); this.extendedLayoutIncludesOpaqueBars = true; }; UITabBarControllerImpl.prototype.viewWillAppear = function (animated) { var _a; _super.prototype.viewWillAppear.call(this, animated); var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (!owner) { return; } IOSHelper.updateAutoAdjustScrollInsets(this, owner); if (!owner.parent) { owner.callLoaded(); } }; UITabBarControllerImpl.prototype.viewDidDisappear = function (animated) { var _a; _super.prototype.viewDidDisappear.call(this, animated); var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner && !owner.parent && owner.isLoaded && !this.presentedViewController) { owner.callUnloaded(); } }; UITabBarControllerImpl.prototype.viewWillTransitionToSizeWithTransitionCoordinator = function (size, coordinator) { var _this = this; _super.prototype.viewWillTransitionToSizeWithTransitionCoordinator.call(this, size, coordinator); coordinator.animateAlongsideTransitionCompletion(null, function () { var _a; var owner = (_a = _this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner && owner.items) { owner.items.forEach(function (tabItem) { return tabItem._updateTitleAndIconPositions(); }); } }); }; UITabBarControllerImpl.prototype.traitCollectionDidChange = function (previousTraitCollection) { var _a; _super.prototype.traitCollectionDidChange.call(this, previousTraitCollection); var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner) { if (SDK_VERSION >= 13) { if (this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)) { owner.notify({ eventName: IOSHelper.traitCollectionColorAppearanceChangedEvent, object: owner, }); } } if (this.traitCollection.layoutDirection !== previousTraitCollection.layoutDirection) { owner.notify({ eventName: IOSHelper.traitCollectionLayoutDirectionChangedEvent, object: owner, }); } } }; __decorate([ profile ], UITabBarControllerImpl.prototype, "viewWillAppear", null); __decorate([ profile ], UITabBarControllerImpl.prototype, "viewDidDisappear", null); return UITabBarControllerImpl; }(UITabBarController)); var UITabBarControllerDelegateImpl = (function (_super) { __extends(UITabBarControllerDelegateImpl, _super); function UITabBarControllerDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } UITabBarControllerDelegateImpl.initWithOwner = function (owner) { var delegate = UITabBarControllerDelegateImpl.new(); delegate._owner = owner; return delegate; }; UITabBarControllerDelegateImpl.prototype.tabBarControllerShouldSelectViewController = function (tabBarController, viewController) { var _a; if (Trace.isEnabled()) { Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); } var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner) { owner._handleTwoNavigationBars(false); } if (tabBarController.selectedViewController === viewController) { return false; } return true; }; UITabBarControllerDelegateImpl.prototype.tabBarControllerDidSelectViewController = function (tabBarController, viewController) { var _a; if (Trace.isEnabled()) { Trace.write("TabView.delegate.DID_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); } var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner) { owner._onViewControllerShown(tabBarController, viewController); } }; UITabBarControllerDelegateImpl.ObjCProtocols = [UITabBarControllerDelegate]; return UITabBarControllerDelegateImpl; }(NSObject)); var UINavigationControllerDelegateImpl = (function (_super) { __extends(UINavigationControllerDelegateImpl, _super); function UINavigationControllerDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } UINavigationControllerDelegateImpl.initWithOwner = function (owner) { var delegate = UINavigationControllerDelegateImpl.new(); delegate._owner = owner; return delegate; }; UINavigationControllerDelegateImpl.prototype.navigationControllerWillShowViewControllerAnimated = function (navigationController, viewController, animated) { var _a, _b, _c; if (Trace.isEnabled()) { Trace.write("TabView.moreNavigationController.WILL_show(" + navigationController + ", " + viewController + ", " + animated + ");", Trace.categories.Debug); } var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner) { var backToMoreWillBeVisible = (_c = (_b = navigationController.tabBarController) === null || _b === void 0 ? void 0 : _b.viewControllers) === null || _c === void 0 ? void 0 : _c.containsObject(viewController); owner._handleTwoNavigationBars(backToMoreWillBeVisible); } }; UINavigationControllerDelegateImpl.prototype.navigationControllerDidShowViewControllerAnimated = function (navigationController, viewController, animated) { var _a; if (Trace.isEnabled()) { Trace.write("TabView.moreNavigationController.DID_show(" + navigationController + ", " + viewController + ", " + animated + ");", Trace.categories.Debug); } navigationController.navigationBar.topItem.rightBarButtonItem = null; var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (owner) { owner._onViewControllerShown(navigationController.tabBarController, viewController); } }; UINavigationControllerDelegateImpl.ObjCProtocols = [UINavigationControllerDelegate]; return UINavigationControllerDelegateImpl; }(NSObject)); function updateTitleAndIconPositions(tabItem, tabBarItem, controller) { if (!tabItem || !tabBarItem) { return; } // For iOS <11 icon is *always* above the text. // For iOS 11 icon is above the text *only* on phones in portrait mode. const orientation = controller.interfaceOrientation; const isPortrait = orientation !== 4 /* UIInterfaceOrientation.LandscapeLeft */ && orientation !== 3 /* UIInterfaceOrientation.LandscapeRight */; const isIconAboveTitle = (!__VISIONOS__ && SDK_VERSION < 11) || (Device.deviceType === 'Phone' && isPortrait); if (!tabItem.iconSource) { if (isIconAboveTitle) { tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: -20, }; } else { tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: 0 }; } } if (!tabItem.title) { if (isIconAboveTitle) { tabBarItem.imageInsets = new UIEdgeInsets({ top: 6, left: 0, bottom: -6, right: 0, }); } else { tabBarItem.imageInsets = new UIEdgeInsets({ top: 0, left: 0, bottom: 0, right: 0, }); } } } export class TabViewItem extends TabViewItemBase { setViewController(controller, nativeView) { this.__controller = controller; this.setNativeView(nativeView); } disposeNativeView() { this.__controller = undefined; this.setNativeView(undefined); } loadView(view) { const tabView = this.parent; if (tabView && tabView.items) { const index = tabView.items.indexOf(this); if (index === tabView.selectedIndex) { super.loadView(view); } } } _update() { const parent = this.parent; const controller = this.__controller; if (parent && controller) { const icon = parent._getIcon(this); const index = parent.items.indexOf(this); const title = getTransformedText(this.title, this.style.textTransform); const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, icon, index); updateTitleAndIconPositions(this, tabBarItem, controller); // There is no need to request title styles update here in newer versions as styling is handled by bar appearance instance if (!__VISIONOS__ && SDK_VERSION < 15) { // TODO: Repeating code. Make TabViewItemBase - ViewBase and move the colorProperty on tabViewItem. // Delete the repeating code. const states = getTitleAttributesForStates(parent); applyStatesToItem(tabBarItem, states); } controller.tabBarItem = tabBarItem; } } _updateTitleAndIconPositions() { if (!this.__controller || !this.__controller.tabBarItem) { return; } updateTitleAndIconPositions(this, this.__controller.tabBarItem, this.__controller); } [textTransformProperty.setNative](value) { this._update(); } } export class TabView extends TabViewBase { constructor() { super(); this._iconsCache = {}; this.viewController = this._ios = UITabBarControllerImpl.initWithOwner(new WeakRef(this)); } createNativeView() { // View controller can be disposed during view disposal, so make sure to create a new one if not defined if (!this._ios) { this.viewController = this._ios = UITabBarControllerImpl.initWithOwner(new WeakRef(this)); } return this._ios.view; } initNativeView() { super.initNativeView(); this._delegate = UITabBarControllerDelegateImpl.initWithOwner(new WeakRef(this)); this._moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.initWithOwner(new WeakRef(this)); } disposeNativeView() { this._delegate = null; this._moreNavigationControllerDelegate = null; this.viewController = null; this._ios = null; super.disposeNativeView(); } onLoaded() { super.onLoaded(); const selectedIndex = this.selectedIndex; const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].view; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } if (this._ios) { this._ios.delegate = this._delegate; } // Re-apply bottom accessory if set if (this.iosBottomAccessory) { this._applyBottomAccessory(this.iosBottomAccessory, false); } } onUnloaded() { if (this._ios) { this._ios.delegate = null; if (this._ios.moreNavigationController) { this._ios.moreNavigationController.delegate = null; } } // Avoid retaining custom view when unloading this._applyBottomAccessory(null, false); super.onUnloaded(); } // @ts-ignore get ios() { return this._ios; } layoutNativeView(left, top, right, bottom) { // } _setNativeViewFrame(nativeView, frame) { // } onSelectedIndexChanged(oldIndex, newIndex) { const items = this.items; if (!items) { return; } const oldItem = items[oldIndex]; if (oldItem) { oldItem.unloadView(oldItem.view); } const newItem = items[newIndex]; if (newItem && this.isLoaded) { const selectedView = items[newIndex].view; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } newItem.loadView(newItem.view); } super.onSelectedIndexChanged(oldIndex, newIndex); } onMeasure(widthMeasureSpec, heightMeasureSpec) { const width = layout.getMeasureSpecSize(widthMeasureSpec); const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); const height = layout.getMeasureSpecSize(heightMeasureSpec); const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); const widthAndState = View.resolveSizeAndState(width, width, widthMode, 0); const heightAndState = View.resolveSizeAndState(height, height, heightMode, 0); this.setMeasuredDimension(widthAndState, heightAndState); } _onViewControllerShown(tabBarController, viewController) { // This method could be called with the moreNavigationController or its list controller, so we have to check. if (Trace.isEnabled()) { Trace.write('TabView._onViewControllerShown(' + viewController + ');', Trace.categories.Debug); } if (tabBarController?.viewControllers && tabBarController.viewControllers.containsObject(viewController)) { this.selectedIndex = tabBarController.viewControllers.indexOfObject(viewController); } else { if (Trace.isEnabled()) { Trace.write('TabView._onViewControllerShown: viewController is not one of our viewControllers', Trace.categories.Debug); } } } _handleTwoNavigationBars(backToMoreWillBeVisible) { if (Trace.isEnabled()) { Trace.write(`TabView._handleTwoNavigationBars(backToMoreWillBeVisible: ${backToMoreWillBeVisible})`, Trace.categories.Debug); } // The "< Back" and "< More" navigation bars should not be visible simultaneously. let page = this.page || this._selectedView?.page; if (!page && this._selectedView instanceof Frame) { page = this._selectedView.currentPage; } if (!page || !page.frame) { return; } const actionBarVisible = page.frame._getNavBarVisible(page); if (backToMoreWillBeVisible && actionBarVisible) { if (page.frame.ios) { page.frame.ios._disableNavBarAnimation = true; page.actionBarHidden = true; page.frame.ios._disableNavBarAnimation = false; } else { page.actionBarHidden = true; } this._actionBarHiddenByTabView = true; if (Trace.isEnabled()) { Trace.write(`TabView hid action bar`, Trace.categories.Debug); } return; } if (!backToMoreWillBeVisible && this._actionBarHiddenByTabView) { if (page.frame.ios) { page.frame.ios._disableNavBarAnimation = true; page.actionBarHidden = false; page.frame.ios._disableNavBarAnimation = false; } else { page.actionBarHidden = false; } this._actionBarHiddenByTabView = undefined; if (Trace.isEnabled()) { Trace.write(`TabView restored action bar`, Trace.categories.Debug); } return; } } getViewController(item) { let newController = item.view ? item.view.viewController : null; if (newController) { item.setViewController(newController, newController.view); return newController; } if (item.view.ios instanceof UIViewController) { newController = item.view.ios; item.setViewController(newController, newController.view); } else if (item.view.ios && item.view.ios.controller instanceof UIViewController) { newController = item.view.ios.controller; item.setViewController(newController, newController.view); } else { newController = IOSHelper.UILayoutViewController.initWithOwner(new WeakRef(item.view)); newController.view.addSubview(item.view.nativeViewProtected); item.view.viewController = newController; item.setViewController(newController, item.view.nativeViewProtected); } return newController; } setViewControllers(items) { const length = items ? items.length : 0; if (length === 0) { this._ios.viewControllers = null; return; } const controllers = NSMutableArray.alloc().initWithCapacity(length); const states = getTitleAttributesForStates(this); items.forEach((item, i) => { const controller = this.getViewController(item); const icon = this._getIcon(item); const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(item.title || '', icon, i); updateTitleAndIconPositions(item, tabBarItem, controller); if (!__VISIONOS__ && SDK_VERSION < 15) { applyStatesToItem(tabBarItem, states); } controller.tabBarItem = tabBarItem; controllers.addObject(controller); item.canBeLoaded = true; }); if (SDK_VERSION >= 15) { this.updateBarItemAppearance(this._ios.tabBar, states); } this._ios.viewControllers = controllers; this._ios.customizableViewControllers = null; // When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here. this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate; } _getIconRenderingMode() { switch (this.iosIconRenderingMode) { case 'alwaysOriginal': return 1 /* UIImageRenderingMode.AlwaysOriginal */; case 'alwaysTemplate': return 2 /* UIImageRenderingMode.AlwaysTemplate */; case 'automatic': default: return 0 /* UIImageRenderingMode.Automatic */; } } _getIcon(item) { if (!item || !item.iconSource) { return null; } let image = this._iconsCache[item.iconSource]; if (!image) { let is; if (isSystemURI(item.iconSource)) { is = ImageSource.fromSystemImageSync(item.iconSource.slice(SYSTEM_PREFIX.length)); } else if (isFontIconURI(item.iconSource)) { // Allow specifying a separate font family for the icon via style.iconFontFamily. // If provided, construct a Font from the family and (optionally) size from fontInternal. let iconFont = item.style.fontInternal; const iconFontFamily = item.iconFontFamily || item.style.iconFontFamily; if (iconFontFamily) { // Preserve size/style from existing fontInternal if present. const baseFont = item.style.fontInternal || Font.default; iconFont = baseFont.withFontFamily(iconFontFamily); } is = ImageSource.fromFontIconCodeSync(item.iconSource.slice(FONT_PREFIX.length), iconFont, item.style.color); } else { is = ImageSource.fromFileOrResourceSync(item.iconSource); } if (is && is.ios) { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); this._iconsCache[item.iconSource] = originalRenderedImage; image = originalRenderedImage; } else { traceMissingIcon(item.iconSource); } } return image; } _updateIOSTabBarColorsAndFonts() { if (!this.items) { return; } const tabBar = this.ios.tabBar; const states = getTitleAttributesForStates(this); if (SDK_VERSION >= 15) { this.updateBarItemAppearance(tabBar, states); } else { for (let i = 0; i < tabBar.items.count; i++) { applyStatesToItem(tabBar.items[i], states); } } } updateBarItemAppearance(tabBar, states) { const appearance = this._getAppearance(tabBar); const itemAppearances = ['stackedLayoutAppearance', 'inlineLayoutAppearance', 'compactInlineLayoutAppearance']; for (const itemAppearance of itemAppearances) { appearance[itemAppearance].normal.titleTextAttributes = states.normalState; appearance[itemAppearance].selected.titleTextAttributes = states.selectedState; } this._updateAppearance(tabBar, appearance); } _getAppearance(tabBar) { if (tabBar.standardAppearance == null) { const appearance = UITabBarAppearance.new(); appearance.stackedLayoutAppearance = appearance.inlineLayoutAppearance = appearance.compactInlineLayoutAppearance = UITabBarItemAppearance.new(); return appearance; } return tabBar.standardAppearance; } _updateAppearance(tabBar, appearance) { tabBar.standardAppearance = appearance; if (SDK_VERSION >= 15) { tabBar.scrollEdgeAppearance = appearance; } } [selectedIndexProperty.setNative](value) { if (Trace.isEnabled()) { Trace.write('TabView._onSelectedIndexPropertyChangedSetNativeValue(' + value + ')', Trace.categories.Debug); } if (value > -1) { this._ios.selectedIndex = value; } } [itemsProperty.getDefault]() { return null; } [itemsProperty.setNative](value) { this.setViewControllers(value); selectedIndexProperty.coerce(this); } [tabTextFontSizeProperty.getDefault]() { return null; } [tabTextFontSizeProperty.setNative](value) { this._updateIOSTabBarColorsAndFonts(); } [tabTextColorProperty.getDefault]() { return null; } [tabTextColorProperty.setNative](value) { this._updateIOSTabBarColorsAndFonts(); } [tabBackgroundColorProperty.getDefault]() { return this._ios.tabBar.barTintColor; } [tabBackgroundColorProperty.setNative](value) { if (SDK_VERSION >= 13) { const appearance = this._getAppearance(this._ios.tabBar); appearance.configureWithDefaultBackground(); appearance.backgroundColor = value instanceof Color ? value.ios : value; this._updateAppearance(this._ios.tabBar, appearance); } else { this._ios.tabBar.barTintColor = value instanceof Color ? value.ios : value; } } [selectedTabTextColorProperty.getDefault]() { return this._ios.tabBar.tintColor; } [selectedTabTextColorProperty.setNative](value) { this._ios.tabBar.tintColor = value instanceof Color ? value.ios : value; this._updateIOSTabBarColorsAndFonts(); } // TODO: Move this to TabViewItem [fontInternalProperty.getDefault]() { return null; } [fontInternalProperty.setNative](value) { this._updateIOSTabBarColorsAndFonts(); } // TODO: Move this to TabViewItem [iosIconRenderingModeProperty.getDefault]() { return 'automatic'; } [iosIconRenderingModeProperty.setNative](value) { this._iconsCache = {}; const items = this.items; if (items && items.length) { for (let i = 0, length = items.length; i < length; i++) { const item = items[i]; if (item.iconSource) { item._update(); } } } } // iOS 26+: bottom accessory support [iosBottomAccessoryProperty.getDefault]() { return null; } [iosBottomAccessoryProperty.setNative](value) { this._applyBottomAccessory(value, false); } // iOS 26+: tab bar minimize behavior [iosTabBarMinimizeBehaviorProperty.getDefault]() { return 'automatic'; } [iosTabBarMinimizeBehaviorProperty.setNative](value) { if (SDK_VERSION < 26) { return; } let mapped; switch (value) { case 'never': mapped = 1 /* UITabBarMinimizeBehavior.Never */; break; case 'onScrollDown': mapped = 2 /* UITabBarMinimizeBehavior.OnScrollDown */; break; case 'onScrollUp': mapped = 3 /* UITabBarMinimizeBehavior.OnScrollUp */; break; case 'automatic': default: mapped = 0 /* UITabBarMinimizeBehavior.Automatic */; } this._ios.tabBarMinimizeBehavior = mapped; } _applyBottomAccessory(value, animated) { // Guard for platform availability if (SDK_VERSION < 26) { return; } const setAccessory = (accessory) => { try { this._ios.setBottomAccessoryAnimated(accessory, animated); } catch (err) { // Fallback to property if needed this._ios.bottomAccessory = accessory; } }; // Clear previous if (!value) { // Clear on controller setAccessory(null); // Tear down previously managed NS view if (this._bottomAccessoryNsView) { // Do not remove from a parent; we didn't add it to the NS view tree. try { this._bottomAccessoryNsView._tearDownUI(true); } catch (_) { } this._bottomAccessoryNsView = null; } return; } // Ensure the NativeScript view has a native view const nsView = value; if (!nsView.nativeViewProtected) { // mirror dialogs approach to setup UI for a detached view nsView._setupUI({}); } // Just mark it loaded, if not already, so measurement & styling are applied. if (!nsView.isLoaded) { // In detached scenarios we simply callLoaded after setup. nsView.callLoaded(); } const contentView = nsView.nativeViewProtected; if (!contentView) { return; } // Use frame-based sizing; keep autoresizing mask-based behavior enabled (no Auto Layout constraints added here). contentView.translatesAutoresizingMaskIntoConstraints = true; // Measure desired height with the tab bar width let tabBarWidth = this._ios?.tabBar?.frame?.size?.width || Screen.mainScreen.screen.bounds.size.width; // Account for safe area insets so accessory doesn't extend visually past rounded corners if (this._ios?.tabBar?.safeAreaInsets) { const insets = this._ios.tabBar.safeAreaInsets; // Reduce usable width by left+right safe area (typically 0, but defensive) const horizontalInsets = insets.left + insets.right; if (horizontalInsets > 0 && horizontalInsets < tabBarWidth) { tabBarWidth -= horizontalInsets; } } const tabBarWidthPx = layout.toDevicePixels(tabBarWidth); // Prefer flooring to avoid overshooting container by +1px due to FP rounding const tabBarWidthPxRounded = Math.floor(tabBarWidthPx); let measuredHeight = 0; // Measure using device-pixel width; flooring prevents +1px expansion const widthSpec = layout.makeMeasureSpec(tabBarWidthPxRounded, layout.EXACTLY); const heightSpec = layout.makeMeasureSpec(0, layout.UNSPECIFIED); nsView.measure(widthSpec, heightSpec); measuredHeight = layout.toDeviceIndependentPixels(nsView.getMeasuredHeight()); // Use a sensible minimum height (44pt button row) if measurement is tiny const minHeight = 44; const finalHeight = Math.max(minHeight, measuredHeight || 0); // Rely on container height constraint (below) and frame-based layout inside container. const container = NSTabAccessoryContainer.initWithOwner(new WeakRef(nsView)); container.translatesAutoresizingMaskIntoConstraints = true; container.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */; // Mask any subpixel spill just in case container.clipsToBounds = true; container.addSubview(contentView); // Constrain the container height (not the content) so UIKit has a concrete size. const containerHeight = container.heightAnchor.constraintEqualToConstant(finalHeight); containerHeight.priority = 999; NSLayoutConstraint.activateConstraints([containerHeight]); const accessory = UITabAccessory.alloc().initWithContentView(container); setAccessory(accessory); // Keep references for later teardown this._bottomAccessoryNsView = nsView; } } __decorate([ profile, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], TabView.prototype, "onLoaded", null); var NSTabAccessoryContainer = (function (_super) { __extends(NSTabAccessoryContainer, _super); function NSTabAccessoryContainer() { return _super !== null && _super.apply(this, arguments) || this; } NSTabAccessoryContainer.initWithOwner = function (owner) { var v = NSTabAccessoryContainer.new(); v._owner = owner; return v; }; NSTabAccessoryContainer.prototype.layoutSubviews = function () { var _a; _super.prototype.layoutSubviews.call(this); var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref(); if (!(owner === null || owner === void 0 ? void 0 : owner.nativeViewProtected)) return; owner.nativeViewProtected.frame = this.bounds; var w = this.bounds.size.width; var h = this.bounds.size.height; try { var wp = Math.floor(layout.toDevicePixels(w)); var hp = Math.floor(layout.toDevicePixels(h)); var containerPxWidth = Math.floor(layout.toDevicePixels(this.bounds.size.width)); if (wp > containerPxWidth) { wp = containerPxWidth; } var widthSpec = layout.makeMeasureSpec(wp, layout.EXACTLY); var heightSpec = layout.makeMeasureSpec(hp, layout.EXACTLY); owner.measure(widthSpec, heightSpec); owner.layout(0, 0, wp, hp); } catch (_) { } }; return NSTabAccessoryContainer; }(UIView)); function getTitleAttributesForStates(tabView) { const result = { normalState: NSMutableDictionary.new(), selectedState: NSMutableDictionary.new(), }; const titleFontSize = tabView.style.tabTextFontSize; let font = tabView.style.fontInternal || Font.default; if (titleFontSize != null) { font = font.withFontSize(titleFontSize); } const nativeFont = font.getUIFont(UIFont.systemFontOfSize(UIFont.labelFontSize)); result.normalState.setValueForKey(nativeFont, NSFontAttributeName); result.selectedState.setValueForKey(nativeFont, NSFontAttributeName); const titleColor = tabView.style.tabTextColor; if (titleColor instanceof Color) { result.normalState.setValueForKey(titleColor.ios, UITextAttributeTextColor); } const selectedTitleColor = tabView.style.selectedTabTextColor; if (selectedTitleColor instanceof Color) { result.selectedState.setValueForKey(selectedTitleColor.ios, UITextAttributeTextColor); } return result; } function applyStatesToItem(item, states) { item.setTitleTextAttributesForState(states.normalState, 0 /* UIControlState.Normal */); item.setTitleTextAttributesForState(states.selectedState, 4 /* UIControlState.Selected */); } //# sourceMappingURL=index.ios.js.map