Environment
Playground
Describe the bug
I would like to find a way to highlight the links for different types of implementations (eg. posts, stories, chat messages,etc.).
The only way I found (for iOS, for now, I'll try later for Android) is to use TextView and to force some properties of it. The best practices I found on the internet is to use something like this :
textView.selectable = true;
textView.editable = false;
textView.userInteractionEnabled = true;
textView.scrollEnabled = false;
textView.dataDetectorTypes = -1; // or 2 (for Playground);
/*
textView.dataDetectorTypes = UIDataDetectorTypes.All // or UIDataDetectorTypes.Links (for local projects)
*/
To Reproduce
https://play.nativescript.org/?template=play-ng&id=5mTabh&v=1
Expected behavior
To highlight the links and be clickable to open the link into a browser.
Any idea if my implementation is correct or if there is any other solution to enable the links?
@alexandruantonica the issue sounds like a potential feature request and is how-to related (as if it is possible on the native side it can be done in NativeScript by accessing the native APIs).
Note that with args.object in your example you are accessing the NativeScript TextView and not the native element. Here is how to access them both
onLoadTextView(args) {
const tf = args.object;
if (isIOS) {
console.log(`tf: ${tf}`); // TextView(11) - this is the NativeScript element
console.log(`tf.ios : ${tf.ios}`); // <NoScrollAnimationUITextView: ...
}
}
@NickIliev : I've implemented further the case in my application and it seems that the Textview will behave differently on device and simulator. With the current TextView, the links will be displayed on the simulator but not on a iOS device. I was able to recreate this strange behaviour also while using local build.
@pap5508 I am not sure what is the outcome you want to achieve but in my case, I wanted to use TextView as a form of Label with text from the server (a post, a story, an article,etc.). The challenge was to achieve a linkable text whenever there are links inside the text received from the server (eg. "Hello, this is my new shop. Check this out http://github.com").
All I wanted was to highlight the links inside the text received from the server without making any other changes. In the example above, I wanted to see http://github.com highlighted and to be able to tap on it.
In order to achieve this, I enclosed everything inside a component and reused that component everywhere I wanted to. It works perfectly cross-platform.
linkable-text.component.html
<TextView
(loaded)="onLoadTextView($event)"
*ngIf="show"
android:editable="false"
[editable]="false"
[text]="text"
textWrap="true"
></TextView>
linkable-text.component.ts
import { ChangeDetectionStrategy, Component, Input, OnInit } from "@angular/core";
import { isIOS } from "tns-core-modules/platform";
import { Color } from "tns-core-modules/ui/core/view-base";
@Component({
selector: "LinkableTextView",
templateUrl: "linkable-text.component.html",
styleUrls: ["linkable-text.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LinkableTextComponent implements OnInit {
@Input("text") text: string = "";
private _linkColor: string = "#199DA4";
private _underline: boolean = true;
constructor() {}
get show(): boolean {
return this.text.trim() !== "";
}
ngOnInit() {}
onLoadTextView(args) {
const linkColor = new Color(this._linkColor);
const tV = args.object;
if (isIOS) {
const itV: UITextView = tV.ios;
itV.userInteractionEnabled = true;
itV.selectable = true;
itV.scrollEnabled = false;
itV.dataDetectorTypes = UIDataDetectorTypes.Link;
itV.tintColor = linkColor.ios;
let objects = [linkColor.ios];
let keys = [NSForegroundColorAttributeName];
if (this._underline) {
objects = [...objects, NSUnderlineStyle.StyleSingle];
keys = [...keys, NSUnderlineStyleAttributeName];
}
itV.linkTextAttributes = NSDictionary.dictionaryWithObjectsForKeys(objects, keys);
} else {
const atV: android.widget.TextView = tV.android;
atV.setAutoLinkMask(1);
atV.setLinksClickable(true);
atV.setLinkTextColor(linkColor.android);
atV.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
atV.setText(atV.getText());
atV.setLinkTextColor(linkColor.android);
}
}
}
@alexandruantonica : thank you for your help. It works perfectly. If I enclosed everything inside a component and reused that component everywhere. but only thing is not working is
itV.dataDetectorTypes = UIDataDetectorTypes.Link; change to itV.dataDetectorTypes = UIDataDetectorTypes.All;
it doesn't recognise anything. May be you can try that as well when you have time. but for me now itV.dataDetectorTypes = UIDataDetectorTypes.Link; works.
Most helpful comment
@pap5508 I am not sure what is the outcome you want to achieve but in my case, I wanted to use TextView as a form of Label with text from the server (a post, a story, an article,etc.). The challenge was to achieve a linkable text whenever there are links inside the text received from the server (eg. "Hello, this is my new shop. Check this out http://github.com").
All I wanted was to highlight the links inside the text received from the server without making any other changes. In the example above, I wanted to see
http://github.comhighlighted and to be able to tap on it.In order to achieve this, I enclosed everything inside a component and reused that component everywhere I wanted to. It works perfectly cross-platform.
linkable-text.component.htmllinkable-text.component.ts