import { TabContentItem } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-content-item' ; import { TabNavigationBase , getIconSpecSize , itemsProperty , selectedIndexProperty , tabStripProperty } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-navigation-base' ; import { TabStrip } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-strip' ; import { TabStripItem } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-strip-item' ; import { Application , CSSType , Color , CoreTypes , Font , Frame , ImageSource , Utils , View } from '@nativescript/core' ; import { getTransformedText } from '@nativescript/core/ui/text-base' ; export { TabContentItem , TabStrip , TabStripItem } ; const PRIMARY_COLOR = 'colorPrimary' ; const DEFAULT_ELEVATION = 8 ; const TABID = '_tabId' ; const INDEX = '_index' ; const ownerSymbol = Symbol ( '_owner' ) ; let TabFragment ; let BottomNavigationBar ; let AttachStateChangeListener ; let appResources ; class IconInfo { drawable : android . graphics . drawable . BitmapDrawable ; height : number ; } function makeFragmentName ( viewId , id ) { return 'android:bottomnavigation:' + viewId + ':' + id ; } function getTabById ( id ) { const ref = tabs . find ( ( ref ) => { const tab = ref . get ( ) ; return tab && tab . _domId === id ; } ) ; return ref && ref . get ( ) ; } function initializeNativeClasses ( ) { if ( BottomNavigationBar ) { return ; } @ NativeClass class TabFragmentImplementation extends org . nativescript . widgets . FragmentBase { private owner : BottomNavigation ; private index : number ; private backgroundBitmap : android . graphics . Bitmap = null ; constructor ( ) { super ( ) ; return global . __native ( this ) ; } static newInstance ( tabId , index ) { const args = new android . os . Bundle ( ) ; args . putInt ( TABID , tabId ) ; args . putInt ( INDEX , index ) ; const fragment = new TabFragmentImplementation ( ) ; fragment . setArguments ( args ) ; return fragment ; } public onCreate ( savedInstanceState ) { super . onCreate ( savedInstanceState ) ; const args = this . getArguments ( ) ; this . owner = getTabById ( args . getInt ( TABID ) ) ; this . index = args . getInt ( INDEX ) ; if ( ! this . owner ) { throw new Error ( 'Cannot find BottomNavigation' ) ; } } public onCreateView ( inflater , container , savedInstanceState ) { const tabItem = this . owner . items [ this . index ] ; return tabItem . nativeViewProtected ; } public onDestroyView ( ) { const hasRemovingParent = this . getRemovingParentFragment ( ) ; if ( hasRemovingParent && this . owner . selectedIndex === this . index ) { const bitmapDrawable = new android . graphics . drawable . BitmapDrawable ( appResources , this . backgroundBitmap ) ; this . owner . _originalBackground = this . owner . backgroundColor || new Color ( 'White' ) ; this . owner . nativeViewProtected . setBackgroundDrawable ( bitmapDrawable ) ; this . backgroundBitmap = null ; const thisView = this . getView ( ) ; if ( thisView ) { const thisViewParent = thisView . getParent ( ) ; if ( thisViewParent && thisViewParent instanceof android . view . ViewGroup ) { thisViewParent . removeView ( thisView ) ; } } } super . onDestroyView ( ) ; } public onPause ( ) { const hasRemovingParent = this . getRemovingParentFragment ( ) ; if ( hasRemovingParent && this . owner . selectedIndex === this . index ) { this . backgroundBitmap = this . loadBitmapFromView ( this . owner . nativeViewProtected ) ; } super . onPause ( ) ; } private loadBitmapFromView ( view ) { view . setDrawingCacheEnabled ( true ) ; const bitmap = android . graphics . Bitmap . createBitmap ( view . getDrawingCache ( ) ) ; view . setDrawingCacheEnabled ( false ) ; return bitmap ; } } @ NativeClass class BottomNavigationBarImplementation extends com . nativescript . material . core . BottomNavigationBar { constructor ( context , public owner ) { super ( context ) ; return global . __native ( this ) ; } public onSelectedPositionChange ( position , prevPosition ) { const owner = this . owner ; if ( ! owner ) { return ; } owner . changeTab ( position ) ; const tabStripItems = owner . tabStrip && owner . tabStrip . items ; if ( position >= 0 && tabStripItems && tabStripItems [ position ] ) { tabStripItems [ position ] . _emit ( TabStripItem . selectEvent ) ; } if ( prevPosition >= 0 && tabStripItems && tabStripItems [ prevPosition ] ) { tabStripItems [ prevPosition ] . _emit ( TabStripItem . unselectEvent ) ; } owner . _setItemsColors ( owner . tabStrip . items ) ; } public onTap ( position ) { const owner = this . owner ; if ( ! owner ) { return false ; } const tabStrip = owner . tabStrip ; const tabStripItems = tabStrip && tabStrip . items ; if ( position >= 0 && tabStripItems [ position ] ) { tabStripItems [ position ] . _emit ( TabStripItem . tapEvent ) ; tabStrip . notify ( { eventName : TabStrip . itemTapEvent , object : tabStrip , index : position } ) ; } if ( ! owner . items [ position ] ) { return false ; } return true ; } } @ NativeClass @ Interfaces ( [ android . view . View . OnAttachStateChangeListener ] ) class AttachListener extends java . lang . Object implements android . view . View . OnAttachStateChangeListener { constructor ( ) { super ( ) ; return global . __native ( this ) ; } onViewAttachedToWindow ( view ) { const owner = view [ ownerSymbol ] ; if ( owner ) { owner . _onAttachedToWindow ( ) ; } } onViewDetachedFromWindow ( view ) { const owner = view [ ownerSymbol ] ; if ( owner ) { owner . _onDetachedFromWindow ( ) ; } } } TabFragment = TabFragmentImplementation ; BottomNavigationBar = BottomNavigationBarImplementation ; AttachStateChangeListener = new AttachListener ( ) ; appResources = Application . android . context . getResources ( ) ; } function setElevation ( bottomNavigationBar ) { const compat = androidx . core . view . ViewCompat ; if ( compat . setElevation ) { const val = DEFAULT_ELEVATION * Utils . layout . getDisplayDensity ( ) ; compat . setElevation ( bottomNavigationBar , val ) ; } } export const tabs = new Array < WeakRef < BottomNavigation > > ( ) ; function iterateIndexRange ( index , eps , lastIndex , callback ) { const rangeStart = Math . max ( 0 , index - eps ) ; const rangeEnd = Math . min ( index + eps , lastIndex ) ; for ( let i = rangeStart ; i <= rangeEnd ; i ++ ) { callback ( i ) ; } } @ CSSType ( 'BottomNavigation' ) export class BottomNavigation extends TabNavigationBase { private _contentView : org . nativescript . widgets . ContentLayout ; private _contentViewId = - 1 ; private _bottomNavigationBar : com . nativescript . material . core . BottomNavigationBar ; private _currentFragment : androidx . fragment . app . Fragment ; private _currentTransaction : androidx . fragment . app . FragmentTransaction ; private _attachedToWindow = false ; public _originalBackground : any ; private _textTransform : CoreTypes . TextTransformType = 'none' ; private _selectedItemColor : Color ; private _unSelectedItemColor : Color ; fragments : androidx . fragment . app . Fragment [ ] = [ ] ; constructor ( ) { super ( ) ; tabs . push ( new WeakRef ( this ) ) ; } get _hasFragments ( ) : boolean { return true ; } public onItemsChanged ( oldItems , newItems ) { super . onItemsChanged ( oldItems , newItems ) ; if ( oldItems ) { oldItems . forEach ( ( item , i , arr ) => { ( item as any ) . index = 0 ; ( item as any ) . tabItemSpec = null ; item . setNativeView ( null ) ; } ) ; } } public createNativeView ( ) { initializeNativeClasses ( ) ; const context = this . _context ; const nativeView = new org . nativescript . widgets . GridLayout ( context ) ; nativeView . addRow ( new org . nativescript . widgets . ItemSpec ( 1 , org . nativescript . widgets . GridUnitType . star ) ) ; nativeView . addRow ( new org . nativescript . widgets . ItemSpec ( 1 , org . nativescript . widgets . GridUnitType . auto ) ) ; const contentView = new org . nativescript . widgets . ContentLayout ( this . _context ) ; const contentViewLayoutParams = new org . nativescript . widgets . CommonLayoutParams ( ) ; contentViewLayoutParams . row = 0 ; contentView . setLayoutParams ( contentViewLayoutParams ) ; nativeView . addView ( contentView ) ; ( nativeView as any ) . contentView = contentView ; const bottomNavigationBar = new BottomNavigationBar ( context , this ) ; const bottomNavigationBarLayoutParams = new org . nativescript . widgets . CommonLayoutParams ( ) ; bottomNavigationBarLayoutParams . row = 1 ; bottomNavigationBar . setLayoutParams ( bottomNavigationBarLayoutParams ) ; nativeView . addView ( bottomNavigationBar ) ; ( nativeView as any ) . bottomNavigationBar = bottomNavigationBar ; setElevation ( bottomNavigationBar ) ; const primaryColor = Utils . ad . resources . getPaletteColor ( PRIMARY_COLOR , context ) ; if ( primaryColor ) { bottomNavigationBar . setBackgroundColor ( primaryColor ) ; } return nativeView ; } public initNativeView ( ) { super . initNativeView ( ) ; if ( this . _contentViewId < 0 ) { this . _contentViewId = android . view . View . generateViewId ( ) ; } const nativeView = this . nativeViewProtected ; nativeView . addOnAttachStateChangeListener ( AttachStateChangeListener ) ; nativeView [ ownerSymbol ] = this ; this . _contentView = nativeView . contentView ; this . _contentView . setId ( this . _contentViewId ) ; this . _bottomNavigationBar = nativeView . bottomNavigationBar ; ( this . _bottomNavigationBar as any ) . owner = this ; if ( this . tabStrip ) { this . tabStrip . setNativeView ( this . _bottomNavigationBar ) ; } } public _loadUnloadTabItems ( newIndex ) { const items = this . items ; const lastIndex = this . items . length - 1 ; const offsideItems = 0 ; const toUnload = [ ] ; const toLoad = [ ] ; iterateIndexRange ( newIndex , offsideItems , lastIndex , ( i ) => toLoad . push ( i ) ) ; if ( this . unloadOnTabChange ) { items . forEach ( ( item , i ) => { const indexOfI = toLoad . indexOf ( i ) ; if ( indexOfI < 0 ) { toUnload . push ( i ) ; } } ) ; toUnload . forEach ( ( index ) => { const item = items [ index ] ; if ( items [ index ] ) { item . unloadView ( item . content ) ; } } ) ; } const newItem = items [ newIndex ] ; const selectedView = newItem && newItem . content ; if ( selectedView instanceof Frame ) { selectedView . _pushInFrameStackRecursive ( ) ; } toLoad . forEach ( ( index ) => { const item = items [ index ] ; if ( this . isLoaded && item ) { item . loadView ( item . content ) ; } } ) ; } public onLoaded ( ) { super . onLoaded ( ) ; if ( this . _originalBackground ) { this . backgroundColor = null ; this . backgroundColor = this . _originalBackground ; this . _originalBackground = null ; } if ( this . tabStrip ) { this . setTabStripItems ( this . tabStrip . items ) ; } else { this . _bottomNavigationBar . setVisibility ( android . view . View . GONE ) ; } if ( this . _attachedToWindow ) { this . changeTab ( this . selectedIndex ) ; } } _onAttachedToWindow ( ) { super . _onAttachedToWindow ( ) ; const activity = Application . android . foregroundActivity || Application . android . startActivity ; const lifecycle = activity ?. getLifecycle ?. ( ) . getCurrentState ( ) || androidx . lifecycle . Lifecycle . State . CREATED ; if ( ( this . _manager && this . _manager . isDestroyed ( ) ) || ( activity instanceof androidx . fragment . app . FragmentActivity && ! lifecycle . isAtLeast ( androidx . lifecycle . Lifecycle . State . CREATED ) ) ) { return ; } this . _attachedToWindow = true ; this . changeTab ( this . selectedIndex ) ; } _onDetachedFromWindow ( ) { super . _onDetachedFromWindow ( ) ; this . disposeTabFragments ( ) ; this . _attachedToWindow = false ; } public onUnloaded ( ) { super . onUnloaded ( ) ; if ( this . tabStrip ) { this . setTabStripItems ( null ) ; } this . items . forEach ( ( item , i ) => { item . unloadView ( item . content ) ; } ) ; } public disposeNativeView ( ) { this . _bottomNavigationBar . setItems ( null ) ; this . _bottomNavigationBar = null ; this . nativeViewProtected . removeOnAttachStateChangeListener ( AttachStateChangeListener ) ; this . nativeViewProtected [ ownerSymbol ] = null ; super . disposeNativeView ( ) ; this . disposeTabFragments ( ) ; } public _onRootViewReset ( ) { super . _onRootViewReset ( ) ; this . disposeTabFragments ( ) ; } private disposeTabFragments ( ) { const fragments = this . fragments ; for ( let i = 0 ; i < fragments . length ; i ++ ) { this . removeFragment ( fragments [ i ] ) ; } this . fragments = [ ] ; } private attachFragment ( fragment , id ? , name ? ) { const fragmentManager = this . _getFragmentManager ( ) ; if ( fragment ) { if ( fragment . isAdded ( ) || fragment . isRemoving ( ) ) { } else { const fragmentExitTransition = fragment . getExitTransition ( ) ; if ( fragmentExitTransition && fragmentExitTransition instanceof org . nativescript . widgets . CustomTransition ) { fragmentExitTransition . setResetOnTransitionEnd ( true ) ; } if ( fragmentManager ) { if ( ! fragmentManager . isDestroyed ( ) ) { try { if ( fragmentManager . isStateSaved ( ) ) { if ( id && name ) { fragmentManager . beginTransaction ( ) . add ( id , fragment , name ) . commitNowAllowingStateLoss ( ) ; } else { fragmentManager . beginTransaction ( ) . attach ( fragment ) . commitNowAllowingStateLoss ( ) ; } } else { if ( id && name ) { fragmentManager . beginTransaction ( ) . add ( id , fragment , name ) . commitNow ( ) ; } else { fragmentManager . beginTransaction ( ) . attach ( fragment ) . commitNow ( ) ; } } } catch ( e ) { } } } } } } public changeTab ( index ) { if ( index === - 1 || ! this . _attachedToWindow ) { return ; } const fragmentToDetach = this . _currentFragment ; if ( fragmentToDetach ) { if ( this . unloadOnTabChange ) { this . destroyItem ( ( fragmentToDetach as any ) . index , fragmentToDetach ) ; } else { this . hideFragment ( fragmentToDetach as any ) ; } } const fragment = this . instantiateItem ( this . _contentView , index ) ; this . setPrimaryItem ( index , fragment , true ) ; } private instantiateItem ( container , position ) { const name = makeFragmentName ( container . getId ( ) , position ) ; const fragmentManager = this . _getFragmentManager ( ) ; let fragment = fragmentManager . findFragmentByTag ( name ) ; if ( fragment != null ) { this . attachFragment ( fragment ) ; } else { fragment = TabFragment . newInstance ( this . _domId , position ) ; this . fragments . push ( fragment ) ; this . attachFragment ( fragment , container . getId ( ) , name ) ; } return fragment ; } private setPrimaryItem ( position , fragment , force = false ) { if ( fragment !== this . _currentFragment || force ) { if ( this . _currentFragment != null ) { this . _currentFragment . setMenuVisibility ( false ) ; this . _currentFragment . setUserVisibleHint ( false ) ; } if ( fragment != null ) { fragment . setMenuVisibility ( true ) ; fragment . setUserVisibleHint ( true ) ; if ( ! this . unloadOnTabChange ) { this . showFragment ( fragment ) ; } } this . _currentFragment = fragment ; this . selectedIndex = position ; const tabItems = this . items ; const tabItem = tabItems ? tabItems [ position ] : null ; if ( tabItem ) { tabItem . canBeLoaded = true ; this . _loadUnloadTabItems ( position ) ; } } } private destroyItem ( position , fragment ) { if ( fragment ) { this . removeFragment ( fragment ) ; const index = this . fragments . indexOf ( fragment ) ; if ( index !== - 1 ) { this . fragments . splice ( index , 1 ) ; } if ( this . _currentFragment === fragment ) { this . _currentFragment = null ; } } if ( this . items && this . items [ position ] ) { this . items [ position ] . canBeLoaded = false ; } } private hideFragment ( fragment , fragmentManager ? ) { if ( ! fragmentManager ) { fragmentManager = this . _getFragmentManager ( ) ; } if ( fragment ) { if ( ! fragment . isAdded ( ) || fragment . isRemoving ( ) ) { return ; } else { const fragmentExitTransition = fragment . getExitTransition ( ) ; if ( fragmentExitTransition && fragmentExitTransition instanceof org . nativescript . widgets . CustomTransition ) { fragmentExitTransition . setResetOnTransitionEnd ( true ) ; } if ( fragment && fragment . isAdded ( ) && ! fragment . isRemoving ( ) ) { const pfm = ( fragment as any ) . getParentFragmentManager ? ( fragment as any ) . getParentFragmentManager ( ) : null ; if ( pfm && ! pfm . isDestroyed ( ) ) { try { if ( pfm . isStateSaved ( ) ) { pfm . beginTransaction ( ) . hide ( fragment ) . commitNowAllowingStateLoss ( ) ; } else { pfm . beginTransaction ( ) . hide ( fragment ) . commitNow ( ) ; } } catch ( e ) { } } } } } } private showFragment ( fragment , fragmentManager ? ) { if ( ! fragmentManager ) { fragmentManager = this . _getFragmentManager ( ) ; } if ( fragment ) { if ( ! fragment . isAdded ( ) || fragment . isRemoving ( ) ) { return ; } else { const fragmentExitTransition = fragment . getExitTransition ( ) ; if ( fragmentExitTransition && fragmentExitTransition instanceof org . nativescript . widgets . CustomTransition ) { fragmentExitTransition . setResetOnTransitionEnd ( true ) ; } if ( fragment && fragment . isAdded ( ) && ! fragment . isRemoving ( ) ) { const pfm = ( fragment as any ) . getParentFragmentManager ? ( fragment as any ) . getParentFragmentManager ( ) : null ; if ( pfm && ! pfm . isDestroyed ( ) ) { try { if ( pfm . isStateSaved ( ) ) { pfm . beginTransaction ( ) . show ( fragment ) . commitNowAllowingStateLoss ( ) ; } else { pfm . beginTransaction ( ) . show ( fragment ) . commitNow ( ) ; } } catch ( e ) { } } } } } } private removeFragment ( fragment , fragmentManager ? ) { if ( ! fragmentManager ) { fragmentManager = this . _getFragmentManager ( ) ; } if ( fragment ) { if ( ! fragment . isAdded ( ) || fragment . isRemoving ( ) ) { return ; } else { const fragmentExitTransition = fragment . getExitTransition ( ) ; if ( fragmentExitTransition && fragmentExitTransition instanceof org . nativescript . widgets . CustomTransition ) { fragmentExitTransition . setResetOnTransitionEnd ( true ) ; } if ( fragment && fragment . isAdded ( ) && ! fragment . isRemoving ( ) ) { const pfm = ( fragment as any ) . getParentFragmentManager ? ( fragment as any ) . getParentFragmentManager ( ) : null ; if ( pfm && ! pfm . isDestroyed ( ) ) { try { if ( pfm . isStateSaved ( ) ) { pfm . beginTransaction ( ) . remove ( fragment ) . commitNowAllowingStateLoss ( ) ; } else { pfm . beginTransaction ( ) . remove ( fragment ) . commitNow ( ) ; } } catch ( e ) { } } } } } } private setTabStripItems ( items ) { if ( ! this . tabStrip || ! items ) { this . _bottomNavigationBar . setItems ( null ) ; return ; } const tabItems = new Array < com . nativescript . material . core . TabItemSpec > ( ) ; items . forEach ( ( tabStripItem , i , arr ) => { tabStripItem . _index = i ; if ( items [ i ] ) { const tabItemSpec = this . createTabItemSpec ( items [ i ] ) ; tabItems . push ( tabItemSpec ) ; } } ) ; this . _bottomNavigationBar . setItems ( tabItems ) ; items . forEach ( ( item , i , arr ) => { const textView = this . _bottomNavigationBar . getTextViewForItemAt ( i ) ; item . setNativeView ( textView ) ; this . _setItemColor ( item ) ; } ) ; } private getItemLabelTextTransform ( tabStripItem ) { const nestedLabel = tabStripItem . label ; let textTransform = null ; if ( nestedLabel && nestedLabel . style . textTransform !== 'initial' ) { textTransform = nestedLabel . style . textTransform ; } else if ( tabStripItem . style . textTransform !== 'initial' ) { textTransform = tabStripItem . style . textTransform ; } return textTransform || this . _textTransform ; } private createTabItemSpec ( tabStripItem ) { const tabItemSpec = new com . nativescript . material . core . TabItemSpec ( ) ; if ( tabStripItem . isLoaded ) { const titleLabel = tabStripItem . label ; let title = titleLabel . text ; const textTransform = this . getItemLabelTextTransform ( tabStripItem ) ; title = getTransformedText ( title , textTransform ) ; tabItemSpec . title = title ; const backgroundColor = tabStripItem . style . backgroundColor ; tabItemSpec . backgroundColor = backgroundColor ? backgroundColor . android : this . getTabBarBackgroundArgbColor ( ) ; const itemColor = this . selectedIndex === tabStripItem . _index ? this . _selectedItemColor : this . _unSelectedItemColor ; const color = itemColor || titleLabel . style . color ; tabItemSpec . color = color && color . android ; const fontInternal = titleLabel . style . fontInternal ; if ( fontInternal ) { tabItemSpec . fontSize = fontInternal . fontSize ; tabItemSpec . typeFace = fontInternal . getAndroidTypeface ( ) ; } const iconSource = tabStripItem . image && tabStripItem . image . src ; if ( iconSource ) { const iconInfo = this . getIconInfo ( tabStripItem , itemColor ) ; if ( iconInfo ) { tabItemSpec . iconDrawable = iconInfo . drawable ; tabItemSpec . imageHeight = iconInfo . height ; } else { } } } return tabItemSpec ; } private getOriginalIcon ( tabStripItem , color ? ) { const iconSource = tabStripItem . image && tabStripItem . image . src ; if ( ! iconSource ) { return null ; } let is ; if ( Utils . isFontIconURI ( iconSource ) ) { const fontIconCode = iconSource . split ( '//' ) [ 1 ] ; const target = tabStripItem . image ? tabStripItem . image : tabStripItem ; const font = target . style . fontInternal ; if ( ! color ) { color = target . style . color ; } is = ImageSource . fromFontIconCodeSync ( fontIconCode , font , color ) ; } else { is = ImageSource . fromFileOrResourceSync ( iconSource ) ; } return is && is . android ; } private getDrawableInfo ( image ) { if ( image ) { if ( this . tabStrip && this . tabStrip . isIconSizeFixed ) { image = this . getFixedSizeIcon ( image ) ; } const imageDrawable = new android . graphics . drawable . BitmapDrawable ( Application . android . context . getResources ( ) , image ) ; return { drawable : imageDrawable , height : image . getHeight ( ) } ; } return new IconInfo ( ) ; } private getIconInfo ( tabStripItem , color ? ) { const originalIcon = this . getOriginalIcon ( tabStripItem , color ) ; return this . getDrawableInfo ( originalIcon ) ; } private getFixedSizeIcon ( image ) { const inWidth = image . getWidth ( ) ; const inHeight = image . getHeight ( ) ; const iconSpecSize = getIconSpecSize ( { width : inWidth , height : inHeight } ) ; const widthPixels = iconSpecSize . width * Utils . layout . getDisplayDensity ( ) ; const heightPixels = iconSpecSize . height * Utils . layout . getDisplayDensity ( ) ; const scaledImage = android . graphics . Bitmap . createScaledBitmap ( image , widthPixels , heightPixels , true ) ; return scaledImage ; } public updateAndroidItemAt ( index , spec ) { if ( this . _bottomNavigationBar ) { this . _bottomNavigationBar . updateItemAt ( index , spec ) ; } } public getTabBarBackgroundColor ( ) { return this . _bottomNavigationBar . getBackground ( ) ; } public setTabBarBackgroundColor ( value ) { if ( ! this . _bottomNavigationBar ) { return ; } if ( value instanceof Color ) { this . _bottomNavigationBar . setBackgroundColor ( value . android ) ; } else { this . _bottomNavigationBar . setBackground ( tryCloneDrawable ( value , this . nativeViewProtected . getResources ( ) ) ) ; } this . updateTabStripItems ( ) ; } private updateTabStripItems ( ) { this . tabStrip . items . forEach ( ( tabStripItem ) => { if ( tabStripItem . nativeView ) { const tabItemSpec = this . createTabItemSpec ( tabStripItem ) ; this . updateAndroidItemAt ( tabStripItem . _index , tabItemSpec ) ; } } ) ; } public _setItemsColors ( items ) { items . forEach ( ( item ) => { if ( item . nativeView ) { this . _setItemColor ( item ) ; } } ) ; } public getTabBarSelectedItemColor ( ) { return this . _selectedItemColor ; } public setTabBarSelectedItemColor ( value ) { this . _selectedItemColor = value ; this . _setItemsColors ( this . tabStrip . items ) ; } public getTabBarUnSelectedItemColor ( ) { return this . _unSelectedItemColor ; } public setTabBarUnSelectedItemColor ( value ) { this . _unSelectedItemColor = value ; this . _setItemsColors ( this . tabStrip . items ) ; } private updateItem ( tabStripItem ) { const tabStripItemIndex = this . tabStrip . items . indexOf ( tabStripItem ) ; const tabItemSpec = this . createTabItemSpec ( tabStripItem ) ; this . updateAndroidItemAt ( tabStripItemIndex , tabItemSpec ) ; } public setTabBarItemTitle ( tabStripItem , value ) { this . updateItem ( tabStripItem ) ; } public setTabBarItemBackgroundColor ( tabStripItem , value ) { this . updateItem ( tabStripItem ) ; } public _setItemColor ( tabStripItem ) { const itemColor = tabStripItem . _index === this . selectedIndex ? this . _selectedItemColor : this . _unSelectedItemColor ; if ( ! itemColor ) { return ; } tabStripItem . nativeViewProtected . setTextColor ( itemColor . android ) ; this . setIconColor ( tabStripItem , itemColor ) ; } private setIconColor ( tabStripItem , color ? ) { const tabBarItem = this . _bottomNavigationBar . getViewForItemAt ( tabStripItem . _index ) ; if ( ! tabBarItem ) { return ; } const drawableInfo = this . getIconInfo ( tabStripItem , color ) ; const imgView = tabBarItem . getChildAt ( 0 ) as android . widget . ImageView ; imgView . setImageDrawable ( drawableInfo . drawable ) ; if ( color ) { imgView . setColorFilter ( color . android ) ; } } public setTabBarItemColor ( tabStripItem , value ) { const itemColor = tabStripItem . _index === this . selectedIndex ? this . _selectedItemColor : this . _unSelectedItemColor ; if ( itemColor ) { return ; } const androidColor = value instanceof Color ? value . android : value ; tabStripItem . nativeViewProtected . setTextColor ( androidColor ) ; } public setTabBarIconColor ( tabStripItem , value ) { const itemColor = tabStripItem . _index === this . selectedIndex ? this . _selectedItemColor : this . _unSelectedItemColor ; if ( itemColor ) { return ; } this . setIconColor ( tabStripItem ) ; } public setTabBarIconSource ( tabStripItem , value ) { this . updateItem ( tabStripItem ) ; } public setTabBarItemFontInternal ( tabStripItem , value ) { if ( value . fontSize ) { tabStripItem . nativeViewProtected . setTextSize ( value . fontSize ) ; } tabStripItem . nativeViewProtected . setTypeface ( value . getAndroidTypeface ( ) ) ; } public setTabBarItemTextTransform ( tabStripItem , value ) { const titleLabel = tabStripItem . label ; const title = getTransformedText ( titleLabel . text , value ) ; tabStripItem . nativeViewProtected . setText ( title ) ; } public getTabBarTextTransform ( ) { return this . _textTransform ; } public setTabBarTextTransform ( value ) { const items = this . tabStrip && this . tabStrip . items ; if ( items ) { items . forEach ( ( tabStripItem ) => { if ( tabStripItem . label && tabStripItem . nativeViewProtected ) { const nestedLabel = tabStripItem . label ; const title = getTransformedText ( nestedLabel . text , value ) ; tabStripItem . nativeViewProtected . setText ( title ) ; } } ) ; } this . _textTransform = value ; } [ selectedIndexProperty . setNative ] ( value ) { if ( this . tabStrip ) { this . _bottomNavigationBar . setSelectedPosition ( value ) ; } else { this . changeTab ( value ) ; } } [ itemsProperty . getDefault ] ( ) { return null ; } [ itemsProperty . setNative ] ( value ) { if ( value ) { value . forEach ( ( item , i ) => { ( item as any ) . index = i ; } ) ; } selectedIndexProperty . coerce ( this ) ; } [ tabStripProperty . getDefault ] ( ) { return null ; } [ tabStripProperty . setNative ] ( value ) { const items = this . tabStrip ? this . tabStrip . items : null ; this . setTabStripItems ( items ) ; } } function tryCloneDrawable ( value , resources ) { if ( value ) { const constantState = value . getConstantState ( ) ; if ( constantState ) { return constantState . newDrawable ( resources ) ; } } return value ; }