diff --git a/e2e/ui-tests-app/app/bottom-navigation/color-page.css b/e2e/ui-tests-app/app/bottom-navigation/color-page.css index 17d688073..3b7744d0d 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/color-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/color-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { color: yellowgreen; } + +TabStripItem.nested Label { + color: teal; +} + +TabStripItem.nested:active Label { + color: yellowgreen; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/color-page.xml b/e2e/ui-tests-app/app/bottom-navigation/color-page.xml index b8c3e9d4e..b63d6c8c4 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/color-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/color-page.xml @@ -3,10 +3,13 @@ - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css index ee183523d..57076da81 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css @@ -6,6 +6,34 @@ font-size: 36; } -.color { - color: blue; -} \ No newline at end of file +TabStrip { + color: mediumvioletred; +} + +TabStripItem { + color: skyblue; +} + +TabStripItem:active { + color: darkblue; +} + +TabStripItem.special Image { + color: lightgreen; +} + +TabStripItem.special:active Image { + color: darkgreen; +} + +TabStripItem.special Label { + color: gold; +} + +TabStripItem.special:active Label { + color: darkgoldenrod; +} + +TabStripItem:active .font-size { + font-size: 10; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml index 644cdb121..c72f3320f 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml @@ -3,32 +3,61 @@ - + - - + + + + - + + + - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-page.css b/e2e/ui-tests-app/app/bottom-navigation/font-page.css index 22a3ce46c..57b0eda89 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/font-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { font: 16 monospace; } + +TabStripItem.nested Label { + font: 12 monospace; +} + +TabStripItem.nested:active Label { + font: 16 monospace; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-page.xml b/e2e/ui-tests-app/app/bottom-navigation/font-page.xml index 6da1c6233..b59f818d8 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/font-page.xml @@ -1,12 +1,15 @@ - + - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts index 199c5c566..bfb016431 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts +++ b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts @@ -6,10 +6,12 @@ export function onSelectedIndexChanged(args: SelectedIndexChangedEventData) { const newItem = bottomNav.tabStrip.items[args.newIndex]; if (newItem) { newItem.iconSource = "res://icon"; + newItem.title = "selected"; } const oldItem = bottomNav.tabStrip.items[args.oldIndex]; if (oldItem) { oldItem.iconSource = "res://testlogo"; + oldItem.title = "unselected"; } } diff --git a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml index 40bf3afac..1305f2a06 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml @@ -4,8 +4,8 @@ - - + + diff --git a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css index 80b3649d4..539c8c817 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { text-transform: uppercase; } + +TabStripItem.nested Label { + text-transform: lowercase; +} + +TabStripItem.nested:active Label { + text-transform: uppercase; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml index 33db487c6..dcddb8bd6 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml @@ -1,12 +1,15 @@ - + - + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/color-page.css b/e2e/ui-tests-app/app/tabs/color-page.css index b417cfecf..97c0d950b 100644 --- a/e2e/ui-tests-app/app/tabs/color-page.css +++ b/e2e/ui-tests-app/app/tabs/color-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { color: yellowgreen; } + +TabStripItem.nested Label { + color: teal; +} + +TabStripItem.nested:active Label { + color: yellowgreen; +} diff --git a/e2e/ui-tests-app/app/tabs/color-page.xml b/e2e/ui-tests-app/app/tabs/color-page.xml index be732a6c3..5741956f5 100644 --- a/e2e/ui-tests-app/app/tabs/color-page.xml +++ b/e2e/ui-tests-app/app/tabs/color-page.xml @@ -1,12 +1,15 @@ - + - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/font-icons-page.css b/e2e/ui-tests-app/app/tabs/font-icons-page.css index ee183523d..57076da81 100644 --- a/e2e/ui-tests-app/app/tabs/font-icons-page.css +++ b/e2e/ui-tests-app/app/tabs/font-icons-page.css @@ -6,6 +6,34 @@ font-size: 36; } -.color { - color: blue; -} \ No newline at end of file +TabStrip { + color: mediumvioletred; +} + +TabStripItem { + color: skyblue; +} + +TabStripItem:active { + color: darkblue; +} + +TabStripItem.special Image { + color: lightgreen; +} + +TabStripItem.special:active Image { + color: darkgreen; +} + +TabStripItem.special Label { + color: gold; +} + +TabStripItem.special:active Label { + color: darkgoldenrod; +} + +TabStripItem:active .font-size { + font-size: 10; +} diff --git a/e2e/ui-tests-app/app/tabs/font-icons-page.xml b/e2e/ui-tests-app/app/tabs/font-icons-page.xml index 317d5def4..0a31a8d76 100644 --- a/e2e/ui-tests-app/app/tabs/font-icons-page.xml +++ b/e2e/ui-tests-app/app/tabs/font-icons-page.xml @@ -3,32 +3,61 @@ - + - - + + + + - + + + - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/font-page.css b/e2e/ui-tests-app/app/tabs/font-page.css index 1e28cb2a5..d2473e4d7 100644 --- a/e2e/ui-tests-app/app/tabs/font-page.css +++ b/e2e/ui-tests-app/app/tabs/font-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { font: 16 monospace; } + +TabStripItem.nested Label { + font: 12 monospace; +} + +TabStripItem.nested:active Label { + font: 16 monospace; +} diff --git a/e2e/ui-tests-app/app/tabs/font-page.xml b/e2e/ui-tests-app/app/tabs/font-page.xml index a0c8bfa60..ee9003d98 100644 --- a/e2e/ui-tests-app/app/tabs/font-page.xml +++ b/e2e/ui-tests-app/app/tabs/font-page.xml @@ -1,12 +1,15 @@ - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/icon-change-page.ts b/e2e/ui-tests-app/app/tabs/icon-change-page.ts index 1a466d6a6..cf4e24af1 100644 --- a/e2e/ui-tests-app/app/tabs/icon-change-page.ts +++ b/e2e/ui-tests-app/app/tabs/icon-change-page.ts @@ -6,10 +6,12 @@ export function onSelectedIndexChanged(args: SelectedIndexChangedEventData) { const newItem = tabsNav.tabStrip.items[args.newIndex]; if (newItem) { newItem.iconSource = "res://icon"; + newItem.title = "selected"; } const oldItem = tabsNav.tabStrip.items[args.oldIndex]; if (oldItem) { oldItem.iconSource = "res://testlogo"; + oldItem.title = "unselected"; } } diff --git a/e2e/ui-tests-app/app/tabs/icon-change-page.xml b/e2e/ui-tests-app/app/tabs/icon-change-page.xml index 28f78dc9f..9dc1ede30 100644 --- a/e2e/ui-tests-app/app/tabs/icon-change-page.xml +++ b/e2e/ui-tests-app/app/tabs/icon-change-page.xml @@ -4,8 +4,8 @@ - - + + diff --git a/e2e/ui-tests-app/app/tabs/text-transform-page.css b/e2e/ui-tests-app/app/tabs/text-transform-page.css index db5fd0e50..ebbc005bd 100644 --- a/e2e/ui-tests-app/app/tabs/text-transform-page.css +++ b/e2e/ui-tests-app/app/tabs/text-transform-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { text-transform: uppercase; } + +TabStripItem.nested Label { + text-transform: lowercase; +} + +TabStripItem.nested:active Label { + text-transform: uppercase; +} diff --git a/e2e/ui-tests-app/app/tabs/text-transform-page.xml b/e2e/ui-tests-app/app/tabs/text-transform-page.xml index c80979319..aa9ea5bf3 100644 --- a/e2e/ui-tests-app/app/tabs/text-transform-page.xml +++ b/e2e/ui-tests-app/app/tabs/text-transform-page.xml @@ -1,12 +1,15 @@ - + - + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java index 29a5c0492..4e2cd7eeb 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java @@ -201,6 +201,19 @@ public class BottomNavigationBar extends LinearLayout { if (tabItem.title != null && !tabItem.title.isEmpty()) { textView.setText(tabItem.title); textView.setVisibility(VISIBLE); + + if (tabItem.typeFace != null) { + textView.setTypeface(tabItem.typeFace); + } + + if (tabItem.fontSize != 0) { + textView.setTextSize(tabItem.fontSize); + } + + if (tabItem.color != 0) { + textView.setTextColor(tabItem.color); + mTabStrip.setShouldUpdateTabsTextColor(false); + } } else { textView.setVisibility(GONE); } diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java index 2aa6ff08b..1494e407f 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java @@ -1,10 +1,14 @@ package org.nativescript.widgets; import android.graphics.drawable.Drawable; +import android.graphics.Typeface; public class TabItemSpec { public String title; + public int fontSize; + public Typeface typeFace; public int iconId; public Drawable iconDrawable; public int backgroundColor; + public int color; } \ No newline at end of file diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java index 557be52a1..37cb21c13 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java @@ -52,6 +52,8 @@ class TabStrip extends LinearLayout { private int mSelectedTabTextColor; private float mTabTextFontSize; + private boolean mShouldUpdateTabsTextColor; + TabStrip(Context context) { this(context, null); } @@ -87,6 +89,8 @@ class TabStrip extends LinearLayout { // Default selected color is the same as mTabTextColor mSelectedTabTextColor = mTabTextColor; + mShouldUpdateTabsTextColor = true; + setMeasureWithLargestChildEnabled(true); } @@ -120,16 +124,22 @@ class TabStrip extends LinearLayout { return mSelectedTabTextColor; } + void setShouldUpdateTabsTextColor(boolean value) { + mShouldUpdateTabsTextColor = value; + } + private void updateTabsTextColor(){ - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++){ - LinearLayout linearLayout = (LinearLayout)getChildAt(i); - TextView textView = (TextView)linearLayout.getChildAt(1); - if (i == mSelectedPosition){ - textView.setTextColor(mSelectedTabTextColor); - } - else { - textView.setTextColor(mTabTextColor); + if (mShouldUpdateTabsTextColor) { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++){ + LinearLayout linearLayout = (LinearLayout)getChildAt(i); + TextView textView = (TextView)linearLayout.getChildAt(1); + if (i == mSelectedPosition){ + textView.setTextColor(mSelectedTabTextColor); + } + else { + textView.setTextColor(mTabTextColor); + } } } } diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java index c53661cc7..20dfdfd0c 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java @@ -252,7 +252,6 @@ public class TabsBar extends HorizontalScrollView { textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); textView.setTypeface(Typeface.DEFAULT_BOLD); textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setAllCaps(true); textView.setMaxLines(2); textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setPadding(padding, 0, padding, 0); @@ -280,6 +279,19 @@ public class TabsBar extends HorizontalScrollView { if (tabItem.title != null && !tabItem.title.isEmpty()) { textView.setText(tabItem.title); textView.setVisibility(VISIBLE); + + if (tabItem.typeFace != null) { + textView.setTypeface(tabItem.typeFace); + } + + if (tabItem.fontSize != 0) { + textView.setTextSize(tabItem.fontSize); + } + + if (tabItem.color != 0) { + textView.setTextColor(tabItem.color); + mTabStrip.setShouldUpdateTabsTextColor(false); + } } else { textView.setVisibility(GONE); } diff --git a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts index 2051ad123..e229ce202 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts @@ -167,43 +167,58 @@ function initializeNativeClasses() { } function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec { - let iconSource; const tabItemSpec = new org.nativescript.widgets.TabItemSpec(); - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; - tabItemSpec.title = tabStripItem.label ? tabStripItem.label.text : tabStripItem.title; + if (tabStripItem.isLoaded) { + const titleLabel = tabStripItem.label; + let title = titleLabel.text; - if (tabStripItem.backgroundColor instanceof Color) { - tabItemSpec.backgroundColor = tabStripItem.backgroundColor.android; - } + // TEXT-TRANSFORM + const textTransform = titleLabel.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + tabItemSpec.title = title; - if (iconSource) { - if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { - tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); - if (tabItemSpec.iconId === 0) { - // TODO: - // traceMissingIcon(iconSource); - } - } else { - let is = new ImageSource(); - if (isFontIconURI(tabStripItem.iconSource)) { - const fontIconCode = tabStripItem.iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; - is = fromFontIconCode(fontIconCode, font, color); + // BACKGROUND-COLOR + const backgroundColor = tabStripItem.style.backgroundColor; + if (backgroundColor) { + tabItemSpec.backgroundColor = backgroundColor.android; + } + + // COLOR + const color = titleLabel.style.color; + if (color) { + tabItemSpec.color = color.android; + } + + // FONT + const fontInternal = titleLabel.style.fontInternal; + if (fontInternal) { + tabItemSpec.fontSize = fontInternal.fontSize; + tabItemSpec.typeFace = fontInternal.getAndroidTypeface(); + } + + // ICON + const iconSource = tabStripItem.image && tabStripItem.image.src; + if (iconSource) { + if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { + tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); + if (tabItemSpec.iconId === 0) { + // TODO: + // traceMissingIcon(iconSource); + } } else { - is = fromFileOrResource(tabStripItem.iconSource); - } + const icon = _getIcon(tabStripItem); - if (is) { - // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. - // tslint:disable-next-line:deprecation - tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); - } else { - // TODO: - // traceMissingIcon(iconSource); + if (icon) { + // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. + // tslint:disable-next-line:deprecation + tabItemSpec.iconDrawable = icon; + } else { + // TODO: + // traceMissingIcon(iconSource); + } } } } @@ -211,6 +226,25 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets return tabItemSpec; } +function _getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable { + const iconSource = tabStripItem.image && tabStripItem.image.src; + + let is: ImageSource; + if (isFontIconURI(iconSource)) { + const fontIconCode = iconSource.split("//")[1]; + const target = tabStripItem.image ? tabStripItem.image : tabStripItem; + const font = target.style.fontInternal; + const color = target.style.color; + is = fromFontIconCode(fontIconCode, font, color); + } else { + is = fromFileOrResource(iconSource); + } + + const image = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); + + return image; +} + function setElevation(bottomNavigationBar: org.nativescript.widgets.BottomNavigationBar) { const compat = androidx.core.view.ViewCompat; if (compat.setElevation) { @@ -561,18 +595,11 @@ export class BottomNavigation extends TabNavigationBase { } } - public getTabBarColor(): number { - return this._bottomNavigationBar.getTabTextColor(); - } - - public setTabBarColor(value: number | Color): void { - if (value instanceof Color) { - this._bottomNavigationBar.setTabTextColor(value.android); - this._bottomNavigationBar.setSelectedTabTextColor(value.android); - } else { - this._bottomNavigationBar.setTabTextColor(value); - this._bottomNavigationBar.setSelectedTabTextColor(value); - } + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { + // TODO: Should figure out a way to do it directly with the the nativeView + const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); + const tabItemSpec = createTabItemSpec(tabStripItem); + this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { @@ -582,10 +609,6 @@ export class BottomNavigation extends TabNavigationBase { this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } - public getTabBarItemColor(tabStripItem: TabStripItem): number { - return tabStripItem.nativeViewProtected.getCurrentTextColor(); - } - public setTabBarItemColor(tabStripItem: TabStripItem, value: number | Color): void { if (typeof value === "number") { tabStripItem.nativeViewProtected.setTextColor(value); @@ -594,45 +617,24 @@ export class BottomNavigation extends TabNavigationBase { } } - public getTabBarItemFontSize(tabStripItem: TabStripItem): { nativeSize: number } { - return { nativeSize: tabStripItem.nativeViewProtected.getTextSize() }; + public setTabBarIconColor(tabStripItem: TabStripItem, value: number | Color): void { + const index = (tabStripItem).index; + const tabBarItem = this._bottomNavigationBar.getViewForItemAt(index); + const imgView = tabBarItem.getChildAt(0); + const drawable = _getIcon(tabStripItem); + + imgView.setImageDrawable(drawable); } - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - if (typeof value === "number") { - tabStripItem.nativeViewProtected.setTextSize(value); - } else { - tabStripItem.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { + tabStripItem.nativeViewProtected.setTextSize(value.fontSize); + tabStripItem.nativeViewProtected.setTypeface(value.getAndroidTypeface()); } - public getTabBarItemFontInternal(tabStripItem: TabStripItem): android.graphics.Typeface { - return tabStripItem.nativeViewProtected.getTypeface(); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font | android.graphics.Typeface): void { - tabStripItem.nativeViewProtected.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value); - } - - private _defaultTransformationMethod: android.text.method.TransformationMethod; - - public getTabBarItemTextTransform(tabStripItem: TabStripItem): "default" { - return "default"; - } - - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform | "default"): void { - const tv = tabStripItem.nativeViewProtected; - - this._defaultTransformationMethod = this._defaultTransformationMethod || tv.getTransformationMethod(); - - if (value === "default") { - tv.setTransformationMethod(this._defaultTransformationMethod); - tv.setText(tabStripItem.title); - } else { - const result = getTransformedText(tabStripItem.title, value); - tv.setText(result); - tv.setTransformationMethod(null); - } + public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { + const titleLabel = tabStripItem.label; + const title = getTransformedText(titleLabel.text, value); + tabStripItem.nativeViewProtected.setText(title); } [selectedIndexProperty.setNative](value: number) { diff --git a/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts b/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts index 8f8918d30..62d0c26d7 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts @@ -259,6 +259,8 @@ export class BottomNavigation extends TabNavigationBase { public onLoaded() { super.onLoaded(); + this.setViewControllers(this.items); + const selectedIndex = this.selectedIndex; const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].content; if (selectedView instanceof Frame) { @@ -320,21 +322,8 @@ export class BottomNavigation extends TabNavigationBase { this._ios.tabBar.barTintColor = value instanceof Color ? value.ios : value; } - public getTabBarColor(): UIColor { - return this._ios.tabBar.tintColor; - } - - public setTabBarColor(value: UIColor | Color): void { - this._ios.tabBar.tintColor = value instanceof Color ? value.ios : value; - - if (!this.tabStrip) { - return; - } - - const states = getTitleAttributesForStates(this.tabStrip); - this.tabStrip.items.forEach((tabStripItem) => { - applyStatesToItem(tabStripItem.nativeView, states); - }); + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { + tabStripItem.nativeView.title = value; } public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: UIColor | Color): void { @@ -355,39 +344,25 @@ export class BottomNavigation extends TabNavigationBase { bgView.backgroundColor = value instanceof Color ? value.ios : value; } - public getTabBarItemColor(tabStripItem: TabStripItem): UIColor { - return this._ios.tabBar.tintColor; - } - public setTabBarItemColor(tabStripItem: TabStripItem, value: UIColor | Color): void { - const states = getTitleAttributesForStates(tabStripItem); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabStripItem.nativeView, states); } - public getTabBarItemFontSize(tabStripItem: TabStripItem): number { - return null; - } + public setTabBarIconColor(tabStripItem: TabStripItem, value: UIColor | Color): void { + const image = this._getIcon(tabStripItem); - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - const states = getTitleAttributesForStates(tabStripItem); - applyStatesToItem(tabStripItem.nativeView, states); - } - - public getTabBarItemFontInternal(tabStripItem: TabStripItem): Font { - return null; + tabStripItem.nativeView.image = image; + tabStripItem.nativeView.selectedImage = image; } public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { - const states = getTitleAttributesForStates(tabStripItem); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabStripItem.nativeView, states); } - public getTabBarItemTextTransform(tabStripItem: TabStripItem): TextTransform { - return null; - } - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { - const title = getTransformedText(tabStripItem.title, value); + const title = getTransformedText(tabStripItem.label.text, value); tabStripItem.nativeView.title = title; } @@ -499,7 +474,6 @@ export class BottomNavigation extends TabNavigationBase { items = items.slice(0, maxTabsCount); const controllers = NSMutableArray.alloc().initWithCapacity(length); - const states = getTitleAttributesForStates(this); if (this.tabStrip) { this.tabStrip.setNativeView(this._ios.tabBar); @@ -513,6 +487,7 @@ export class BottomNavigation extends TabNavigationBase { const tabBarItem = this.createTabBarItem(tabStripItem, i); updateTitleAndIconPositions(tabStripItem, tabBarItem, controller); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabBarItem, states); controller.tabBarItem = tabBarItem; @@ -534,8 +509,15 @@ export class BottomNavigation extends TabNavigationBase { let image: UIImage; let title: string; - image = this._getIcon(item); - title = item.label ? item.label.text : item.title; + if (item.isLoaded) { + image = this._getIcon(item); + title = item.label.text; + + const textTransform = item.label.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + } const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index); @@ -549,18 +531,21 @@ export class BottomNavigation extends TabNavigationBase { public _getIcon(tabStripItem: TabStripItem): UIImage { // Image and Label children of TabStripItem // take priority over its `iconSource` and `title` properties - const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; + const iconSource = tabStripItem.image && tabStripItem.image.src; if (!iconSource) { return null; } - let image: UIImage = this._iconsCache[iconSource]; + const target = tabStripItem.image; + const font = target.style.fontInternal; + const color = target.style.color; + const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(";"); + + let image: UIImage = this._iconsCache[iconTag]; if (!image) { let is = new ImageSource; if (isFontIconURI(iconSource)) { const fontIconCode = iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; is = fromFontIconCode(fontIconCode, font, color); } else { is = fromFileOrResource(iconSource); @@ -568,7 +553,7 @@ export class BottomNavigation extends TabNavigationBase { if (is && is.ios) { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); - this._iconsCache[iconSource] = originalRenderedImage; + this._iconsCache[iconTag] = originalRenderedImage; image = originalRenderedImage; } else { // TODO @@ -615,6 +600,12 @@ export class BottomNavigation extends TabNavigationBase { return null; } [itemsProperty.setNative](value: TabContentItem[]) { + if (value) { + value.forEach((item: TabContentItem, i) => { + (item).index = i; + }); + } + this.setViewControllers(value); selectedIndexProperty.coerce(this); } diff --git a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts index 1c81bfa0c..73aba71b0 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts @@ -27,7 +27,6 @@ export class TabContentItem extends TabContentItemBase { public initNativeView(): void { super.initNativeView(); - this.nativeViewProtected.setBackgroundColor(-1); // White color. } public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean { diff --git a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts index 400b158a5..6a11acd77 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts @@ -144,6 +144,12 @@ export class TabNavigationBase extends View { */ setTabBarHighlightColor(value: any) + /** + * @private + * Method is intended to be overridden by inheritors and used as "protected" + */ + setTabBarItemTitle(tabStripItem: TabStripItem, value: any): any + /** * @private * Method is intended to be overridden by inheritors and used as "protected" @@ -168,6 +174,12 @@ export class TabNavigationBase extends View { */ setTabBarItemColor(tabStripItem: TabStripItem, value: any): void + /** + * @private + * Method is intended to be overridden by inheritors and used as "protected" + */ + setTabBarIconColor(tabStripItem: TabStripItem, value: any): void + /** * @private * Method is intended to be overridden by inheritors and used as "protected" diff --git a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts index f18c5b8de..b72d5640d 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts @@ -152,6 +152,10 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti // overridden by inheritors } + public setTabBarItemTitle(tabStripItem: TabStripItem, value: any): void { + // overridden by inheritors + } + public getTabBarItemBackgroundColor(tabStripItem: TabStripItem): any { // overridden by inheritors return null; @@ -170,6 +174,10 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti // overridden by inheritors } + public setTabBarIconColor(tabStripItem: TabStripItem, value: any): void { + // overridden by inheritors + } + public getTabBarItemFontSize(tabStripItem: TabStripItem): any { // overridden by inheritors return null; diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts index 9d81137f9..79753759d 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts @@ -1,5 +1,6 @@ // Types import { TabStripItem as TabStripItemDefinition } from "."; +import { PropertyChangeData } from "../../../data/observable"; import { TabNavigationBase } from "../tab-navigation-base"; import { TabStrip } from "../tab-strip"; import { Image } from "../../image/image"; @@ -9,10 +10,8 @@ import { AddChildFromBuilder } from "../../core/view"; // Requires import { - View, CSSType, backgroundColorProperty, backgroundInternalProperty, colorProperty, - fontSizeProperty, fontInternalProperty, PseudoClassHandler + View, ViewBase, CSSType, backgroundColorProperty, backgroundInternalProperty, PseudoClassHandler } from "../../core/view"; -import { textTransformProperty, TextTransform } from "../../text-base"; export * from "../../core/view"; export const traceCategory = "TabView"; @@ -23,14 +22,153 @@ export class TabStripItem extends View implements TabStripItemDefinition, AddChi public static selectEvent = "select"; public static unselectEvent = "unselect"; - public title: string; - public iconSource: string; public image: Image; public label: Label; + private _title: string; + private _iconSource: string; + private _highlightedHandler: () => void; private _normalHandler: () => void; + private _labelColorHandler: (args: PropertyChangeData) => void; + private _labelFontHandler: (args: PropertyChangeData) => void; + private _labelTextTransformHandler: (args: PropertyChangeData) => void; + private _labelTextHandler: (args: PropertyChangeData) => void; + + private _imageColorHandler: (args: PropertyChangeData) => void; + private _imageFontHandler: (args: PropertyChangeData) => void; + private _imageSrcHandler: (args: PropertyChangeData) => void; + + get title(): string { + if (this.isLoaded) { + return this.label.text; + } + + return this._title; + } + + set title(value: string) { + this._title = value; + + if (this.isLoaded) { + this.label.text = value; + } + } + + get iconSource(): string { + if (this.isLoaded) { + return this.image.src; + } + + return this._iconSource; + } + + set iconSource(value: string) { + this._iconSource = value; + + if (this.isLoaded) { + this.image.src = value; + } + } + + public onLoaded() { + if (!this.image) { + const image = new Image(); + image.src = this.iconSource; + this.image = image; + this._addView(this.image); + } + + if (!this.label) { + const label = new Label(); + label.text = this.title; + this.label = label; + this._addView(this.label); + } + + super.onLoaded(); + + this._labelColorHandler = this._labelColorHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemColor(this, args.value); + }); + this.label.style.on("colorChange", this._labelColorHandler); + + this._labelFontHandler = this._labelFontHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemFontInternal(this, args.value); + }); + this.label.style.on("fontInternalChange", this._labelFontHandler); + + this._labelTextTransformHandler = this._labelTextTransformHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemTextTransform(this, args.value); + }); + this.label.style.on("textTransformChange", this._labelTextTransformHandler); + + this._labelTextHandler = this._labelTextHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemTitle(this, args.value); + }); + this.label.on("textChange", this._labelTextHandler); + + this._imageColorHandler = this._imageColorHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.style.on("colorChange", this._imageColorHandler); + + this._imageFontHandler = this._imageFontHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.style.on("fontInternalChange", this._imageFontHandler); + + this._imageSrcHandler = this._imageSrcHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.on("srcChange", this._imageSrcHandler); + } + + public onUnloaded() { + super.onUnloaded(); + + this.label.style.off("colorChange", this._labelColorHandler); + this.label.style.off("fontInternalChange", this._labelFontHandler); + this.label.style.off("textTransformChange", this._labelTextTransformHandler); + this.label.style.off("textChange", this._labelTextHandler); + + this.image.style.off("colorChange", this._imageColorHandler); + this.image.style.off("fontInternalChange", this._imageFontHandler); + this.image.style.off("srcChange", this._imageSrcHandler); + } + + public eachChild(callback: (child: ViewBase) => boolean) { + if (this.label) { + callback(this.label); + } + + if (this.image) { + callback(this.image); + } + } + public _addChildFromBuilder(name: string, value: any): void { if (name === "Image") { this.image = value; @@ -99,56 +237,4 @@ export class TabStripItem extends View implements TabStripItemDefinition, AddChi [backgroundInternalProperty.setNative](value: any) { // disable the background CSS properties } - - [colorProperty.getDefault](): Color { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemColor(this); - } - [colorProperty.setNative](value: Color) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemColor(this, value); - } - - [fontSizeProperty.getDefault](): { nativeSize: number } { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemFontSize(this); - } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemFontSize(this, value); - } - - [fontInternalProperty.getDefault](): any { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemFontInternal(this); - } - [fontInternalProperty.setNative](value: any) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemFontInternal(this, value); - } - - [textTransformProperty.getDefault](): any { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemTextTransform(this); - } - [textTransformProperty.setNative](value: any) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemTextTransform(this, value); - } } diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts index 774af491d..bd2280d12 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts @@ -51,6 +51,18 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu } } + public onItemsChanged(oldItems: TabStripItem[], newItems: TabStripItem[]): void { + if (oldItems) { + oldItems.forEach(item => this._removeView(item)); + } + + if (newItems) { + newItems.forEach(item => { + this._addView(item); + }); + } + } + [backgroundColorProperty.getDefault](): Color { const parent = this.parent; @@ -112,7 +124,14 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu return parent && parent.setTabBarHighlightColor(value); } -} +} + +export const itemsProperty = new Property({ + name: "items", valueChanged: (target, oldValue, newValue) => { + target.onItemsChanged(oldValue, newValue); + } +}); +itemsProperty.register(TabStrip); export const iosIconRenderingModeProperty = new Property({ name: "iosIconRenderingMode", defaultValue: "automatic" }); iosIconRenderingModeProperty.register(TabStrip); diff --git a/tns-core-modules/ui/tabs/tabs.android.ts b/tns-core-modules/ui/tabs/tabs.android.ts index fbfa0929b..9fa203fb4 100644 --- a/tns-core-modules/ui/tabs/tabs.android.ts +++ b/tns-core-modules/ui/tabs/tabs.android.ts @@ -284,42 +284,58 @@ function initializeNativeClasses() { } function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec { - let iconSource; const tabItemSpec = new org.nativescript.widgets.TabItemSpec(); - if (tabStripItem.backgroundColor instanceof Color) { - tabItemSpec.backgroundColor = tabStripItem.backgroundColor.android; - } + if (tabStripItem.isLoaded) { + const nestedLabel = tabStripItem.label; + let title = nestedLabel.text; - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; - tabItemSpec.title = tabStripItem.label ? tabStripItem.label.text : tabStripItem.title; + // TEXT-TRANSFORM + const textTransform = nestedLabel.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + tabItemSpec.title = title; - if (iconSource) { - if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { - tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); - if (tabItemSpec.iconId === 0) { - // TODO - // traceMissingIcon(iconSource); - } - } else { - let is = new ImageSource(); - if (isFontIconURI(tabStripItem.iconSource)) { - const fontIconCode = tabStripItem.iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; - is = fromFontIconCode(fontIconCode, font, color); + // BACKGROUND-COLOR + const backgroundColor = tabStripItem.style.backgroundColor; + if (backgroundColor) { + tabItemSpec.backgroundColor = backgroundColor.android; + } + + // COLOR + const color = nestedLabel.style.color; + if (color) { + tabItemSpec.color = color.android; + } + + // FONT + const fontInternal = nestedLabel.style.fontInternal; + if (fontInternal) { + tabItemSpec.fontSize = fontInternal.fontSize; + tabItemSpec.typeFace = fontInternal.getAndroidTypeface(); + } + + // ICON + const iconSource = tabStripItem.image && tabStripItem.image.src; + if (iconSource) { + if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { + tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); + if (tabItemSpec.iconId === 0) { + // TODO: + // traceMissingIcon(iconSource); + } } else { - is = fromFileOrResource(tabStripItem.iconSource); - } + const icon = _getIcon(tabStripItem); - if (is) { - // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. - tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); - } else { - // TODO - // traceMissingIcon(iconSource); + if (icon) { + // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. + // tslint:disable-next-line:deprecation + tabItemSpec.iconDrawable = icon; + } else { + // TODO: + // traceMissingIcon(iconSource); + } } } } @@ -327,6 +343,25 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets return tabItemSpec; } +function _getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable { + const iconSource = tabStripItem.image && tabStripItem.image.src; + + let is = new ImageSource(); + if (isFontIconURI(iconSource)) { + const fontIconCode = iconSource.split("//")[1]; + const target = tabStripItem.image ? tabStripItem.image : tabStripItem; + const font = target.style.fontInternal; + const color = target.style.color; + is = fromFontIconCode(fontIconCode, font, color); + } else { + is = fromFileOrResource(iconSource); + } + + const image = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); + + return image; +} + let defaultAccentColor: number = undefined; function getDefaultAccentColor(context: android.content.Context): number { if (defaultAccentColor === undefined) { @@ -665,20 +700,6 @@ export class Tabs extends TabsBase { } } - public getTabBarColor(): number { - return this._tabsBar.getTabTextColor(); - } - - public setTabBarColor(value: number | Color): void { - if (value instanceof Color) { - this._tabsBar.setTabTextColor(value.android); - this._tabsBar.setSelectedTabTextColor(value.android); - } else { - this._tabsBar.setTabTextColor(value); - this._tabsBar.setSelectedTabTextColor(value); - } - } - public getTabBarHighlightColor(): number { return getDefaultAccentColor(this._context); } @@ -688,15 +709,18 @@ export class Tabs extends TabsBase { this._tabsBar.setSelectedIndicatorColors([color]); } - public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { // TODO: Should figure out a way to do it directly with the the nativeView const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); const tabItemSpec = createTabItemSpec(tabStripItem); this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } - public getTabBarItemColor(tabStripItem: TabStripItem): number { - return tabStripItem.nativeViewProtected.getCurrentTextColor(); + public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { + // TODO: Should figure out a way to do it directly with the the nativeView + const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); + const tabItemSpec = createTabItemSpec(tabStripItem); + this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } public setTabBarItemColor(tabStripItem: TabStripItem, value: number | Color): void { @@ -707,45 +731,24 @@ export class Tabs extends TabsBase { } } - public getTabBarItemFontSize(tabStripItem: TabStripItem): { nativeSize: number } { - return { nativeSize: tabStripItem.nativeViewProtected.getTextSize() }; + public setTabBarIconColor(tabStripItem: TabStripItem, value: number | Color): void { + const index = (tabStripItem).index; + const tabBarItem = this._tabsBar.getViewForItemAt(index); + const imgView = tabBarItem.getChildAt(0); + const drawable = _getIcon(tabStripItem); + + imgView.setImageDrawable(drawable); } - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - if (typeof value === "number") { - tabStripItem.nativeViewProtected.setTextSize(value); - } else { - tabStripItem.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { + tabStripItem.nativeViewProtected.setTextSize(value.fontSize); + tabStripItem.nativeViewProtected.setTypeface(value.getAndroidTypeface()); } - public getTabBarItemFontInternal(tabStripItem: TabStripItem): android.graphics.Typeface { - return tabStripItem.nativeViewProtected.getTypeface(); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font | android.graphics.Typeface): void { - tabStripItem.nativeViewProtected.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value); - } - - private _defaultTransformationMethod: android.text.method.TransformationMethod; - - public getTabBarItemTextTransform(tabStripItem: TabStripItem): "default" { - return "default"; - } - - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform | "default"): void { - const tv = tabStripItem.nativeViewProtected; - - this._defaultTransformationMethod = this._defaultTransformationMethod || tv.getTransformationMethod(); - - if (value === "default") { - tv.setTransformationMethod(this._defaultTransformationMethod); - tv.setText(tabStripItem.title); - } else { - const result = getTransformedText(tabStripItem.title, value); - tv.setText(result); - tv.setTransformationMethod(null); - } + public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { + const nestedLabel = tabStripItem.label; + const title = getTransformedText(nestedLabel.text, value); + tabStripItem.nativeViewProtected.setText(title); } [selectedIndexProperty.setNative](value: number) { diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts index d278ac4c6..2bceb236d 100644 --- a/tns-core-modules/ui/tabs/tabs.ios.ts +++ b/tns-core-modules/ui/tabs/tabs.ios.ts @@ -528,10 +528,8 @@ export class Tabs extends TabsBase { this._ios.dataSource = this._dataSource; this._ios.delegate = this._delegate; - if (!this.tabBarItems) { - const tabStripItems = this.tabStrip ? this.tabStrip.items : null; - this.setTabStripItems(tabStripItems); - } + const tabStripItems = this.tabStrip ? this.tabStrip.items : null; + this.setTabStripItems(tabStripItems); } public onUnloaded() { @@ -838,8 +836,8 @@ export class Tabs extends TabsBase { let image: UIImage; let title: string; - image = this._getIcon(item); - title = item.label ? item.label.text : item.title; + image = item.isLoaded && this._getIcon(item); + title = item.label && item.label.text; if (!this.tabStrip._hasImage) { this.tabStrip._hasImage = !!image; @@ -872,20 +870,21 @@ export class Tabs extends TabsBase { } public _getIcon(tabStripItem: TabStripItem): UIImage { - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; + const iconSource = tabStripItem.image && tabStripItem.image.src; if (!iconSource) { return null; } - let image: UIImage = this._iconsCache[iconSource]; + const target = tabStripItem.image; + const font = target.style.fontInternal; + const color = target.style.color; + const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(";"); + + let image: UIImage = this._iconsCache[iconTag]; if (!image) { let is = new ImageSource; if (isFontIconURI(iconSource)) { const fontIconCode = iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; is = fromFontIconCode(fontIconCode, font, color); } else { is = fromFileOrResource(iconSource); @@ -893,7 +892,7 @@ export class Tabs extends TabsBase { if (is && is.ios) { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); - this._iconsCache[iconSource] = originalRenderedImage; + this._iconsCache[iconTag] = originalRenderedImage; image = originalRenderedImage; } else { // TODO diff --git a/tns-platform-declarations/android/org.nativescript.widgets.d.ts b/tns-platform-declarations/android/org.nativescript.widgets.d.ts index b78e57aa2..dc17e7638 100644 --- a/tns-platform-declarations/android/org.nativescript.widgets.d.ts +++ b/tns-platform-declarations/android/org.nativescript.widgets.d.ts @@ -452,9 +452,12 @@ export class TabItemSpec { title: string; + fontSize: number; + typeFace: android.graphics.Typeface; iconId: number; iconDrawable: android.graphics.drawable.Drawable; backgroundColor: number; + color: number; } export namespace image {