Skip to content

Commit ba87f09

Browse files
committed
feat: support verticalAlignment
1 parent 1ba91aa commit ba87f09

File tree

4 files changed

+316
-72
lines changed

4 files changed

+316
-72
lines changed

Diff for: src/label-common.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { Label as HtmlViewDefinition } from './label';
2-
import { booleanConverter, CSSType } from 'tns-core-modules/ui/core/view';
1+
import { Label as HtmlViewDefinition, TextShadow } from './label';
2+
import { booleanConverter, Color, CSSType, dip } from 'tns-core-modules/ui/core/view';
33
import { Label as TNLabel } from 'tns-core-modules/ui/label/label';
44
import { Style } from 'tns-core-modules/ui/styling/style';
55
import { CssProperty, Property } from 'tns-core-modules/ui/core/properties';
6+
import { isIOS } from 'tns-core-modules/platform';
7+
import { layout } from 'tns-core-modules/utils/utils';
68

79
export const cssProperty = (target: Object, key: string | symbol) => {
810
// property getter
@@ -51,3 +53,27 @@ export const autoFontSizeProperty = new CssProperty<Style, boolean>({
5153
valueConverter: booleanConverter
5254
});
5355
autoFontSizeProperty.register(Style);
56+
57+
function parseDIPs(value: string): dip {
58+
if (value.indexOf('px') !== -1) {
59+
return layout.toDeviceIndependentPixels(parseFloat(value.replace('px', '').trim()));
60+
} else {
61+
return parseFloat(value.replace('dip', '').trim());
62+
}
63+
}
64+
65+
export const textShadowProperty = new CssProperty<Style, string | TextShadow>({
66+
name: 'textShadow',
67+
cssName: 'text-shadow',
68+
affectsLayout: isIOS,
69+
valueConverter: value => {
70+
const params = value.split(' ');
71+
return {
72+
offsetX: parseDIPs(params[0]),
73+
offsetY: parseDIPs(params[1]),
74+
blurRadius: parseDIPs(params[2]),
75+
color: new Color(params.slice(3).join(''))
76+
};
77+
}
78+
});
79+
textShadowProperty.register(Style);

Diff for: src/label.android.ts

+62-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { htmlProperty, LabelBase, lineBreakProperty, maxLinesProperty } from './label-common';
1+
import { htmlProperty, LabelBase, lineBreakProperty, maxLinesProperty, textShadowProperty } from './label-common';
22
// import { backgroundColorProperty } from 'tns-core-modules/ui/page/page';
3-
import { TextTransform, WhiteSpace, whiteSpaceProperty } from 'tns-core-modules/ui/text-base/text-base';
3+
import { TextTransform, VerticalAlignment, verticalAlignmentProperty, WhiteSpace, whiteSpaceProperty } from 'tns-core-modules/ui/text-base/text-base';
44
import { Font } from 'tns-core-modules/ui/styling/font';
5+
import { layout } from 'tns-core-modules/utils/utils';
6+
57
Font.prototype.getAndroidTypeface = function() {
68
if (!this._typeface) {
79
this._typeface = createTypeface(this);
@@ -19,17 +21,25 @@ function useAndroidX() {
1921
}
2022
return _useAndroidX;
2123
}
22-
let _ContentPackageName: typeof android.support.v4.content;
24+
let _HtmlCompat: typeof androidx.core.text.HtmlCompat;
25+
function HtmlCompat() {
26+
if (_HtmlCompat === undefined) {
27+
_HtmlCompat = useAndroidX() ? (global as any).androidx.core.text.HtmlCompat : android.text.Html;
28+
}
29+
return _HtmlCompat;
30+
}
31+
let _ContentPackageName: typeof androidx.core.content;
2332
function ContentPackageName() {
2433
if (_ContentPackageName === undefined) {
25-
_ContentPackageName = useAndroidX() ? (global as any).androidx.core.content : android.support.v4.content;
34+
_ContentPackageName = useAndroidX() ? (global as any).androidx.core.content : (android as any).support.v4.content;
2635
}
2736
return _ContentPackageName;
2837
}
2938
import * as application from 'tns-core-modules/application';
3039
import * as fs from 'tns-core-modules/file-system';
3140
import { categories as traceCategories, isEnabled as traceEnabled, messageType as traceMessageType, write as traceWrite } from 'tns-core-modules/trace';
3241
import { Font as FontBase, FontWeight, genericFontFamilies, parseFontFamily } from 'tns-core-modules/ui/styling/font-common';
42+
import { TextShadow } from './label';
3343
let appAssets: android.content.res.AssetManager;
3444
const typefaceCache = new Map<string, android.graphics.Typeface>();
3545
const FONTS_BASE_PATH = '/fonts/';
@@ -171,7 +181,8 @@ export class Label extends LabelBase {
171181

172182
// This makes the html <a href...> work
173183
nativeView.setLinksClickable(false);
174-
nativeView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
184+
nativeView.setMovementMethod(null);
185+
// nativeView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
175186
}
176187

177188
public resetNativeView(): void {
@@ -182,6 +193,7 @@ export class Label extends LabelBase {
182193
[htmlProperty.getDefault](): string {
183194
return '';
184195
}
196+
185197
[htmlProperty.setNative](value: string) {
186198
// If the data.newValue actually has a <a...> in it; we need to disable autolink mask
187199
// it internally disables the coloring, but then the <a> links won't work.. So to support both
@@ -192,7 +204,12 @@ export class Label extends LabelBase {
192204
}
193205
const nativeView = this.nativeViewProtected;
194206
nativeView.setAutoLinkMask(mask);
195-
const spannableStringBuilder = createSpannableStringBuilder(android.text.Html.fromHtml(value));
207+
let spannableStringBuilder: android.text.SpannableStringBuilder;
208+
if (useAndroidX()) {
209+
spannableStringBuilder = createSpannableStringBuilder(HtmlCompat().fromHtml(value, HtmlCompat().FROM_HTML_MODE_COMPACT));
210+
} else {
211+
spannableStringBuilder = createSpannableStringBuilder(android.text.Html.fromHtml(value));
212+
}
196213
nativeView.setText(spannableStringBuilder as any);
197214

198215
// textProperty.nativeValueChange(this, value === null || value === undefined ? '' : value.toString());
@@ -212,17 +229,56 @@ export class Label extends LabelBase {
212229
const nativeView = this.nativeTextViewProtected;
213230
switch (value) {
214231
case 'end':
232+
nativeView.setSingleLine(true);
215233
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
216234
break;
217235
case 'start':
236+
nativeView.setSingleLine(true);
218237
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.START);
219238
break;
220239
case 'middle':
240+
nativeView.setSingleLine(true);
221241
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.MIDDLE);
222242
break;
223243
case 'none':
244+
nativeView.setSingleLine(false);
245+
nativeView.setEllipsize(null);
246+
break;
247+
}
248+
}
249+
250+
[whiteSpaceProperty.setNative](value: WhiteSpace) {
251+
const nativeView = this.nativeTextViewProtected;
252+
switch (value) {
253+
case 'initial':
254+
case 'normal':
255+
nativeView.setSingleLine(false);
224256
nativeView.setEllipsize(null);
225257
break;
258+
case 'nowrap':
259+
nativeView.setSingleLine(true);
260+
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
261+
break;
262+
}
263+
}
264+
[textShadowProperty.setNative](value: TextShadow) {
265+
this.nativeViewProtected.setShadowLayer(layout.toDevicePixels(value.blurRadius), layout.toDevicePixels(value.offsetX), layout.toDevicePixels(value.offsetY), value.color.android);
266+
}
267+
268+
[verticalAlignmentProperty.setNative](value: VerticalAlignment) {
269+
const horizontalGravity = this.nativeTextViewProtected.getGravity() & android.view.Gravity.HORIZONTAL_GRAVITY_MASK;
270+
switch (value) {
271+
case 'stretch':
272+
case 'top':
273+
this.nativeTextViewProtected.setGravity(android.view.Gravity.TOP | horizontalGravity);
274+
break;
275+
case 'middle':
276+
this.nativeTextViewProtected.setGravity(android.view.Gravity.CENTER_VERTICAL | horizontalGravity);
277+
break;
278+
279+
case 'bottom':
280+
this.nativeTextViewProtected.setGravity(android.view.Gravity.BOTTOM | horizontalGravity);
281+
break;
226282
}
227283
}
228284
}

Diff for: src/label.d.ts

+33-26
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,37 @@
22
* Contains the Label class, which represents a custom label widget which correctly supports html.
33
*/ /** */
44

5-
import { View, Property } from "tns-core-modules/ui/core/view";
6-
import { Label as TNLabel } from "tns-core-modules/ui/label/label";
5+
import { Property, View } from 'tns-core-modules/ui/core/view';
6+
import { Label as TNLabel } from 'tns-core-modules/ui/label/label';
7+
import { dip } from 'tns-core-modules/ui/core/view';
8+
import { Color } from 'tns-core-modules/color/color';
9+
/**
10+
* Represents a label with html content. Use this component instead WebView when you want to show just static HTML content.
11+
* [iOS support](https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSAttributedString_UIKit_Additions/#//apple_ref/occ/instm/NSAttributedString/initWithData:options:documentAttributes:error:)
12+
* [android support](http://developer.android.com/reference/android/text/Html.html)
13+
*/
14+
export declare class Label extends TNLabel {
15+
/**
16+
* Gets the native [android widget](http://developer.android.com/reference/android/widget/TextView.html) that represents the user interface for this component. Valid only when running on Android OS.
17+
*/
18+
android: any /* android.widget.TextView */;
19+
20+
/**
21+
* Gets the native [UITextView](https://developer.apple.com/documentation/uikit/uitextview) that represents the user interface for this component. Valid only when running on iOS.
22+
*/
23+
ios: any /* UITextView */;
24+
25+
/**
26+
* Gets or sets html string for the HtmlView.
27+
*/
28+
html: string;
29+
}
30+
31+
export declare const htmlProperty: Property<Label, string>;
732

8-
/**
9-
* Represents a label with html content. Use this component instead WebView when you want to show just static HTML content.
10-
* [iOS support](https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSAttributedString_UIKit_Additions/#//apple_ref/occ/instm/NSAttributedString/initWithData:options:documentAttributes:error:)
11-
* [android support](http://developer.android.com/reference/android/text/Html.html)
12-
*/
13-
export declare class Label extends TNLabel {
14-
/**
15-
* Gets the native [android widget](http://developer.android.com/reference/android/widget/TextView.html) that represents the user interface for this component. Valid only when running on Android OS.
16-
*/
17-
android: any /* android.widget.TextView */;
18-
19-
/**
20-
* Gets the native [UITextView](https://developer.apple.com/documentation/uikit/uitextview) that represents the user interface for this component. Valid only when running on iOS.
21-
*/
22-
ios: any /* UITextView */;
23-
24-
/**
25-
* Gets or sets html string for the HtmlView.
26-
*/
27-
html: string;
28-
}
29-
30-
export declare const htmlProperty: Property<Label, string>;
31-
33+
export interface TextShadow {
34+
offsetX: dip;
35+
offsetY: dip;
36+
blurRadius: dip;
37+
color: Color;
38+
}

0 commit comments

Comments
 (0)