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 fontInternal: Font;
public iconFontFamily: string;
/** /**
* This property ensures inheritance of a11y scale among views. * This property ensures inheritance of a11y scale among views.
*/ */

View File

@@ -9,6 +9,7 @@ import { Trace } from '../../trace';
import { Color } from '../../color'; import { Color } from '../../color';
import { fontSizeProperty, fontInternalProperty } from '../styling/style-properties'; import { fontSizeProperty, fontInternalProperty } from '../styling/style-properties';
import { RESOURCE_PREFIX, ad, layout } from '../../utils'; import { RESOURCE_PREFIX, ad, layout } from '../../utils';
import { FONT_PREFIX, isFontIconURI } from '../../utils/common';
import { Frame } from '../frame'; import { Frame } from '../frame';
import { Application } from '../../application'; import { Application } from '../../application';
import { AndroidHelper } from '../core/view'; import { AndroidHelper } from '../core/view';
@@ -292,19 +293,31 @@ function createTabItemSpec(item: TabViewItem): org.nativescript.widgets.TabItemS
result.title = item.title; result.title = item.title;
if (item.iconSource) { if (item.iconSource) {
if (item.iconSource.indexOf(RESOURCE_PREFIX) === 0) { const addDrawable = (is: ImageSource) => {
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);
if (is) { if (is) {
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS. // 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); result.iconDrawable = new android.graphics.drawable.BitmapDrawable(appResources, is.android);
} else { } else {
traceMissingIcon(item.iconSource); 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([ JSON.stringify([
{ value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ }, { value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ },
{ value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ }, { value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ },
]) ]),
); );
viewPager.setLayoutParams(lp); viewPager.setLayoutParams(lp);
@@ -506,7 +519,7 @@ export class TabView extends TabViewBase {
JSON.stringify([ JSON.stringify([
{ value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ }, { value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ },
{ value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ }, { value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ },
]) ]),
); );
tabLayout.setLayoutParams(lp); tabLayout.setLayoutParams(lp);
viewPager.setSwipePageEnabled(false); viewPager.setSwipePageEnabled(false);

View File

@@ -13,7 +13,7 @@ import { ImageSource } from '../../image-source';
import { profile } from '../../profiling'; import { profile } from '../../profiling';
import { Frame } from '../frame'; import { Frame } from '../frame';
import { layout } from '../../utils/layout-helper'; 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 { SDK_VERSION } from '../../utils/constants';
import { Device } from '../../platform'; import { Device } from '../../platform';
export * from './tab-view-common'; export * from './tab-view-common';
@@ -504,7 +504,16 @@ export class TabView extends TabViewBase {
if (isSystemURI(item.iconSource)) { if (isSystemURI(item.iconSource)) {
is = ImageSource.fromSystemImageSync(item.iconSource.slice(SYSTEM_PREFIX.length)); is = ImageSource.fromSystemImageSync(item.iconSource.slice(SYSTEM_PREFIX.length));
} else if (isFontIconURI(item.iconSource)) { } 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 { } else {
is = ImageSource.fromFileOrResourceSync(item.iconSource); is = ImageSource.fromFileOrResourceSync(item.iconSource);
} }

View File

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