Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api-reports/NativeScript.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ export class Color {
public b: number;
public equals(value: Color): boolean;
public static equals(value1: Color, value2: Color): boolean;
public static fromIosColor(value: any /* UIColor */): Color;
public g: number;
public hex: string;
ios: any /* UIColor */;
Expand Down
7 changes: 7 additions & 0 deletions e2e/ui-tests-app/app/css/all-non-uniform-border-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@
height: 80;
font-size: 6;
}

.html-view {
font-size: 10;
link-color: red;
color: green;
font-family: 'Courier New', Courier, monospace;
}
2 changes: 1 addition & 1 deletion e2e/ui-tests-app/app/css/all-non-uniform-border-page.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ActivityIndicator class="s0" row="2" col="2" busy="false"/>
<Image class="s0" row="3" col="0" src="~/resources/images/gravatar.png" stretch="fill"/>
<ListView class="s0" row="3" col="1" items="ListView"/>
<HtmlView class="s0" row="3" col="2" html="<h1>HtmlView</h1>"/>
<HtmlView class="s0 html-view" row="3" col="2" html="<h1>HtmlView</h1><a href='http://www.nativescript.org'>{N} Site</a>"/>
<WebView class="s0" row="4" col="0" src="~/web-view/test.html"/>
<SegmentedBar class="s0" row="4" col="1">
<SegmentedBar.items>
Expand Down
4 changes: 4 additions & 0 deletions nativescript-core/color/color-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions nativescript-core/color/color.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 11 additions & 0 deletions nativescript-core/color/color.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
);
}
}
12 changes: 11 additions & 1 deletion nativescript-core/ui/html-view/html-view-common.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -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);
57 changes: 55 additions & 2 deletions nativescript-core/ui/html-view/html-view.android.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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());
Expand All @@ -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);
}
}
}
70 changes: 67 additions & 3 deletions nativescript-core/ui/html-view/html-view.ios.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -9,6 +16,7 @@ const majorVersion = ios.MajorVersion;

export class HtmlView extends HtmlViewBase {
nativeViewProtected: UITextView;
private currentHtml: string;

public createNativeView() {
const view = UITextView.new();
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand All @@ -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();
}
}