mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(html-view): Additional properties for HtmlView component (#8207)
* feat(html-view): Additional properties for HtmlView component - Allow to set text color with `color` CSS property. - Allow to set link color with `link-color` CSS property. - Allow to set font attributes with `font-family` and `font-size` CSS properties. - Make text selectable on Android by default (for consistency with IOS). - Remove extra padding on IOS. * refactor: Move uiColorToHex function to nativescript-core/color module * test: adding test for new HtmlView css properties Co-authored-by: Vasil Trifonov <v.trifonov@gmail.com>
This commit is contained in:
committed by
Vasil Trifonov
parent
3c340b42dc
commit
9217094a8e
@@ -157,6 +157,10 @@ export class Color implements definition.Color {
|
||||
public toString(): string {
|
||||
return this.hex;
|
||||
}
|
||||
|
||||
public static fromIosColor(value: UIColor): Color {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function isRgbOrRgba(value: string): boolean {
|
||||
|
||||
5
nativescript-core/color/color.d.ts
vendored
5
nativescript-core/color/color.d.ts
vendored
@@ -75,4 +75,9 @@ export class Color {
|
||||
* @param value Input string.
|
||||
*/
|
||||
public static isValid(value: any): boolean;
|
||||
|
||||
/**
|
||||
* Creates color from iOS-specific UIColor value representation.
|
||||
*/
|
||||
public static fromIosColor(value: any /* UIColor */): Color;
|
||||
}
|
||||
|
||||
@@ -11,4 +11,15 @@ export class Color extends common.Color {
|
||||
|
||||
return this._ios;
|
||||
}
|
||||
|
||||
public static fromIosColor(value: UIColor): Color {
|
||||
const rgba = CGColorGetComponents(value.CGColor);
|
||||
|
||||
return new Color(
|
||||
Math.round(rgba[3] * 255),
|
||||
Math.round(rgba[0] * 255),
|
||||
Math.round(rgba[1] * 255),
|
||||
Math.round(rgba[2] * 255),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { HtmlView as HtmlViewDefinition } from ".";
|
||||
import { Color } from "../../color";
|
||||
import { Style, CssProperty } from "../core/properties";
|
||||
import { View, Property, CSSType } from "../core/view";
|
||||
import { HtmlView as HtmlViewDefinition } from ".";
|
||||
|
||||
export * from "../core/view";
|
||||
|
||||
@@ -13,3 +15,11 @@ HtmlViewBase.prototype.recycleNativeView = "auto";
|
||||
// TODO: Can we use Label.ios optimization for affectsLayout???
|
||||
export const htmlProperty = new Property<HtmlViewBase, string>({ name: "html", defaultValue: "", affectsLayout: true });
|
||||
htmlProperty.register(HtmlViewBase);
|
||||
|
||||
export const linkColorProperty = new CssProperty<Style, Color>({
|
||||
name: "linkColor",
|
||||
cssName: "link-color",
|
||||
equalityComparer: Color.equals,
|
||||
valueConverter: (value) => new Color(value),
|
||||
});
|
||||
linkColorProperty.register(Style);
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import {
|
||||
HtmlViewBase, htmlProperty
|
||||
import { Color } from "../../color";
|
||||
import { Font } from "../styling/font";
|
||||
import {
|
||||
colorProperty,
|
||||
fontSizeProperty,
|
||||
fontInternalProperty,
|
||||
} from "../styling/style-properties";
|
||||
import {
|
||||
HtmlViewBase, htmlProperty,
|
||||
linkColorProperty,
|
||||
} from "./html-view-common";
|
||||
|
||||
export * from "./html-view-common";
|
||||
@@ -15,6 +23,9 @@ export class HtmlView extends HtmlViewBase {
|
||||
super.initNativeView();
|
||||
const nativeView = this.nativeViewProtected;
|
||||
|
||||
// Allow text selection
|
||||
nativeView.setTextIsSelectable(true);
|
||||
|
||||
// This makes the html <a href...> work
|
||||
nativeView.setLinksClickable(true);
|
||||
nativeView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
|
||||
@@ -39,4 +50,46 @@ export class HtmlView extends HtmlViewBase {
|
||||
this.nativeViewProtected.setAutoLinkMask(mask);
|
||||
this.nativeViewProtected.setText(<any>android.text.Html.fromHtml(value));
|
||||
}
|
||||
|
||||
[colorProperty.getDefault](): android.content.res.ColorStateList {
|
||||
return this.nativeViewProtected.getTextColors();
|
||||
}
|
||||
[colorProperty.setNative](value: Color | android.content.res.ColorStateList) {
|
||||
if (value instanceof Color) {
|
||||
this.nativeViewProtected.setTextColor(value.android);
|
||||
} else {
|
||||
this.nativeViewProtected.setTextColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
[linkColorProperty.getDefault](): android.content.res.ColorStateList {
|
||||
return this.nativeViewProtected.getLinkTextColors();
|
||||
}
|
||||
[linkColorProperty.setNative](value: Color | android.content.res.ColorStateList) {
|
||||
const color = value instanceof Color ? value.android : value;
|
||||
if (value instanceof Color) {
|
||||
this.nativeViewProtected.setLinkTextColor(value.android);
|
||||
} else {
|
||||
this.nativeViewProtected.setLinkTextColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
[fontInternalProperty.getDefault](): android.graphics.Typeface {
|
||||
return this.nativeViewProtected.getTypeface();
|
||||
}
|
||||
[fontInternalProperty.setNative](value: Font | android.graphics.Typeface) {
|
||||
const font = value instanceof Font ? value.getAndroidTypeface() : value;
|
||||
this.nativeViewProtected.setTypeface(font);
|
||||
}
|
||||
|
||||
[fontSizeProperty.getDefault](): {nativeSize: number} {
|
||||
return {nativeSize: this.nativeViewProtected.getTextSize()};
|
||||
}
|
||||
[fontSizeProperty.setNative](value: number | {nativeSize: number}) {
|
||||
if (typeof value === "number") {
|
||||
this.nativeViewProtected.setTextSize(value);
|
||||
} else {
|
||||
this.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { Color } from "../../color";
|
||||
import { Font } from "../styling/font";
|
||||
import {
|
||||
HtmlViewBase, View, layout, htmlProperty
|
||||
colorProperty,
|
||||
fontInternalProperty,
|
||||
} from "../styling/style-properties";
|
||||
import {
|
||||
HtmlViewBase, View, layout, htmlProperty, fontSizeProperty,
|
||||
linkColorProperty,
|
||||
} from "./html-view-common";
|
||||
import { ios } from "../../utils/utils";
|
||||
|
||||
@@ -9,6 +16,7 @@ const majorVersion = ios.MajorVersion;
|
||||
|
||||
export class HtmlView extends HtmlViewBase {
|
||||
nativeViewProtected: UITextView;
|
||||
private currentHtml: string;
|
||||
|
||||
public createNativeView() {
|
||||
const view = UITextView.new();
|
||||
@@ -21,6 +29,14 @@ export class HtmlView extends HtmlViewBase {
|
||||
return view;
|
||||
}
|
||||
|
||||
public initNativeView(): void {
|
||||
super.initNativeView();
|
||||
|
||||
// Remove extra padding
|
||||
this.nativeViewProtected.textContainer.lineFragmentPadding = 0;
|
||||
this.nativeViewProtected.textContainerInset = (UIEdgeInsets as any).zero;
|
||||
}
|
||||
|
||||
get ios(): UITextView {
|
||||
return this.nativeViewProtected;
|
||||
}
|
||||
@@ -50,8 +66,22 @@ export class HtmlView extends HtmlViewBase {
|
||||
[htmlProperty.getDefault](): string {
|
||||
return "";
|
||||
}
|
||||
[htmlProperty.setNative](value: string) {
|
||||
const htmlString = NSString.stringWithString(value + "");
|
||||
|
||||
private renderWithStyles() {
|
||||
let html = this.currentHtml;
|
||||
const styles = [];
|
||||
if (this.nativeViewProtected.font) {
|
||||
styles.push(`font-family: '${this.nativeViewProtected.font.fontName}';`);
|
||||
styles.push(`font-size: ${this.nativeViewProtected.font.pointSize}px;`);
|
||||
}
|
||||
if (this.nativeViewProtected.textColor) {
|
||||
const textColor = Color.fromIosColor(this.nativeViewProtected.textColor);
|
||||
styles.push(`color: ${textColor.hex};`);
|
||||
}
|
||||
if (styles.length > 0) {
|
||||
html += `<style>body {${styles.join("")}}</style>`;
|
||||
}
|
||||
const htmlString = NSString.stringWithString(html + "");
|
||||
const nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
|
||||
this.nativeViewProtected.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(
|
||||
nsData,
|
||||
@@ -63,4 +93,38 @@ export class HtmlView extends HtmlViewBase {
|
||||
this.nativeViewProtected.textColor = UIColor.labelColor;
|
||||
}
|
||||
}
|
||||
|
||||
[htmlProperty.setNative](value: string) {
|
||||
this.currentHtml = value;
|
||||
this.renderWithStyles();
|
||||
}
|
||||
|
||||
[colorProperty.getDefault](): UIColor {
|
||||
return this.nativeViewProtected.textColor;
|
||||
}
|
||||
[colorProperty.setNative](value: Color | UIColor) {
|
||||
const color = value instanceof Color ? value.ios : value;
|
||||
this.nativeViewProtected.textColor = color;
|
||||
this.renderWithStyles();
|
||||
}
|
||||
|
||||
[linkColorProperty.getDefault](): UIColor {
|
||||
return this.nativeViewProtected.linkTextAttributes[NSForegroundColorAttributeName];
|
||||
}
|
||||
[linkColorProperty.setNative](value: Color | UIColor) {
|
||||
const color = value instanceof Color ? value.ios : value;
|
||||
const linkTextAttributes = NSDictionary.dictionaryWithObjectForKey(
|
||||
color,
|
||||
NSForegroundColorAttributeName,
|
||||
);
|
||||
this.nativeViewProtected.linkTextAttributes = linkTextAttributes;
|
||||
}
|
||||
[fontInternalProperty.getDefault](): UIFont {
|
||||
return this.nativeViewProtected.font;
|
||||
}
|
||||
[fontInternalProperty.setNative](value: Font | UIFont) {
|
||||
const font = value instanceof Font ? value.getUIFont(this.nativeViewProtected.font) : value;
|
||||
this.nativeViewProtected.font = font;
|
||||
this.renderWithStyles();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user