Skip to content

Commit c003061

Browse files
committed
fix: ios and android fix
1 parent 094eb26 commit c003061

File tree

2 files changed

+194
-88
lines changed

2 files changed

+194
-88
lines changed

Diff for: src/label.android.ts

+165-68
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,163 @@
1-
import {
2-
htmlProperty,
3-
LabelBase,
4-
lineBreakProperty,
5-
maxLinesProperty
6-
} from './label-common';
1+
import { htmlProperty, LabelBase, lineBreakProperty, maxLinesProperty } from './label-common';
72
// import { backgroundColorProperty } from 'tns-core-modules/ui/page/page';
8-
import {
9-
TextTransform,
10-
WhiteSpace,
11-
whiteSpaceProperty
12-
} from 'tns-core-modules/ui/text-base/text-base';
3+
import { TextTransform, WhiteSpace, whiteSpaceProperty } from 'tns-core-modules/ui/text-base/text-base';
134
import { Font } from 'tns-core-modules/ui/styling/font';
5+
Font.prototype.getAndroidTypeface = function() {
6+
if (!this._typeface) {
7+
this._typeface = createTypeface(this);
8+
}
9+
return this._typeface;
10+
};
1411
// import { Span } from 'tns-core-modules/text/span';
1512

1613
export * from './label-common';
1714

