mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
feat: add font icons to image actionbar and tab navigation (#7498)
This commit is contained in:

committed by
Manol Donev

parent
aa1c160465
commit
d8262a624e
11
e2e/ui-tests-app/app/action-bar/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/action-bar/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
||||
.font-awesome {
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
|
||||
.font-size {
|
||||
font-size: 48;
|
||||
}
|
||||
|
||||
.color {
|
||||
color: blue;
|
||||
}
|
17
e2e/ui-tests-app/app/action-bar/font-icons-page.ts
Normal file
17
e2e/ui-tests-app/app/action-bar/font-icons-page.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import * as frame from "tns-core-modules/ui/frame";
|
||||
import { EventData } from "tns-core-modules/ui/frame";
|
||||
import { Button } from "tns-core-modules/ui/button";
|
||||
import { ActionBar } from "tns-core-modules/ui/action-bar";
|
||||
|
||||
const iconModes = ["automatic", "alwaysOriginal", "alwaysTemplate", undefined];
|
||||
|
||||
export function navigate(args) {
|
||||
frame.topmost().navigate("ui-tests-app/action-bar/clean");
|
||||
}
|
||||
|
||||
export function onChangeRenderingMode(args: EventData) {
|
||||
const button = <Button>args.object;
|
||||
const actionBar = <ActionBar>button.page.actionBar;
|
||||
actionBar.iosIconRenderingMode = <"automatic" | "alwaysOriginal" | "alwaysTemplate">iconModes[(iconModes.indexOf(actionBar.iosIconRenderingMode) + 1) % iconModes.length];
|
||||
button.text = "" + actionBar.iosIconRenderingMode;
|
||||
}
|
19
e2e/ui-tests-app/app/action-bar/font-icons-page.xml
Normal file
19
e2e/ui-tests-app/app/action-bar/font-icons-page.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<Page>
|
||||
<Page.actionBar>
|
||||
<ActionBar>
|
||||
<ActionBar.actionItems>
|
||||
<!-- font family + font size + color -->
|
||||
<ActionItem icon="font://" class="font-awesome font-size color" tap="navigate"/>
|
||||
<!-- default font + valid char code -->
|
||||
<ActionItem icon="font://" tap="navigate"/>
|
||||
<!-- font family + invalid char code -->
|
||||
<ActionItem icon="font://" class="font-awesome font-size" tap="navigate"/>
|
||||
</ActionBar.actionItems>
|
||||
</ActionBar>
|
||||
</Page.actionBar>
|
||||
|
||||
<StackLayout>
|
||||
<Button text="go to cleared page" tap="navigate"/>
|
||||
<Button text="undefined" tap="onChangeRenderingMode"/>
|
||||
</StackLayout>
|
||||
</Page>
|
@ -23,6 +23,7 @@ export function loadExamples() {
|
||||
examples.set("actTransparentBgCss", "action-bar/transparent-bg-css-page");
|
||||
examples.set("modalHiddenActBar", "action-bar/modal-test-hidden-action-bar-page");
|
||||
examples.set("modalShownActBar", "action-bar/modal-test-with-action-bar-page");
|
||||
examples.set("font-icons", "action-bar/font-icons-page");
|
||||
examples.set("flat", "action-bar/flat-page");
|
||||
examples.set("flat-tab", "action-bar/flat-tab-page");
|
||||
examples.set("flat-tab-opaque-bar", "action-bar/flat-tab-opaque-bar-page");
|
||||
|
11
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
||||
.font-awesome {
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
|
||||
.font-size {
|
||||
font-size: 36;
|
||||
}
|
||||
|
||||
.color {
|
||||
color: blue;
|
||||
}
|
34
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml
Normal file
34
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<Page class="page">
|
||||
|
||||
<ActionBar title="BottomNavigation font icons" icon="" class="action-bar">
|
||||
</ActionBar>
|
||||
|
||||
<BottomNavigation class="font-awesome"> <!-- TODO: The font-awesome class here should be removed -->
|
||||
<TabStrip>
|
||||
<!-- font family + font size + color -->
|
||||
<TabStripItem title="First" iconSource="font://" class="special font-awesome font-size color"></TabStripItem>
|
||||
<!-- default font + valid char code -->
|
||||
<TabStripItem title="Second" iconSource="font://"></TabStripItem>
|
||||
<!-- font family + invalid char code -->
|
||||
<TabStripItem title="Third" iconSource="font://" class="font-awesome font-size"></TabStripItem>
|
||||
</TabStrip>
|
||||
|
||||
<TabContentItem class="special">
|
||||
<GridLayout>
|
||||
<Label text="First View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
|
||||
<TabContentItem>
|
||||
<GridLayout>
|
||||
<Label text="Second View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
|
||||
<TabContentItem>
|
||||
<GridLayout>
|
||||
<Label text="Third View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
</BottomNavigation>
|
||||
</Page>
|
@ -20,6 +20,7 @@ export function loadExamples() {
|
||||
examples.set("icon-title-placement", "bottom-navigation/icon-title-placement-page");
|
||||
examples.set("icon-change", "bottom-navigation/icon-change-page");
|
||||
examples.set("binding", "bottom-navigation/binding-page");
|
||||
examples.set("font-icons", "bottom-navigation/font-icons-page");
|
||||
|
||||
return examples;
|
||||
}
|
||||
|
11
e2e/ui-tests-app/app/image-view/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/image-view/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
||||
.font-awesome {
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
|
||||
.font-size {
|
||||
font-size: 96;
|
||||
}
|
||||
|
||||
.color {
|
||||
color: blue;
|
||||
}
|
16
e2e/ui-tests-app/app/image-view/font-icons-page.xml
Normal file
16
e2e/ui-tests-app/app/image-view/font-icons-page.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<Page navigatingTo="navigatingTo">
|
||||
<GridLayout rows="*, *, *" columns="*, *" height="200">
|
||||
<!-- font family only -->
|
||||
<Image row="0" col="0" src="font://" class="font-awesome"/>
|
||||
<!-- font family + font size -->
|
||||
<Image row="0" col="1" src="font://" class="font-awesome font-size"/>
|
||||
<!-- font family + color -->
|
||||
<Image row="1" col="0" src="font://" class="font-awesome color"/>
|
||||
<!-- font family + font size + color -->
|
||||
<Image row="1" col="1" src="font://" class="font-awesome font-size color"/>
|
||||
<!-- default font + valid char code -->
|
||||
<Image row="2" col="0" src="font://" />
|
||||
<!-- font family + invalid char code -->
|
||||
<Image row="2" col="1" src="font://" class="font-awesome"/>
|
||||
</GridLayout>
|
||||
</Page>
|
@ -17,6 +17,7 @@ export function loadExamples() {
|
||||
examples.set("stretch-modes", "image-view/stretch-modes-page");
|
||||
examples.set("missing-image", "image-view/missing-image-page");
|
||||
examples.set("image-asset", "image-view/image-asset/image-asset-page");
|
||||
examples.set("font-icons", "image-view/font-icons-page");
|
||||
|
||||
return examples;
|
||||
}
|
||||
|
11
e2e/ui-tests-app/app/tabs/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/tabs/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
||||
.font-awesome {
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
|
||||
.font-size {
|
||||
font-size: 36;
|
||||
}
|
||||
|
||||
.color {
|
||||
color: blue;
|
||||
}
|
34
e2e/ui-tests-app/app/tabs/font-icons-page.xml
Normal file
34
e2e/ui-tests-app/app/tabs/font-icons-page.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<Page class="page">
|
||||
|
||||
<ActionBar title="Tabs font icons" icon="" class="action-bar">
|
||||
</ActionBar>
|
||||
|
||||
<Tabs class="font-awesome"> <!-- TODO: The font-awesome class here should be removed -->
|
||||
<TabStrip>
|
||||
<!-- font family + font size + color -->
|
||||
<TabStripItem title="First" iconSource="font://" class="special font-awesome font-size color"></TabStripItem>
|
||||
<!-- default font + valid char code -->
|
||||
<TabStripItem title="Second" iconSource="font://"></TabStripItem>
|
||||
<!-- font family + invalid char code -->
|
||||
<TabStripItem title="Third" iconSource="font://" class="font-awesome font-size"></TabStripItem>
|
||||
</TabStrip>
|
||||
|
||||
<TabContentItem class="special">
|
||||
<GridLayout>
|
||||
<Label text="First View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
|
||||
<TabContentItem>
|
||||
<GridLayout>
|
||||
<Label text="Second View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
|
||||
<TabContentItem>
|
||||
<GridLayout>
|
||||
<Label text="Third View" />
|
||||
</GridLayout>
|
||||
</TabContentItem>
|
||||
</Tabs>
|
||||
</Page>
|
@ -26,6 +26,7 @@ export function loadExamples() {
|
||||
examples.set("strip-items", "tabs/tab-strip-items-page");
|
||||
examples.set("tabs-position", "tabs/tabs-position-page");
|
||||
examples.set("tabs-binding", "tabs/tabs-binding-page");
|
||||
examples.set("font-icons", "tabs/font-icons-page");
|
||||
|
||||
return examples;
|
||||
}
|
||||
|
BIN
tests/app/font/FontAwesome.ttf
Normal file
BIN
tests/app/font/FontAwesome.ttf
Normal file
Binary file not shown.
@ -3,6 +3,8 @@ import * as imageAssetModule from "tns-core-modules/image-asset";
|
||||
import * as fs from "tns-core-modules/file-system";
|
||||
import * as app from "tns-core-modules/application";
|
||||
import * as TKUnit from "../tk-unit";
|
||||
import { Font } from "tns-core-modules/ui/styling/font";
|
||||
import { Color } from "tns-core-modules/color";
|
||||
|
||||
const imagePath = "~/assets/logo.png";
|
||||
const splashscreenPath = "~/assets/splashscreen.png";
|
||||
@ -285,3 +287,12 @@ export function testLoadFromBase64Encode_PNG() {
|
||||
TKUnit.assertEqual(img.width, 4, "img.width");
|
||||
TKUnit.assertEqual(img.height, 4, "img.height");
|
||||
}
|
||||
|
||||
export function testLoadFromFontIconCode() {
|
||||
let img: imageSource.ImageSource;
|
||||
img = imageSource.fromFontIconCode("F10B", Font.default.withFontFamily("FontAwesome"), new Color("red"));
|
||||
|
||||
TKUnit.assert(img !== null, "Actual: " + img);
|
||||
TKUnit.assert(img.width !== null, "img.width");
|
||||
TKUnit.assert(img.height !== null, "img.width");
|
||||
}
|
||||
|
@ -136,6 +136,14 @@ export const test_SettingImageSrcToDataURI_async = function (done) {
|
||||
runImageTestAsync(image, image.src, done);
|
||||
};
|
||||
|
||||
export const test_SettingImageSrcToFontIconCode_sync = function () {
|
||||
const image = new ImageModule.Image();
|
||||
image.style.fontFamily = "FontAwesome";
|
||||
image.src = "font://";
|
||||
|
||||
runImageTestSync(image, image.src);
|
||||
};
|
||||
|
||||
export function test_imageSourceNotResetAfterCreateUI() {
|
||||
let image = new ImageModule.Image();
|
||||
let imageSource = ImageSourceModule.fromResource("splashscreen");
|
||||
|
@ -5,8 +5,10 @@ import * as httpModule from "../http";
|
||||
|
||||
// Types.
|
||||
import { path as fsPath, knownFolders } from "../file-system";
|
||||
import { isFileOrResourcePath, RESOURCE_PREFIX } from "../utils/utils";
|
||||
import { isFileOrResourcePath, RESOURCE_PREFIX, layout } from "../utils/utils";
|
||||
import { getNativeApplication } from "../application";
|
||||
import { Font } from "../ui/styling/font";
|
||||
import { Color } from "../color";
|
||||
|
||||
export { isFileOrResourcePath };
|
||||
|
||||
@ -140,6 +142,43 @@ export class ImageSource implements ImageSourceDefinition {
|
||||
});
|
||||
}
|
||||
|
||||
public loadFromFontIconCode(source: string, font: Font, color: Color): boolean {
|
||||
const paint = new android.graphics.Paint();
|
||||
paint.setTypeface(font.getAndroidTypeface());
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
if (color) {
|
||||
paint.setColor(color.android);
|
||||
}
|
||||
|
||||
let fontSize = layout.toDevicePixels(font.fontSize);
|
||||
if (!fontSize) {
|
||||
// TODO: Consider making 36 font size as default for optimal look on TabView and ActionBar
|
||||
fontSize = paint.getTextSize();
|
||||
}
|
||||
|
||||
const density = layout.getDisplayDensity();
|
||||
const scaledFontSize = fontSize * density;
|
||||
paint.setTextSize(scaledFontSize);
|
||||
|
||||
const textBounds = new android.graphics.Rect();
|
||||
paint.getTextBounds(source, 0, source.length, textBounds);
|
||||
|
||||
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);
|
||||
|
||||
this.android = bitmap;
|
||||
|
||||
return this.android != null;
|
||||
}
|
||||
|
||||
public setNativeSource(source: any): void {
|
||||
if (source && !(source instanceof android.graphics.Bitmap)) {
|
||||
throw new Error("The method setNativeSource() expects android.graphics.Bitmap instance.");
|
||||
@ -241,6 +280,12 @@ export function fromData(data: any): ImageSource {
|
||||
return image.loadFromData(data) ? image : null;
|
||||
}
|
||||
|
||||
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource {
|
||||
const image = new ImageSource();
|
||||
|
||||
return image.loadFromFontIconCode(source, font, color) ? image : null;
|
||||
}
|
||||
|
||||
export function fromBase64(source: string): ImageSource {
|
||||
const image = new ImageSource();
|
||||
|
||||
|
18
tns-core-modules/image-source/image-source.d.ts
vendored
18
tns-core-modules/image-source/image-source.d.ts
vendored
@ -4,6 +4,8 @@
|
||||
*/ /** */
|
||||
|
||||
import * as imageAssetModule from "../image-asset";
|
||||
import { Font } from "../ui/styling/font";
|
||||
import { Color } from "../color";
|
||||
/**
|
||||
* Encapsulates the common abstraction behind a platform specific object (typically a Bitmap) that is used as a source for images.
|
||||
*/
|
||||
@ -87,6 +89,14 @@ export class ImageSource {
|
||||
*/
|
||||
fromBase64(source: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Loads this instance from the specified font icon code.
|
||||
* @param source The hex font icon code string
|
||||
* @param font The font for the corresponding font icon code
|
||||
* @param color The color of the generated icon image
|
||||
*/
|
||||
loadFromFontIconCode(source: string, font: Font, color: Color): boolean;
|
||||
|
||||
/**
|
||||
* Sets the provided native source object (typically a Bitmap or a UIImage).
|
||||
* This will update either the android or ios properties, depending on the target os.
|
||||
@ -147,6 +157,14 @@ export function fromBase64(source: string): ImageSource;
|
||||
*/
|
||||
export function fromNativeSource(source: any): ImageSource;
|
||||
|
||||
/**
|
||||
* Creates a new ImageSource instance and loads it from the specified font icon code.
|
||||
* @param source The hex font icon code string
|
||||
* @param font The font for the corresponding font icon code
|
||||
* @param color The color of the generated icon image
|
||||
*/
|
||||
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource;
|
||||
|
||||
/**
|
||||
* Downloads the image from the provided Url and creates a new ImageSource instance from it.
|
||||
* @param url The link to the remote image object. This operation will download and decode the image.
|
||||
|
@ -2,10 +2,12 @@
|
||||
import { ImageSource as ImageSourceDefinition } from ".";
|
||||
import { ImageAsset } from "../image-asset";
|
||||
import * as httpModule from "../http";
|
||||
import { Font } from "../ui/styling/font";
|
||||
import { Color } from "../color";
|
||||
|
||||
// Types.
|
||||
import { path as fsPath, knownFolders } from "../file-system";
|
||||
import { isFileOrResourcePath, RESOURCE_PREFIX } from "../utils/utils";
|
||||
import { isFileOrResourcePath, RESOURCE_PREFIX, layout } from "../utils/utils";
|
||||
|
||||
export { isFileOrResourcePath };
|
||||
|
||||
@ -121,6 +123,37 @@ export class ImageSource implements ImageSourceDefinition {
|
||||
});
|
||||
}
|
||||
|
||||
public loadFromFontIconCode(source: string, font: Font, color: Color): boolean {
|
||||
let fontSize = layout.toDevicePixels(font.fontSize);
|
||||
if (!fontSize) {
|
||||
// TODO: Consider making 36 font size as default for optimal look on TabView and ActionBar
|
||||
fontSize = UIFont.labelFontSize;
|
||||
}
|
||||
|
||||
const density = layout.getDisplayDensity();
|
||||
const scaledFontSize = fontSize * density;
|
||||
|
||||
const attributes = {
|
||||
[NSFontAttributeName]: font.getUIFont(UIFont.systemFontOfSize(scaledFontSize))
|
||||
};
|
||||
|
||||
if (color) {
|
||||
attributes[NSForegroundColorAttributeName] = color.ios;
|
||||
}
|
||||
|
||||
const attributedString = NSAttributedString.alloc().initWithStringAttributes(source, <NSDictionary<string, any>>attributes);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(attributedString.size(), false, 0.0);
|
||||
attributedString.drawAtPoint(CGPointMake(0, 0));
|
||||
|
||||
const iconImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
this.ios = iconImage;
|
||||
|
||||
return this.ios != null;
|
||||
}
|
||||
|
||||
public setNativeSource(source: any): void {
|
||||
if (source && !(source instanceof UIImage)) {
|
||||
throw new Error("The method setNativeSource() expects UIImage instance.");
|
||||
@ -231,6 +264,12 @@ export function fromFile(path: string): ImageSource {
|
||||
return image.loadFromFile(path) ? image : null;
|
||||
}
|
||||
|
||||
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource {
|
||||
const image = new ImageSource();
|
||||
|
||||
return image.loadFromFontIconCode(source, font, color) ? image : null;
|
||||
}
|
||||
|
||||
export function fromData(data: any): ImageSource {
|
||||
const image = new ImageSource();
|
||||
|
||||
|
@ -4,8 +4,8 @@ import {
|
||||
View, layout, colorProperty, flatProperty,
|
||||
Color, traceMissingIcon
|
||||
} from "./action-bar-common";
|
||||
import { RESOURCE_PREFIX } from "../../utils/utils";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { RESOURCE_PREFIX, isFontIconURI } from "../../utils/utils";
|
||||
import { fromFileOrResource, fromFontIconCode } from "../../image-source";
|
||||
import * as application from "../../application";
|
||||
|
||||
export * from "./action-bar-common";
|
||||
@ -311,9 +311,21 @@ export class ActionBar extends ActionBarBase {
|
||||
}
|
||||
}
|
||||
else if (item.icon) {
|
||||
let drawableOrId = getDrawableOrResourceId(item.icon, appResources);
|
||||
if (drawableOrId) {
|
||||
menuItem.setIcon(drawableOrId);
|
||||
if (isFontIconURI(item.icon)) {
|
||||
const fontIconCode = item.icon.split("//")[1];
|
||||
const font = item.style.fontInternal;
|
||||
const color = item.style.color;
|
||||
const is = fromFontIconCode(fontIconCode, font, color);
|
||||
|
||||
if (is && is.android) {
|
||||
const drawable = new android.graphics.drawable.BitmapDrawable(appResources, is.android);
|
||||
menuItem.setIcon(drawable);
|
||||
}
|
||||
} else {
|
||||
let drawableOrId = getDrawableOrResourceId(item.icon, appResources);
|
||||
if (drawableOrId) {
|
||||
menuItem.setIcon(drawableOrId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ import {
|
||||
colorProperty, backgroundColorProperty,
|
||||
backgroundInternalProperty, flatProperty, iosIconRenderingModeProperty,
|
||||
layout, Color, traceMissingIcon } from "./action-bar-common";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { ios as iosUtils } from "../../utils/utils";
|
||||
import { fromFileOrResource, fromFontIconCode } from "../../image-source";
|
||||
import { ios as iosUtils, isFontIconURI } from "../../utils/utils";
|
||||
|
||||
export * from "./action-bar-common";
|
||||
|
||||
@ -255,7 +255,23 @@ export class ActionBar extends ActionBarBase {
|
||||
|
||||
barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(id, tapHandler, "tap");
|
||||
} else if (item.icon) {
|
||||
const img = loadActionIconFromFileOrResource(item.icon);
|
||||
let img = null;
|
||||
|
||||
if (isFontIconURI(item.icon)) {
|
||||
const fontIconCode = item.icon.split("//")[1];
|
||||
const font = item.style.fontInternal;
|
||||
const color = item.style.color;
|
||||
const is = fromFontIconCode(fontIconCode, font, color);
|
||||
|
||||
if (is && is.ios) {
|
||||
img = is.ios;
|
||||
} else {
|
||||
traceMissingIcon(item.icon);
|
||||
}
|
||||
} else {
|
||||
img = loadActionIconFromFileOrResource(item.icon);
|
||||
}
|
||||
|
||||
const image = img.imageWithRenderingMode(this._getIconRenderingMode());
|
||||
barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(image, UIBarButtonItemStyle.Plain, tapHandler, "tap");
|
||||
} else {
|
||||
|
@ -10,8 +10,8 @@ import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
import { CSSType, Color } from "../core/view";
|
||||
import { Frame, View } from "../frame";
|
||||
import { RESOURCE_PREFIX, ad, layout } from "../../utils/utils";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
|
||||
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||
import * as application from "../../application";
|
||||
|
||||
// TODO: Impl trace
|
||||
@ -177,7 +177,16 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets
|
||||
// traceMissingIcon(iconSource);
|
||||
}
|
||||
} else {
|
||||
const is = fromFileOrResource(tabStripItem.iconSource);
|
||||
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);
|
||||
} else {
|
||||
is = fromFileOrResource(tabStripItem.iconSource);
|
||||
}
|
||||
|
||||
if (is) {
|
||||
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
|
||||
// tslint:disable-next-line:deprecation
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Types
|
||||
// Types
|
||||
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
||||
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
||||
import { TextTransform } from "../text-base";
|
||||
@ -9,10 +9,10 @@ import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
import { Frame } from "../frame";
|
||||
import { ios as iosView, View, CSSType } from "../core/view";
|
||||
import { ios as iosUtils, layout } from "../../utils/utils";
|
||||
import { ios as iosUtils, layout, isFontIconURI } from "../../utils/utils";
|
||||
import { device } from "../../platform";
|
||||
import { Color } from "../../color";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||
// TODO:
|
||||
// import { profile } from "../../profiling";
|
||||
|
||||
@ -526,9 +526,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
let image: UIImage;
|
||||
let title: string;
|
||||
|
||||
// Image and Label children of TabStripItem
|
||||
// take priority over its `iconSource` and `title` properties
|
||||
image = item.image ? this._getIcon(item.image.src) : this._getIcon(item.iconSource);
|
||||
image = this._getIcon(item);
|
||||
title = item.label ? item.label.text : item.title;
|
||||
|
||||
const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index);
|
||||
@ -540,14 +538,26 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
return UIImageRenderingMode.AlwaysOriginal;
|
||||
}
|
||||
|
||||
public _getIcon(iconSource: string): UIImage {
|
||||
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;
|
||||
if (!iconSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let image: UIImage = this._iconsCache[iconSource];
|
||||
if (!image) {
|
||||
const is = fromFileOrResource(iconSource);
|
||||
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);
|
||||
}
|
||||
|
||||
if (is && is.ios) {
|
||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||
this._iconsCache[iconSource] = originalRenderedImage;
|
||||
|
@ -2,9 +2,9 @@ import { Image as ImageDefinition, Stretch } from ".";
|
||||
import { View, Property, InheritedCssProperty, Length, Style, Color, isIOS, booleanConverter, CSSType, traceEnabled, traceWrite, traceCategories } from "../core/view";
|
||||
import { ImageAsset } from "../../image-asset";
|
||||
import { ImageSource, fromAsset, fromNativeSource, fromUrl } from "../../image-source";
|
||||
import { isDataURI, isFileOrResourcePath, RESOURCE_PREFIX } from "../../utils/utils";
|
||||
import { isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX } from "../../utils/utils";
|
||||
export * from "../core/view";
|
||||
export { ImageSource, ImageAsset, fromAsset, fromNativeSource, fromUrl, isDataURI, isFileOrResourcePath, RESOURCE_PREFIX };
|
||||
export { ImageSource, ImageAsset, fromAsset, fromNativeSource, fromUrl, isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX };
|
||||
|
||||
@CSSType("Image")
|
||||
export abstract class ImageBase extends View implements ImageDefinition {
|
||||
@ -46,7 +46,16 @@ export abstract class ImageBase extends View implements ImageDefinition {
|
||||
this.isLoading = false;
|
||||
};
|
||||
|
||||
if (isDataURI(value)) {
|
||||
if (isFontIconURI(value)) {
|
||||
const fontIconCode = value.split("//")[1];
|
||||
if (fontIconCode !== undefined) {
|
||||
// support sync mode only
|
||||
const font = this.style.fontInternal;
|
||||
const color = this.style.color;
|
||||
source.loadFromFontIconCode(fontIconCode, font, color);
|
||||
imageLoaded();
|
||||
}
|
||||
} else if (isDataURI(value)) {
|
||||
const base64Data = value.split(",")[1];
|
||||
if (base64Data !== undefined) {
|
||||
if (sync) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {
|
||||
ImageSource, ImageAsset, ImageBase, stretchProperty, imageSourceProperty, srcProperty, tintColorProperty, Color,
|
||||
isDataURI, isFileOrResourcePath, RESOURCE_PREFIX, Length
|
||||
isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX, Length
|
||||
} from "./image-common";
|
||||
import { knownFolders } from "../../file-system";
|
||||
|
||||
@ -106,7 +106,7 @@ export class Image extends ImageBase {
|
||||
value = value.trim();
|
||||
this.isLoading = true;
|
||||
|
||||
if (isDataURI(value)) {
|
||||
if (isFontIconURI(value) || isDataURI(value)) {
|
||||
// TODO: Check with runtime what should we do in case of base64 string.
|
||||
super._createImageSourceFromSrc(value);
|
||||
} else if (isFileOrResourcePath(value)) {
|
||||
|
@ -11,8 +11,8 @@ import { Font } from "../styling/font";
|
||||
import { getTransformedText } from "../text-base";
|
||||
import { Frame } from "../frame";
|
||||
import { Color } from "../core/view";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { RESOURCE_PREFIX, ad, layout } from "../../utils/utils";
|
||||
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
|
||||
import * as application from "../../application";
|
||||
|
||||
export * from "./tabs-common";
|
||||
@ -304,7 +304,16 @@ function createTabItemSpec(item: TabStripItem): org.nativescript.widgets.TabItem
|
||||
// traceMissingIcon(iconSource);
|
||||
}
|
||||
} else {
|
||||
const is = fromFileOrResource(iconSource);
|
||||
let is = new ImageSource();
|
||||
if (isFontIconURI(item.iconSource)) {
|
||||
const fontIconCode = item.iconSource.split("//")[1];
|
||||
const font = item.style.fontInternal;
|
||||
const color = item.style.color;
|
||||
is = fromFontIconCode(fontIconCode, font, color);
|
||||
} else {
|
||||
is = fromFileOrResource(item.iconSource);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -11,9 +11,9 @@ import { Font } from "../styling/font";
|
||||
import { Frame } from "../frame";
|
||||
import { ios as iosView, View } from "../core/view";
|
||||
import { Color } from "../../color";
|
||||
import { /*ios as iosUtils,*/ layout } from "../../utils/utils";
|
||||
import { /*ios as iosUtils,*/ layout, isFontIconURI } from "../../utils/utils";
|
||||
// import { device } from "../../platform";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||
|
||||
// TODO
|
||||
// import { profile } from "../../profiling";
|
||||
@ -883,9 +883,7 @@ export class Tabs extends TabsBase {
|
||||
let image: UIImage;
|
||||
let title: string;
|
||||
|
||||
// Image and Label children of TabStripItem
|
||||
// take priority over its `iconSource` and `title` properties
|
||||
image = item.image ? this._getIcon(item.image.src) : this._getIcon(item.iconSource);
|
||||
image = this._getIcon(item);
|
||||
title = item.label ? item.label.text : item.title;
|
||||
|
||||
if (!this.tabStrip._hasImage) {
|
||||
@ -918,14 +916,26 @@ export class Tabs extends TabsBase {
|
||||
return UIImageRenderingMode.AlwaysOriginal;
|
||||
}
|
||||
|
||||
public _getIcon(iconSource: string): UIImage {
|
||||
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;
|
||||
if (!iconSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let image: UIImage = this._iconsCache[iconSource];
|
||||
if (!image) {
|
||||
const is = fromFileOrResource(iconSource);
|
||||
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);
|
||||
}
|
||||
|
||||
if (is && is.ios) {
|
||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||
this._iconsCache[iconSource] = originalRenderedImage;
|
||||
|
@ -113,6 +113,16 @@ export function isFileOrResourcePath(path: string): boolean {
|
||||
path.indexOf(RESOURCE_PREFIX) === 0; // resource
|
||||
}
|
||||
|
||||
export function isFontIconURI(uri: string): boolean {
|
||||
if (!types.isString(uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstSegment = uri.trim().split("//")[0];
|
||||
|
||||
return firstSegment && firstSegment.indexOf("font:") === 0;
|
||||
}
|
||||
|
||||
export function isDataURI(uri: string): boolean {
|
||||
if (!types.isString(uri)) {
|
||||
return false;
|
||||
|
6
tns-core-modules/utils/utils.d.ts
vendored
6
tns-core-modules/utils/utils.d.ts
vendored
@ -278,6 +278,12 @@ export function executeOnMainThread(func: Function);
|
||||
*/
|
||||
export function mainThreadify(func: Function): (...args: any[]) => void
|
||||
|
||||
/**
|
||||
* Returns true if the specified URI is a font icon URI like "fontIcon://".
|
||||
* @param uri The URI.
|
||||
*/
|
||||
export function isFontIconURI(uri: string): boolean
|
||||
|
||||
/**
|
||||
* Returns true if the specified path points to a resource or local file.
|
||||
* @param path The path.
|
||||
|
Reference in New Issue
Block a user