@@ -2,7 +2,10 @@ import { IOSActionItemSettings, ActionItem as ActionItemDefinition } from '.';
22import { ActionItemBase , ActionBarBase , isVisible , flatProperty , iosIconRenderingModeProperty , traceMissingIcon } from './action-bar-common' ;
33import { View } from '../core/view' ;
44import { Color } from '../../color' ;
5- import { colorProperty , backgroundColorProperty , backgroundInternalProperty } from '../styling/style-properties' ;
5+ import { ios as iosBackground } from '../styling/background' ;
6+ import { LinearGradient } from '../styling/linear-gradient' ;
7+ import { colorProperty , backgroundInternalProperty , backgroundColorProperty , backgroundImageProperty } from '../styling/style-properties' ;
8+ import { ios as iosViewUtils } from '../utils' ;
69import { ImageSource } from '../../image-source' ;
710import { layout , iOSNativeHelper , isFontIconURI } from '../../utils' ;
811import { accessibilityHintProperty , accessibilityLabelProperty , accessibilityLanguageProperty , accessibilityValueProperty } from '../../accessibility/accessibility-properties' ;
@@ -12,6 +15,10 @@ export * from './action-bar-common';
1215const majorVersion = iOSNativeHelper . MajorVersion ;
1316const UNSPECIFIED = layout . makeMeasureSpec ( 0 , layout . UNSPECIFIED ) ;
1417
18+ interface NSUINavigationBar extends UINavigationBar {
19+ gradientLayer ?: CAGradientLayer ;
20+ }
21+
1522function loadActionIcon ( item : ActionItemDefinition ) : any /* UIImage */ {
1623 let is = null ;
1724 let img = null ;
@@ -140,6 +147,15 @@ export class ActionBar extends ActionBarBase {
140147 return this . ios ;
141148 }
142149
150+ public disposeNativeView ( ) {
151+ const navBar = this . navBar as NSUINavigationBar ;
152+ if ( navBar ?. gradientLayer ) {
153+ navBar . gradientLayer = null ;
154+ }
155+
156+ super . disposeNativeView ( ) ;
157+ }
158+
143159 public _addChildFromBuilder ( name : string , value : any ) {
144160 if ( value instanceof NavigationButton ) {
145161 this . navigationButton = value ;
@@ -151,12 +167,12 @@ export class ActionBar extends ActionBarBase {
151167 }
152168
153169 public get _getActualSize ( ) : { width : number ; height : number } {
154- const navBar = this . ios ;
155- if ( ! navBar ) {
170+ const nativeView = this . ios ;
171+ if ( ! nativeView ) {
156172 return { width : 0 , height : 0 } ;
157173 }
158174
159- const frame = navBar . frame ;
175+ const frame = nativeView . frame ;
160176 const size = frame . size ;
161177 const width = layout . toDevicePixels ( size . width ) ;
162178 const height = layout . toDevicePixels ( size . height ) ;
@@ -273,7 +289,7 @@ export class ActionBar extends ActionBarBase {
273289 this . populateMenuItems ( navigationItem ) ;
274290
275291 // update colors explicitly - they may have to be cleared form a previous page
276- this . updateColors ( navigationBar ) ;
292+ this . updateFills ( navigationBar ) ;
277293
278294 // the 'flat' property may have changed in between pages
279295 this . updateFlatness ( navigationBar ) ;
@@ -345,12 +361,14 @@ export class ActionBar extends ActionBarBase {
345361 return barButtonItem ;
346362 }
347363
348- private updateColors ( navBar : UINavigationBar ) {
364+ private updateFills ( navBar : UINavigationBar ) {
349365 const color = this . color ;
350366 this . setColor ( navBar , color ) ;
351367
352- const bgColor = < Color > this . backgroundColor ;
353- this . setBackgroundColor ( navBar , bgColor ) ;
368+ this . _setBackgroundColor ( navBar , this . style . backgroundColor ) ;
369+ this . _createBackgroundUIImage ( navBar , this . style . backgroundImage , ( image : UIImage ) => {
370+ this . _setBackgroundImage ( navBar , image ) ;
371+ } ) ;
354372 }
355373
356374 private setColor ( navBar : UINavigationBar , color ?: Color ) {
@@ -373,20 +391,112 @@ export class ActionBar extends ActionBarBase {
373391 }
374392 }
375393
376- private setBackgroundColor ( navBar : UINavigationBar , color ?: UIColor | Color ) {
394+ private _setBackgroundColor ( navBar : UINavigationBar , color ?: UIColor | Color ) {
395+ if ( ! navBar ) {
396+ return ;
397+ }
398+
399+ const nativeColor = color instanceof Color ? color . ios : color ;
400+ if ( __VISIONOS__ || majorVersion >= 15 ) {
401+ const appearance = this . _getAppearance ( navBar ) ;
402+ // appearance.configureWithOpaqueBackground();
403+ appearance . backgroundColor = nativeColor ;
404+ this . _updateAppearance ( navBar , appearance ) ;
405+ } else {
406+ // legacy styling
407+ navBar . barTintColor = nativeColor ;
408+ }
409+ }
410+
411+ private _getBackgroundColor ( navBar : UINavigationBar ) {
412+ if ( ! navBar ) {
413+ return null ;
414+ }
415+
416+ let color : UIColor ;
417+
418+ if ( __VISIONOS__ || majorVersion >= 15 ) {
419+ const appearance = this . _getAppearance ( navBar ) ;
420+ color = appearance . backgroundColor ;
421+ } else {
422+ // legacy styling
423+ color = navBar . barTintColor ;
424+ }
425+
426+ return color ;
427+ }
428+
429+ private _setBackgroundImage ( navBar : UINavigationBar , image : UIImage ) {
377430 if ( ! navBar ) {
378431 return ;
379432 }
380433
381- const color_ = color instanceof Color ? color . ios : color ;
382434 if ( __VISIONOS__ || majorVersion >= 15 ) {
383435 const appearance = this . _getAppearance ( navBar ) ;
384436 // appearance.configureWithOpaqueBackground();
385- appearance . backgroundColor = color_ ;
437+ appearance . backgroundImage = image ;
386438 this . _updateAppearance ( navBar , appearance ) ;
387439 } else {
388440 // legacy styling
389- navBar . barTintColor = color_ ;
441+
442+ // Set a blank image in case image is null and flatness is enabled
443+ if ( this . flat && ! image ) {
444+ image = UIImage . new ( ) ;
445+ }
446+
447+ navBar . setBackgroundImageForBarMetrics ( image , UIBarMetrics . Default ) ;
448+ }
449+ }
450+
451+ private _getBackgroundImage ( navBar : UINavigationBar ) {
452+ if ( ! navBar ) {
453+ return null ;
454+ }
455+
456+ let image : UIImage ;
457+
458+ if ( __VISIONOS__ || majorVersion >= 15 ) {
459+ const appearance = this . _getAppearance ( navBar ) ;
460+ image = appearance . backgroundImage ;
461+ } else {
462+ // legacy styling
463+ image = navBar . backgroundImageForBarMetrics ( UIBarMetrics . Default ) ;
464+ }
465+
466+ return image ;
467+ }
468+
469+ private _createBackgroundUIImage ( navBar : NSUINavigationBar , value : string | LinearGradient , callback : ( image : UIImage ) => void ) : void {
470+ if ( ! navBar ) {
471+ return ;
472+ }
473+
474+ if ( value ) {
475+ if ( value instanceof LinearGradient ) {
476+ if ( ! navBar . gradientLayer ) {
477+ navBar . gradientLayer = CAGradientLayer . new ( ) ;
478+ }
479+
480+ iosViewUtils . drawGradient ( navBar , navBar . gradientLayer , value ) ;
481+
482+ const renderer = UIGraphicsImageRenderer . alloc ( ) . initWithSize ( navBar . bounds . size ) ;
483+ const img = renderer . imageWithActions ( ( context : UIGraphicsRendererContext ) => {
484+ navBar . gradientLayer . renderInContext ( context . CGContext ) ;
485+ } ) ;
486+
487+ callback ( img ) ;
488+ // Return here to avoid unnecessary cleanups
489+ return ;
490+ }
491+
492+ // Background image
493+ iosBackground . createUIImageFromURI ( this , value , false , callback ) ;
494+ } else {
495+ callback ( null ) ;
496+ }
497+
498+ if ( navBar . gradientLayer ) {
499+ navBar . gradientLayer = null ;
390500 }
391501 }
392502
@@ -411,7 +521,10 @@ export class ActionBar extends ActionBarBase {
411521 appearance . shadowColor = UIColor . clearColor ;
412522 this . _updateAppearance ( navBar , appearance ) ;
413523 } else {
414- navBar . setBackgroundImageForBarMetrics ( UIImage . new ( ) , UIBarMetrics . Default ) ;
524+ // Do not apply blank image if background image is already set
525+ if ( ! this . backgroundImage ) {
526+ navBar . setBackgroundImageForBarMetrics ( UIImage . new ( ) , UIBarMetrics . Default ) ;
527+ }
415528 navBar . shadowImage = UIImage . new ( ) ;
416529 navBar . translucent = false ;
417530 }
@@ -424,7 +537,11 @@ export class ActionBar extends ActionBarBase {
424537 this . _updateAppearance ( navBar , appearance ) ;
425538 }
426539 } else {
427- navBar . setBackgroundImageForBarMetrics ( null , null ) ;
540+ // Do not apply blank image if background image is already set
541+ if ( ! this . backgroundImage ) {
542+ // Bar metrics is needed even when unsetting the image
543+ navBar . setBackgroundImageForBarMetrics ( null , UIBarMetrics . Default ) ;
544+ }
428545 navBar . shadowImage = null ;
429546 navBar . translucent = true ;
430547 }
@@ -507,13 +624,21 @@ export class ActionBar extends ActionBarBase {
507624 }
508625
509626 [ backgroundColorProperty . getDefault ] ( ) : UIColor {
510- // This getter is never called.
511- // CssAnimationProperty use default value form their constructor.
512- return null ;
627+ return this . _getBackgroundColor ( this . navBar ) ;
513628 }
514629 [ backgroundColorProperty . setNative ] ( color : UIColor | Color ) {
630+ this . _setBackgroundColor ( this . navBar , color ) ;
631+ }
632+
633+ [ backgroundImageProperty . getDefault ] ( ) : UIImage {
634+ return this . _getBackgroundImage ( this . navBar ) ;
635+ }
636+ [ backgroundImageProperty . setNative ] ( value : string | LinearGradient ) {
515637 const navBar = this . navBar ;
516- this . setBackgroundColor ( navBar , color ) ;
638+
639+ this . _createBackgroundUIImage ( navBar , value , ( image : UIImage ) => {
640+ this . _setBackgroundImage ( navBar , image ) ;
641+ } ) ;
517642 }
518643
519644 [ backgroundInternalProperty . getDefault ] ( ) : UIColor {
@@ -524,7 +649,6 @@ export class ActionBar extends ActionBarBase {
524649 }
525650
526651 [ flatProperty . setNative ] ( value : boolean ) {
527- // tslint:disable-line
528652 const navBar = this . navBar ;
529653 if ( navBar ) {
530654 this . updateFlatness ( navBar ) ;
0 commit comments