mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat: introduce fixed font icons to tab navigation (#7691)
This commit is contained in:
committed by
Manol Donev
parent
efdd7e625c
commit
8039c2c1dd
@@ -163,19 +163,23 @@ export class ImageSource implements ImageSourceDefinition {
|
||||
|
||||
const textBounds = new android.graphics.Rect();
|
||||
paint.getTextBounds(source, 0, source.length, textBounds);
|
||||
|
||||
const textWidth = textBounds.width();
|
||||
const textHeight = textBounds.height();
|
||||
if (textWidth > 0 && textHeight > 0) {
|
||||
const bitmap = android.graphics.Bitmap
|
||||
.createBitmap(
|
||||
textWidth,
|
||||
textHeight,
|
||||
android.graphics.Bitmap.Config.ARGB_8888
|
||||
);
|
||||
|
||||
const bitmap = android.graphics.Bitmap
|
||||
.createBitmap(
|
||||
textBounds.width(),
|
||||
textBounds.height(),
|
||||
android.graphics.Bitmap.Config.ARGB_8888
|
||||
);
|
||||
const canvas = new android.graphics.Canvas(bitmap);
|
||||
canvas.drawText(source, -textBounds.left, -textBounds.top, paint);
|
||||
|
||||
const canvas = new android.graphics.Canvas(bitmap);
|
||||
canvas.drawText(source, -textBounds.left, -textBounds.top, paint);
|
||||
this.android = bitmap;
|
||||
}
|
||||
|
||||
this.android = bitmap;
|
||||
|
||||
return this.android != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
||||
import { TextTransform } from "../text-base";
|
||||
|
||||
// Requires
|
||||
import { TabNavigationBase, itemsProperty, selectedIndexProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import {
|
||||
TabNavigationBase, getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
|
||||
} from "../tab-navigation-base/tab-navigation-base";
|
||||
import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
import { CSSType, Color } from "../core/view";
|
||||
@@ -166,85 +168,6 @@ function initializeNativeClasses() {
|
||||
AttachStateChangeListener = new AttachListener();
|
||||
}
|
||||
|
||||
function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
|
||||
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
|
||||
|
||||
if (tabStripItem.isLoaded) {
|
||||
const titleLabel = tabStripItem.label;
|
||||
let title = titleLabel.text;
|
||||
|
||||
// TEXT-TRANSFORM
|
||||
const textTransform = titleLabel.style.textTransform;
|
||||
if (textTransform) {
|
||||
title = getTransformedText(title, textTransform);
|
||||
}
|
||||
tabItemSpec.title = title;
|
||||
|
||||
// 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 {
|
||||
const icon = _getIcon(tabStripItem);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = <any>androidx.core.view.ViewCompat;
|
||||
if (compat.setElevation) {
|
||||
@@ -566,7 +489,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
items.forEach((item, i, arr) => {
|
||||
(<any>item).index = i;
|
||||
if (items[i]) {
|
||||
const tabItemSpec = createTabItemSpec(items[i]);
|
||||
const tabItemSpec = this.createTabItemSpec(items[i]);
|
||||
tabItems.push(tabItemSpec);
|
||||
}
|
||||
});
|
||||
@@ -579,6 +502,111 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
});
|
||||
}
|
||||
|
||||
private createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
|
||||
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
|
||||
|
||||
if (tabStripItem.isLoaded) {
|
||||
const titleLabel = tabStripItem.label;
|
||||
let title = titleLabel.text;
|
||||
|
||||
// TEXT-TRANSFORM
|
||||
const textTransform = titleLabel.style.textTransform;
|
||||
if (textTransform) {
|
||||
title = getTransformedText(title, textTransform);
|
||||
}
|
||||
tabItemSpec.title = title;
|
||||
|
||||
// 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 {
|
||||
const icon = this.getIcon(tabStripItem);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tabItemSpec;
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
let imageDrawable: android.graphics.drawable.BitmapDrawable;
|
||||
if (is && is.android) {
|
||||
let image = is.android;
|
||||
|
||||
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
|
||||
image = this.getFixedSizeIcon(image);
|
||||
}
|
||||
|
||||
imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
|
||||
} else {
|
||||
// TODO
|
||||
// traceMissingIcon(iconSource);
|
||||
}
|
||||
|
||||
return imageDrawable;
|
||||
}
|
||||
|
||||
private getFixedSizeIcon(image: android.graphics.Bitmap): android.graphics.Bitmap {
|
||||
const inWidth = image.getWidth();
|
||||
const inHeight = image.getHeight();
|
||||
|
||||
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
|
||||
|
||||
const widthPixels = iconSpecSize.width * layout.getDisplayDensity();
|
||||
const heightPixels = iconSpecSize.height * layout.getDisplayDensity();
|
||||
|
||||
const scaledImage = android.graphics.Bitmap.createScaledBitmap(image, widthPixels, heightPixels, true);
|
||||
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
public updateAndroidItemAt(index: number, spec: org.nativescript.widgets.TabItemSpec) {
|
||||
this._bottomNavigationBar.updateItemAt(index, spec);
|
||||
}
|
||||
@@ -598,14 +626,14 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
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);
|
||||
const tabItemSpec = this.createTabItemSpec(tabStripItem);
|
||||
this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec);
|
||||
}
|
||||
|
||||
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);
|
||||
const tabItemSpec = this.createTabItemSpec(tabStripItem);
|
||||
this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec);
|
||||
}
|
||||
|
||||
@@ -621,7 +649,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
const index = (<any>tabStripItem).index;
|
||||
const tabBarItem = this._bottomNavigationBar.getViewForItemAt(index);
|
||||
const imgView = <android.widget.ImageView>tabBarItem.getChildAt(0);
|
||||
const drawable = _getIcon(tabStripItem);
|
||||
const drawable = this.getIcon(tabStripItem);
|
||||
|
||||
imgView.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
||||
import { TextTransform } from "../text-base";
|
||||
|
||||
//Requires
|
||||
import { TabNavigationBase, itemsProperty, selectedIndexProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import {
|
||||
TabNavigationBase, getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
|
||||
} from "../tab-navigation-base/tab-navigation-base";
|
||||
import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
import { Frame } from "../frame";
|
||||
@@ -350,7 +352,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
}
|
||||
|
||||
public setTabBarIconColor(tabStripItem: TabStripItem, value: UIColor | Color): void {
|
||||
const image = this._getIcon(tabStripItem);
|
||||
const image = this.getIcon(tabStripItem);
|
||||
|
||||
tabStripItem.nativeView.image = image;
|
||||
tabStripItem.nativeView.selectedImage = image;
|
||||
@@ -510,7 +512,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
let title: string;
|
||||
|
||||
if (item.isLoaded) {
|
||||
image = this._getIcon(item);
|
||||
image = this.getIcon(item);
|
||||
title = item.label.text;
|
||||
|
||||
const textTransform = item.label.style.textTransform;
|
||||
@@ -524,11 +526,11 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
return tabBarItem;
|
||||
}
|
||||
|
||||
private _getIconRenderingMode(): UIImageRenderingMode {
|
||||
private getIconRenderingMode(): UIImageRenderingMode {
|
||||
return UIImageRenderingMode.AlwaysOriginal;
|
||||
}
|
||||
|
||||
public _getIcon(tabStripItem: TabStripItem): UIImage {
|
||||
private 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;
|
||||
@@ -552,7 +554,13 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
}
|
||||
|
||||
if (is && is.ios) {
|
||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||
image = is.ios;
|
||||
|
||||
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
|
||||
image = this.getFixedSizeIcon(image);
|
||||
}
|
||||
|
||||
const originalRenderedImage = image.imageWithRenderingMode(this.getIconRenderingMode());
|
||||
this._iconsCache[iconTag] = originalRenderedImage;
|
||||
image = originalRenderedImage;
|
||||
} else {
|
||||
@@ -564,6 +572,23 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
return image;
|
||||
}
|
||||
|
||||
private getFixedSizeIcon(image: UIImage): UIImage {
|
||||
const inWidth = image.size.width;
|
||||
const inHeight = image.size.height;
|
||||
|
||||
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
|
||||
|
||||
const widthPts = iconSpecSize.width;
|
||||
const heightPts = iconSpecSize.height;
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions({ width: widthPts, height: heightPts }, false, layout.getDisplayDensity());
|
||||
image.drawInRect(CGRectMake(0, 0, widthPts, heightPts));
|
||||
let resultImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return resultImage;
|
||||
}
|
||||
|
||||
// private _updateIOSTabBarColorsAndFonts(): void {
|
||||
// if (!this.tabStrip || !this.tabStrip.items || !this.tabStrip.items.length) {
|
||||
// return;
|
||||
|
||||
@@ -217,6 +217,8 @@ export class TabNavigationBase extends View {
|
||||
setTabBarItemTextTransform(tabStripItem: TabStripItem, value: any): void
|
||||
}
|
||||
|
||||
export function getIconSpecSize(size: { width: number, height: number }): { width: number, height: number }
|
||||
|
||||
export const itemsProperty: Property<TabNavigationBase, TabContentItem[]>;
|
||||
export const tabStripProperty: Property<TabNavigationBase, TabStrip>
|
||||
export const selectedIndexProperty: CoercibleProperty<TabNavigationBase, number>;
|
||||
|
||||
@@ -211,6 +211,35 @@ export interface TabNavigationBase {
|
||||
on(event: "selectedIndexChanged", callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any);
|
||||
}
|
||||
|
||||
const MIN_ICON_SIZE = 24;
|
||||
const MAX_ICON_WIDTH = 31;
|
||||
const MAX_ICON_HEIGHT = 28;
|
||||
|
||||
export function getIconSpecSize(size: { width: number, height: number }): { width: number, height: number } {
|
||||
const inWidth = size.width;
|
||||
const inHeight = size.height;
|
||||
let outWidth = 0;
|
||||
let outHeight = 0;
|
||||
|
||||
if (inWidth < inHeight) {
|
||||
outWidth = MIN_ICON_SIZE;
|
||||
outHeight = (inHeight * MIN_ICON_SIZE) / inWidth;
|
||||
if (outHeight > MAX_ICON_HEIGHT) {
|
||||
outHeight = MAX_ICON_HEIGHT;
|
||||
outWidth = (inWidth * MAX_ICON_HEIGHT) / inHeight;
|
||||
}
|
||||
} else {
|
||||
outHeight = MIN_ICON_SIZE;
|
||||
outWidth = (inWidth * MIN_ICON_SIZE) / inHeight;
|
||||
if (outWidth > MAX_ICON_WIDTH) {
|
||||
outWidth = MAX_ICON_WIDTH;
|
||||
outHeight = (inHeight * MAX_ICON_WIDTH) / inWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return { width: outWidth, height: outHeight };
|
||||
}
|
||||
|
||||
export const selectedIndexProperty = new CoercibleProperty<TabNavigationBase, number>({
|
||||
name: "selectedIndex", defaultValue: -1, affectsLayout: isIOS,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
|
||||
@@ -12,6 +12,8 @@ import { AddChildFromBuilder } from "../../core/view";
|
||||
import {
|
||||
View, ViewBase, CSSType, backgroundColorProperty, backgroundInternalProperty, PseudoClassHandler
|
||||
} from "../../core/view";
|
||||
import { Tabs } from "../../tabs";
|
||||
import { isIOS } from "../../../platform";
|
||||
|
||||
export * from "../../core/view";
|
||||
export const traceCategory = "TabView";
|
||||
@@ -209,7 +211,8 @@ export class TabStripItem extends View implements TabStripItemDefinition, AddChi
|
||||
|
||||
const parent = <TabStrip>this.parent;
|
||||
const tabStripParent = parent && <TabNavigationBase>parent.parent;
|
||||
if ((<any>this).index === tabStripParent.selectedIndex) {
|
||||
if ((<any>this).index === tabStripParent.selectedIndex &&
|
||||
!(isIOS && tabStripParent instanceof Tabs)) {
|
||||
this._goToVisualState("highlighted");
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -17,6 +17,11 @@ export class TabStrip extends View {
|
||||
*/
|
||||
items: Array<TabStripItem>;
|
||||
|
||||
/**
|
||||
* Gets or sets whether icon size should be fixed based on specs or use the actual size. Defaults to true(fixed).
|
||||
*/
|
||||
isIconSizeFixed: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets the icon rendering mode on iOS
|
||||
*/
|
||||
@@ -34,3 +39,4 @@ export class TabStrip extends View {
|
||||
}
|
||||
|
||||
export const iosIconRenderingModeProperty: Property<TabStrip, "automatic" | "alwaysOriginal" | "alwaysTemplate">;
|
||||
export const isIconSizeFixedProperty: Property<TabStrip, boolean>;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ViewBase, AddArrayFromBuilder, AddChildFromBuilder } from "../../core/v
|
||||
// Requires
|
||||
import {
|
||||
View, Property, CSSType, backgroundColorProperty, backgroundInternalProperty,
|
||||
colorProperty, fontInternalProperty
|
||||
colorProperty, fontInternalProperty, booleanConverter
|
||||
} from "../../core/view";
|
||||
import { textTransformProperty } from "../../text-base";
|
||||
|
||||
@@ -21,6 +21,7 @@ export const highlightColorProperty = new Property<TabStrip, Color>({ name: "hig
|
||||
@CSSType("TabStrip")
|
||||
export class TabStrip extends View implements TabStripDefinition, AddChildFromBuilder, AddArrayFromBuilder {
|
||||
public items: TabStripItem[];
|
||||
public isIconSizeFixed: boolean;
|
||||
public iosIconRenderingMode: "automatic" | "alwaysOriginal" | "alwaysTemplate";
|
||||
public _hasImage: boolean;
|
||||
public _hasTitle: boolean;
|
||||
@@ -136,4 +137,9 @@ itemsProperty.register(TabStrip);
|
||||
export const iosIconRenderingModeProperty = new Property<TabStrip, "automatic" | "alwaysOriginal" | "alwaysTemplate">({ name: "iosIconRenderingMode", defaultValue: "automatic" });
|
||||
iosIconRenderingModeProperty.register(TabStrip);
|
||||
|
||||
export const isIconSizeFixedProperty = new Property<TabStrip, boolean>({
|
||||
name: "isIconSizeFixed", defaultValue: true, valueConverter: booleanConverter
|
||||
});
|
||||
isIconSizeFixedProperty.register(TabStrip);
|
||||
|
||||
highlightColorProperty.register(TabStrip);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
||||
import { TextTransform } from "../text-base";
|
||||
|
||||
// Requires
|
||||
import { selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import { getIconSpecSize, selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import { TabsBase, swipeEnabledProperty, offscreenTabLimitProperty } from "./tabs-common";
|
||||
import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
@@ -283,85 +283,6 @@ function initializeNativeClasses() {
|
||||
TabsBar = TabsBarImplementation;
|
||||
}
|
||||
|
||||
function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
|
||||
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
|
||||
|
||||
if (tabStripItem.isLoaded) {
|
||||
const nestedLabel = tabStripItem.label;
|
||||
let title = nestedLabel.text;
|
||||
|
||||
// TEXT-TRANSFORM
|
||||
const textTransform = nestedLabel.style.textTransform;
|
||||
if (textTransform) {
|
||||
title = getTransformedText(title, textTransform);
|
||||
}
|
||||
tabItemSpec.title = title;
|
||||
|
||||
// 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 {
|
||||
const icon = _getIcon(tabStripItem);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -640,7 +561,7 @@ export class Tabs extends TabsBase {
|
||||
const tabItems = new Array<org.nativescript.widgets.TabItemSpec>();
|
||||
items.forEach((item: TabStripItem, i, arr) => {
|
||||
(<any>item).index = i;
|
||||
const tabItemSpec = createTabItemSpec(item);
|
||||
const tabItemSpec = this.createTabItemSpec(item);
|
||||
(<any>item).tabItemSpec = tabItemSpec;
|
||||
tabItems.push(tabItemSpec);
|
||||
});
|
||||
@@ -654,6 +575,111 @@ export class Tabs extends TabsBase {
|
||||
});
|
||||
}
|
||||
|
||||
private createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
|
||||
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
|
||||
|
||||
if (tabStripItem.isLoaded) {
|
||||
const nestedLabel = tabStripItem.label;
|
||||
let title = nestedLabel.text;
|
||||
|
||||
// TEXT-TRANSFORM
|
||||
const textTransform = nestedLabel.style.textTransform;
|
||||
if (textTransform) {
|
||||
title = getTransformedText(title, textTransform);
|
||||
}
|
||||
tabItemSpec.title = title;
|
||||
|
||||
// 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 {
|
||||
const icon = this.getIcon(tabStripItem);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tabItemSpec;
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
let imageDrawable: android.graphics.drawable.BitmapDrawable;
|
||||
if (is && is.android) {
|
||||
let image = is.android;
|
||||
|
||||
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
|
||||
image = this.getFixedSizeIcon(image);
|
||||
}
|
||||
|
||||
imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
|
||||
} else {
|
||||
// TODO
|
||||
// traceMissingIcon(iconSource);
|
||||
}
|
||||
|
||||
return imageDrawable;
|
||||
}
|
||||
|
||||
private getFixedSizeIcon(image: android.graphics.Bitmap): android.graphics.Bitmap {
|
||||
const inWidth = image.getWidth();
|
||||
const inHeight = image.getHeight();
|
||||
|
||||
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
|
||||
|
||||
const widthPixels = iconSpecSize.width * layout.getDisplayDensity();
|
||||
const heightPixels = iconSpecSize.height * layout.getDisplayDensity();
|
||||
|
||||
const scaledImage = android.graphics.Bitmap.createScaledBitmap(image, widthPixels, heightPixels, true);
|
||||
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
// private setAdapterItems(items: Array<TabStripItem>) {
|
||||
// if (this.shouldUpdateAdapter(items)) {
|
||||
// (<any>this._pagerAdapter).items = items;
|
||||
@@ -712,14 +738,14 @@ export class Tabs extends TabsBase {
|
||||
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);
|
||||
const tabItemSpec = this.createTabItemSpec(tabStripItem);
|
||||
this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec);
|
||||
}
|
||||
|
||||
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);
|
||||
const tabItemSpec = this.createTabItemSpec(tabStripItem);
|
||||
this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec);
|
||||
}
|
||||
|
||||
@@ -735,7 +761,7 @@ export class Tabs extends TabsBase {
|
||||
const index = (<any>tabStripItem).index;
|
||||
const tabBarItem = this._tabsBar.getViewForItemAt(index);
|
||||
const imgView = <android.widget.ImageView>tabBarItem.getChildAt(0);
|
||||
const drawable = _getIcon(tabStripItem);
|
||||
const drawable = this.getIcon(tabStripItem);
|
||||
|
||||
imgView.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TabStrip } from "../tab-navigation-base/tab-strip";
|
||||
import { TextTransform } from "../text-base";
|
||||
|
||||
// Requires
|
||||
import { selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import { getIconSpecSize, selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
|
||||
import { TabsBase, swipeEnabledProperty } from "./tabs-common";
|
||||
import { Font } from "../styling/font";
|
||||
import { Frame } from "../frame";
|
||||
@@ -697,7 +697,7 @@ export class Tabs extends TabsBase {
|
||||
// }
|
||||
// }
|
||||
|
||||
public getViewController(item: TabContentItem): UIViewController {
|
||||
private getViewController(item: TabContentItem): UIViewController {
|
||||
let newController: UIViewController = item.content ? item.content.viewController : null;
|
||||
|
||||
if (newController) {
|
||||
@@ -799,7 +799,7 @@ export class Tabs extends TabsBase {
|
||||
// this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate;
|
||||
}
|
||||
|
||||
public setTabStripItems(items: Array<TabStripItem>) {
|
||||
private setTabStripItems(items: Array<TabStripItem>) {
|
||||
if (!this.tabStrip || !items) {
|
||||
return;
|
||||
}
|
||||
@@ -816,7 +816,7 @@ export class Tabs extends TabsBase {
|
||||
this.tabBarItems = tabBarItems;
|
||||
|
||||
if (this.viewController && this.viewController.tabBar) {
|
||||
this.viewController.tabBar.itemAppearance = this._getTabBarItemAppearance();
|
||||
this.viewController.tabBar.itemAppearance = this.getTabBarItemAppearance();
|
||||
this.viewController.tabBar.items = NSArray.arrayWithArray(tabBarItems);
|
||||
// TODO: investigate why this call is necessary to actually toggle item appearance
|
||||
this.viewController.tabBar.sizeToFit();
|
||||
@@ -849,15 +849,17 @@ export class Tabs extends TabsBase {
|
||||
let image: UIImage;
|
||||
let title: string;
|
||||
|
||||
image = item.isLoaded && this._getIcon(item);
|
||||
title = item.label && item.label.text;
|
||||
if (item.isLoaded) {
|
||||
image = this.getIcon(item);
|
||||
title = item.label.text;
|
||||
|
||||
if (!this.tabStrip._hasImage) {
|
||||
this.tabStrip._hasImage = !!image;
|
||||
}
|
||||
|
||||
if (!this.tabStrip._hasTitle) {
|
||||
this.tabStrip._hasTitle = !!title;
|
||||
if (!this.tabStrip._hasImage) {
|
||||
this.tabStrip._hasImage = !!image;
|
||||
}
|
||||
|
||||
if (!this.tabStrip._hasTitle) {
|
||||
this.tabStrip._hasTitle = !!title;
|
||||
}
|
||||
}
|
||||
|
||||
const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index);
|
||||
@@ -865,7 +867,7 @@ export class Tabs extends TabsBase {
|
||||
return tabBarItem;
|
||||
}
|
||||
|
||||
private _getTabBarItemAppearance(): MDCTabBarItemAppearance {
|
||||
private getTabBarItemAppearance(): MDCTabBarItemAppearance {
|
||||
let itemAppearance;
|
||||
if (this.tabStrip._hasImage && this.tabStrip._hasTitle) {
|
||||
itemAppearance = MDCTabBarItemAppearance.TitledImages;
|
||||
@@ -878,11 +880,11 @@ export class Tabs extends TabsBase {
|
||||
return itemAppearance;
|
||||
}
|
||||
|
||||
private _getIconRenderingMode(): UIImageRenderingMode {
|
||||
private getIconRenderingMode(): UIImageRenderingMode {
|
||||
return UIImageRenderingMode.AlwaysOriginal;
|
||||
}
|
||||
|
||||
public _getIcon(tabStripItem: TabStripItem): UIImage {
|
||||
private getIcon(tabStripItem: TabStripItem): UIImage {
|
||||
const iconSource = tabStripItem.image && tabStripItem.image.src;
|
||||
if (!iconSource) {
|
||||
return null;
|
||||
@@ -890,7 +892,7 @@ export class Tabs extends TabsBase {
|
||||
|
||||
const target = tabStripItem.image;
|
||||
const font = target.style.fontInternal;
|
||||
const color = target.style.color;
|
||||
const color = tabStripItem.parent.style.color;
|
||||
const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(";");
|
||||
|
||||
let image: UIImage = this._iconsCache[iconTag];
|
||||
@@ -904,7 +906,13 @@ export class Tabs extends TabsBase {
|
||||
}
|
||||
|
||||
if (is && is.ios) {
|
||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||
image = is.ios;
|
||||
|
||||
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
|
||||
image = this.getFixedSizeIcon(image);
|
||||
}
|
||||
|
||||
const originalRenderedImage = image.imageWithRenderingMode(this.getIconRenderingMode());
|
||||
this._iconsCache[iconTag] = originalRenderedImage;
|
||||
image = originalRenderedImage;
|
||||
} else {
|
||||
@@ -916,6 +924,23 @@ export class Tabs extends TabsBase {
|
||||
return image;
|
||||
}
|
||||
|
||||
private getFixedSizeIcon(image: UIImage): UIImage {
|
||||
const inWidth = image.size.width;
|
||||
const inHeight = image.size.height;
|
||||
|
||||
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
|
||||
|
||||
const widthPts = iconSpecSize.width;
|
||||
const heightPts = iconSpecSize.height;
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions({ width: widthPts, height: heightPts }, false, layout.getDisplayDensity());
|
||||
image.drawInRect(CGRectMake(0, 0, widthPts, heightPts));
|
||||
let resultImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return resultImage;
|
||||
}
|
||||
|
||||
// private _updateIOSTabBarColorsAndFonts(): void {
|
||||
// if (!this.tabStrip || !this.tabStrip.items || !this.tabStrip.items.length) {
|
||||
// return;
|
||||
|
||||
Reference in New Issue
Block a user