15+
let _useAndroidX;
16+
function useAndroidX() {
17+
if (_useAndroidX === undefined) {
18+
_useAndroidX = !!(global as any).androidx && !!(global as any).androidx.appcompat;
19+
}
20+
return _useAndroidX;
21+
}
22+
let _ContentPackageName: typeof android.support.v4.content;
23+
function ContentPackageName() {
24+
if (_ContentPackageName === undefined) {
25+
_ContentPackageName = useAndroidX() ? (global as any).androidx.core.content : android.support.v4.content;
26+
}
27+
return _ContentPackageName;
28+
}
29+
import * as application from 'tns-core-modules/application';
30+
import * as fs from 'tns-core-modules/file-system';
31+
import { categories as traceCategories, isEnabled as traceEnabled, messageType as traceMessageType, write as traceWrite } from 'tns-core-modules/trace';
32+
import { Font as FontBase, FontWeight, genericFontFamilies, parseFontFamily } from 'tns-core-modules/ui/styling/font-common';
33+
let appAssets: android.content.res.AssetManager;
34+
const typefaceCache = new Map<string, android.graphics.Typeface>();
35+
const FONTS_BASE_PATH = '/fonts/';
36+
function loadFontFromFile(fontFamily: string): android.graphics.Typeface {
37+
if (fontFamily.startsWith('res/')) {
38+
let result = typefaceCache.get(fontFamily);
39+
if (!result) {
40+
const context = application.android.context;
41+
const fontID = context.getResources().getIdentifier(fontFamily.slice(4), 'font', context.getPackageName());
42+
result = ContentPackageName().res.ResourcesCompat.getFont(context, fontID);
43+
if (result) {
44+
typefaceCache.set(fontFamily, result);
45+
}
46+
return result;
47+
}
48+
}
49+
appAssets = appAssets || application.android.context.getAssets();
50+
if (!appAssets) {
51+
return null;
52+
}
53+
54+
let result = typefaceCache.get(fontFamily);
55+
// Check for undefined explicitly as null mean we tried to load the font, but failed.
56+
if (result === undefined) {
57+
result = null;
58+
59+
let fontAssetPath: string;
60+
const basePath = fs.path.join(fs.knownFolders.currentApp().path, 'fonts', fontFamily);
61+
if (fs.File.exists(basePath + '.ttf')) {
62+
fontAssetPath = FONTS_BASE_PATH + fontFamily + '.ttf';
63+
} else if (fs.File.exists(basePath + '.otf')) {
64+
fontAssetPath = FONTS_BASE_PATH + fontFamily + '.otf';
65+
} else {
66+
if (traceEnabled()) {
67+
traceWrite('Could not find font file for ' + fontFamily, traceCategories.Error, traceMessageType.error);
68+
}
69+
}
70+
71+
if (fontAssetPath) {
72+
try {
73+
fontAssetPath = fs.path.join(fs.knownFolders.currentApp().path, fontAssetPath);
74+
result = android.graphics.Typeface.createFromFile(fontAssetPath);
75+
} catch (e) {
76+
if (traceEnabled()) {
77+
traceWrite('Error loading font asset: ' + fontAssetPath, traceCategories.Error, traceMessageType.error);
78+
}
79+
}
80+
}
81+
typefaceCache.set(fontFamily, result);
82+
}
83+
84+
return result;
85+
}
86+
87+
function createTypeface(font: Font): android.graphics.Typeface {
88+
let fontStyle = 0;
89+
if (font.isBold) {
90+
fontStyle |= android.graphics.Typeface.BOLD;
91+
}
92+
if (font.isItalic) {
93+
fontStyle |= android.graphics.Typeface.ITALIC;
94+
}
95+
96+
// http://stackoverflow.com/questions/19691530/valid-values-for-androidfontfamily-and-what-they-map-to
97+
const fonts = parseFontFamily(font.fontFamily);
98+
let result = null;
99+
for (let i = 0; i < fonts.length; i++) {
100+
switch (fonts[i].toLowerCase()) {
101+
case genericFontFamilies.serif:
102+
result = android.graphics.Typeface.create('serif' + getFontWeightSuffix(font.fontWeight), fontStyle);
103+
break;
104+
105+
case genericFontFamilies.sansSerif:
106+
case genericFontFamilies.system:
107+
result = android.graphics.Typeface.create('sans-serif' + getFontWeightSuffix(font.fontWeight), fontStyle);
108+
break;
109+
110+
case genericFontFamilies.monospace:
111+
result = android.graphics.Typeface.create('monospace' + getFontWeightSuffix(font.fontWeight), fontStyle);
112+
break;
113+
114+
default:
115+
result = loadFontFromFile(fonts[i]);
116+
if (result && fontStyle) {
117+
result = android.graphics.Typeface.create(result, fontStyle);
118+
}
119+
break;
120+
}
121+
122+
if (result) {
123+
// Found the font!
124+
break;
125+
}
126+
}
127+
128+
if (!result) {
129+
result = android.graphics.Typeface.create('sans-serif' + getFontWeightSuffix(font.fontWeight), fontStyle);
130+
}
131+
132+
return result;
133+
}
134+
135+
function getFontWeightSuffix(fontWeight: FontWeight): string {
136+
switch (fontWeight) {
137+
case FontWeight.THIN:
138+
return android.os.Build.VERSION.SDK_INT >= 16 ? '-thin' : '';
139+
case FontWeight.EXTRA_LIGHT:
140+
case FontWeight.LIGHT:
141+
return android.os.Build.VERSION.SDK_INT >= 16 ? '-light' : '';
142+
case FontWeight.NORMAL:
143+
case '400':
144+
case undefined:
145+
case null:
146+
return '';
147+
case FontWeight.MEDIUM:
148+
case FontWeight.SEMI_BOLD:
149+
return android.os.Build.VERSION.SDK_INT >= 21 ? '-medium' : '';
150+
case FontWeight.BOLD:
151+
case '700':
152+
case FontWeight.EXTRA_BOLD:
153+
return '';
154+
case FontWeight.BLACK:
155+
return android.os.Build.VERSION.SDK_INT >= 21 ? '-black' : '';
156+
default:
157+
throw new Error(`Invalid font weight: "${fontWeight}"`);
158+
}
159+
}
160+
18161
export class Label extends LabelBase {
19162
nativeViewProtected: android.widget.TextView;
20163

@@ -28,9 +171,7 @@ export class Label extends LabelBase {
28171

29172
// This makes the html <a href...> work
30173
nativeView.setLinksClickable(false);
31-
nativeView.setMovementMethod(
32-
android.text.method.LinkMovementMethod.getInstance()
33-
);
174+
nativeView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
34175
}
35176

36177
public resetNativeView(): void {
@@ -51,9 +192,7 @@ export class Label extends LabelBase {
51192
}
52193
const nativeView = this.nativeViewProtected;
53194
nativeView.setAutoLinkMask(mask);
54-
const spannableStringBuilder = createSpannableStringBuilder(
55-
android.text.Html.fromHtml(value)
56-
);
195+
const spannableStringBuilder = createSpannableStringBuilder(android.text.Html.fromHtml(value));
57196
nativeView.setText(spannableStringBuilder as any);
58197

59198
// textProperty.nativeValueChange(this, value === null || value === undefined ? '' : value.toString());
@@ -79,27 +218,13 @@ export class Label extends LabelBase {
79218
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.START);
80219
break;
81220
case 'middle':
82-
nativeView.setEllipsize(
83-
android.text.TextUtils.TruncateAt.MIDDLE
84-
);
221+
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.MIDDLE);
85222
break;
86223
case 'none':
87224
nativeView.setEllipsize(null);
88225
break;
89226
}
90227
}
91-
[whiteSpaceProperty.setNative](value: WhiteSpace) {
92-
const nativeView = this.nativeTextViewProtected;
93-
switch (value) {
94-
case 'initial':
95-
case 'normal':
96-
nativeView.setEllipsize(null);
97-
break;
98-
case 'nowrap':
99-
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
100-
break;
101-
}
102-
}
103228
}
104229

