feat(tabs): allow iconFontFamily for font icons in iconSource

This commit is contained in:
Nathan Walker
2025-08-19 13:49:39 -07:00
parent 226dc85efb
commit 6a8b92c1a1
4 changed files with 41 additions and 11 deletions

View File

@@ -106,6 +106,7 @@ export class Style extends Observable {
}
public fontInternal: Font;
public iconFontFamily: string;
/**
* This property ensures inheritance of a11y scale among views.
*/

View File

@@ -9,6 +9,7 @@ import { Trace } from '../../trace';
import { Color } from '../../color';
import { fontSizeProperty, fontInternalProperty } from '../styling/style-properties';
import { RESOURCE_PREFIX, ad, layout } from '../../utils';
import { FONT_PREFIX, isFontIconURI } from '../../utils/common';
import { Frame } from '../frame';
import { Application } from '../../application';
import { AndroidHelper } from '../core/view';
@@ -292,19 +293,31 @@ function createTabItemSpec(item: TabViewItem): org.nativescript.widgets.TabItemS
result.title = item.title;
if (item.iconSource) {
if (item.iconSource.indexOf(RESOURCE_PREFIX) === 0) {
result.iconId = ad.resources.getDrawableId(item.iconSource.substr(RESOURCE_PREFIX.length));
if (result.iconId === 0) {
traceMissingIcon(item.iconSource);
}
} else {
const is = ImageSource.fromFileOrResourceSync(item.iconSource);
const addDrawable = (is: ImageSource) => {
if (is) {
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
result.iconDrawable = new android.graphics.drawable.BitmapDrawable(appResources, is.android);
} else {
traceMissingIcon(item.iconSource);
}
};
if (item.iconSource.indexOf(RESOURCE_PREFIX) === 0) {
result.iconId = ad.resources.getDrawableId(item.iconSource.slice(RESOURCE_PREFIX.length));
if (result.iconId === 0) {
traceMissingIcon(item.iconSource);
}
} else if (isFontIconURI(item.iconSource)) {
// Allow specifying a separate font family for the icon via style.iconFontFamily.
let iconFont: any = item.style.fontInternal;
const iconFontFamily = item.iconFontFamily || item.style.iconFontFamily;
if (iconFontFamily) {
const baseFont = item.style.fontInternal || Font.default;
iconFont = baseFont.withFontFamily(iconFontFamily);
}
const is = ImageSource.fromFontIconCodeSync(item.iconSource.slice(FONT_PREFIX.length), iconFont, item.style.color);
addDrawable(is);
} else {
addDrawable(ImageSource.fromFileOrResourceSync(item.iconSource));
}
}
@@ -494,7 +507,7 @@ export class TabView extends TabViewBase {
JSON.stringify([
{ value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ },
{ value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ },
])
]),
);
viewPager.setLayoutParams(lp);
@@ -506,7 +519,7 @@ export class TabView extends TabViewBase {
JSON.stringify([
{ value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ },
{ value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ },
])
]),
);
tabLayout.setLayoutParams(lp);
viewPager.setSwipePageEnabled(false);

View File

@@ -13,7 +13,7 @@ import { ImageSource } from '../../image-source';
import { profile } from '../../profiling';
import { Frame } from '../frame';
import { layout } from '../../utils/layout-helper';
import { isFontIconURI, isSystemURI, SYSTEM_PREFIX } from '../../utils/common';
import { FONT_PREFIX, isFontIconURI, isSystemURI, SYSTEM_PREFIX } from '../../utils/common';
import { SDK_VERSION } from '../../utils/constants';
import { Device } from '../../platform';
export * from './tab-view-common';
@@ -504,7 +504,16 @@ export class TabView extends TabViewBase {
if (isSystemURI(item.iconSource)) {
is = ImageSource.fromSystemImageSync(item.iconSource.slice(SYSTEM_PREFIX.length));
} else if (isFontIconURI(item.iconSource)) {
is = ImageSource.fromFontIconCodeSync(item.iconSource, item.style.fontInternal, item.style.color);
// Allow specifying a separate font family for the icon via style.iconFontFamily.
// If provided, construct a Font from the family and (optionally) size from fontInternal.
let iconFont = item.style.fontInternal;
const iconFontFamily = item.iconFontFamily || item.style.iconFontFamily;
if (iconFontFamily) {
// Preserve size/style from existing fontInternal if present.
const baseFont = item.style.fontInternal || Font.default;
iconFont = baseFont.withFontFamily(iconFontFamily);
}
is = ImageSource.fromFontIconCodeSync(item.iconSource.slice(FONT_PREFIX.length), iconFont, item.style.color);
} else {
is = ImageSource.fromFileOrResourceSync(item.iconSource);
}

View File

@@ -15,6 +15,7 @@ export abstract class TabViewItemBase extends ViewBase implements TabViewItemDef
private _title = '';
private _view: View;
private _iconSource: string;
iconFontFamily: string;
get textTransform(): CoreTypes.TextTransformType {
return this.style.textTransform;
@@ -287,6 +288,12 @@ export const tabTextColorProperty = new CssProperty<Style, Color>({
});
tabTextColorProperty.register(Style);
export const iconFontFamilyProperty = new CssProperty<Style, string>({
name: 'iconFontFamily',
cssName: 'icon-font-family',
});
iconFontFamilyProperty.register(Style);
export const tabBackgroundColorProperty = new CssProperty<Style, Color>({
name: 'tabBackgroundColor',
cssName: 'tab-background-color',