105230
// function isBold(fontWeight: FontWeight): boolean {
@@ -117,10 +242,7 @@ function getCapitalizedString(str: string): string {
117242
return newWords.join(' ');
118243
}
119244

120-
export function getTransformedText(
121-
text: string,
122-
textTransform: TextTransform
123-
): string {
245+
export function getTransformedText(text: string, textTransform: TextTransform): string {
124246
switch (textTransform) {
125247
case 'uppercase':
126248
return text.toUpperCase();
@@ -134,47 +256,22 @@ export function getTransformedText(
134256
}
135257
}
136258

137-
function createSpannableStringBuilder(
138-
spannedString: android.text.Spanned
139-
): android.text.SpannableStringBuilder {
259+
function createSpannableStringBuilder(spannedString: android.text.Spanned): android.text.SpannableStringBuilder {
140260
if (!spannedString) {
141261
return null;
142262
}
143-
const builder = new android.text.SpannableStringBuilder(
144-
spannedString as any
145-
);
146-
const spans: native.Array<
147-
android.text.style.TypefaceSpan
148-
> = builder.getSpans(
149-
0,
150-
builder.length(),
151-
android.text.style.TypefaceSpan.class
152-
);
263+
const builder = new android.text.SpannableStringBuilder(spannedString as any);
264+
const spans: native.Array<android.text.style.TypefaceSpan> = builder.getSpans(0, builder.length(), android.text.style.TypefaceSpan.class);
153265
for (let index = 0; index < spans.length; index++) {
154266
const span = spans[index];
155267
const start = builder.getSpanStart(span);
156268
const end = builder.getSpanEnd(span);
157269
const fontFamily = span.getFamily();
158270
const style = fontFamily.split('-')[1] || builder.removeSpan(span);
159-
const font = new Font(
160-
fontFamily,
161-
0,
162-
style === 'italic' ? 'italic' : 'normal',
163-
style === 'bold' ? 'bold' : 'normal'
164-
);
165-
const typeface =
166-
font.getAndroidTypeface() ||
167-
android.graphics.Typeface.create(fontFamily, 0);
168-
const typefaceSpan: android.text.style.TypefaceSpan = new org.nativescript.widgets.CustomTypefaceSpan(
169-
fontFamily,
170-
typeface
171-
);
172-
builder.setSpan(
173-
typefaceSpan,
174-
start,
175-
end,
176-
android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
177-
);
271+
const font = new Font(fontFamily, 0, style === 'italic' ? 'italic' : 'normal', style === 'bold' ? 'bold' : 'normal');
272+
const typeface = font.getAndroidTypeface() || android.graphics.Typeface.create(fontFamily, 0);
273+
const typefaceSpan: android.text.style.TypefaceSpan = new org.nativescript.widgets.CustomTypefaceSpan(fontFamily, typeface);
274+
builder.setSpan(typefaceSpan, start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
178275
}
179276

180277
// const ssb = new android.text.SpannableStringBuilder();

Diff for: src/label.ios.ts

+29-20
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,31 @@ export class Label extends LabelBase {
124124
this.htmlText = null;
125125
} else {
126126
let htmlString = this.html;
127+
128+
let fontFamily,
129+
fontSize = UIFont.labelFontSize;
127130
if (!!this.style.fontInternal) {
128-
// console.log('fontInternal', this.style.fontInternal.fontFamily, this.style.fontInternal.fontSize);
129-
htmlString = `<span style="font-family: ${
130-
this.style.fontInternal.fontFamily[0] === "'" ? this.style.fontInternal.fontFamily.replace(/'/g, '') : this.style.fontInternal.fontFamily
131-
}}; font-size:${this.style.fontInternal.fontSize};">${htmlString}</span>`;
131+
if (!!this.style.fontInternal.fontFamily) {
132+
fontFamily = this.style.fontInternal.fontFamily[0] === "'" ? this.style.fontInternal.fontFamily.replace(/'/g, '') : this.style.fontInternal.fontFamily;
133+
} else {
134+
fontFamily = UIFont.systemFontOfSize(10).familyName;
135+
}
136+
if (this.style.fontInternal.fontSize) {
137+
fontSize = this.style.fontInternal.fontSize;
138+
}
132139
}
140+
console.log('span', fontFamily, fontSize);
141+
142+
htmlString = `<span style="font-family: ${fontFamily}}; font-size:${fontSize};">${htmlString}</span>`;
133143
const nsString = NSString.stringWithString(htmlString);
134-
// console.log('updateHTMLString1', htmlString);
144+
console.log('updateHTMLString1', htmlString);
135145
const nsData = nsString.dataUsingEncoding(NSUTF8StringEncoding);
136146
const options = {
137147
[DTDefaultTextAlignment]: kCTLeftTextAlignment,
138148
// [NSTextSizeMultiplierDocumentOption]: 1,
139149
// [DTIgnoreLinkStyleOption]: false,
140-
// [DTDefaultFontFamily] : [self defaultSystemFontFamily],
141-
// [NSFontAttributeName] : [self defaultSystemFontFamily],
150+
[DTDefaultFontFamily]: fontFamily,
151+
// [NSFontAttributeName]: fontFamily,
142152
[NSTextSizeMultiplierDocumentOption]: 17 / 12.0,
143153
[DTUseiOS6Attributes]: true,
144154
[DTDocumentPreserveTrailingSpaces]: true
@@ -304,19 +314,18 @@ export class Label extends LabelBase {
304314
break;
305315
}
306316
}
307-
[whiteSpaceProperty.setNative](value: WhiteSpace) {
308-
const nativeView = this.nativeTextViewProtected;
309-
console.log('whiteSpaceProperty', value);
310-
switch (value) {
311-
case 'initial':
312-
case 'normal':
313-
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
314-
break;
315-
case 'nowrap':
316-
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
317-
break;
318-
}
319-
}
317+
// [whiteSpaceProperty.setNative](value: WhiteSpace) {
318+
// const nativeView = this.nativeTextViewProtected;
319+
// switch (value) {
320+
// case 'initial':
321+
// case 'normal':
322+
// nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
323+
// break;
324+
// case 'nowrap':
325+
// nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
326+
// break;
327+
// }
328+
// }
320329
// [autoFontSizeProperty.getDefault](): boolean {
321330
// return this.nativeViewProtected.adjustsFontSizeToFitWidth;
322331
// }

0 commit comments

Comments
 (0)