Android web link in textView inside ListView - android

I want to create a link in text view.
My link look like so:
The text to the link I get from array.xml
<item>Icons made by Freepik</item>
I already read set movement method
textView.setMovementMethod(LinkMovementMethod.getInstance());
This has no impact
and
android:autoLink="web"
This works if the text is http://www.freepik.com, but not if I want to have a custom text as link.
viewHolder.textView.setClickable(true);
viewHolder.textView.setText(text);
viewHolder.textView.setMovementMethod(LinkMovementMethod.getInstance());
This is a code which I am using to fill textView
I want in the end text looking like so:
Icons made by Freepik

I think you can't accomplish what you want in this way.
I think the simplest solution is to separate your links in differents list items. Keep in mind that you could use different TextView with different heights for example
Alternatively you could pass to a custom view approach. If you create a custom view (for example MultiLinkView), then you could add this view to the ListView.
I suggest this solution because this approach allow you to add a powerful logic to the view item.
I can't give you the complete code because it should be too long, but I can put you in the right way.
A custom view is a real Java class that extends some Android view class. So when you instantiate a CustomView you can pass to its constructor all the params you want (references, links, arrays and so on).
Start here
My idea is to find a way to pass all the parameters you need to your custom view and then find a way to represent your data, mapping them to your links.
I think you should abandon html solution in favor to ClickableSpan.
This is a piece of code that I used in a project to make clickable a single part of my string:
String text = "Hello <b>click me!</b> to go to internet!";
// create Spanned
Spanned spanned = Html.fromHtml(text);
// create SpannableString
SpannableString spanString = new SpannableString(spanned);
// set clickable part
ClickableSpan clickablePart = new ClickableSpan() {
#Override
public void onClick(View textView) {
if (connectionDetector.isConnectedToInternet()) {
// open browser or webview fragment
}
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(Color.WHITE);
}
};
int startClickMe = spanString.toString().indexOf(text);
spanString.setSpan(clickablePart, startClickMe, text.length() + startClickMe, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Obviously in the onClick you should find a way to get the right link, but, as I said before, in a custom view you can put as many variables as you want. I'm sure that you can find a solution.
Let me know if it helps

Related

How to show HTML text in Android while detecting clicks on specific phrases and scrolling position?

I'm getting a wall of plain HTML text from the server and need to render it in my application, but that's not all.
I also need to detect clicks on specific phrases within the text. The phrases are defined by two numbers: word count where the phrase starts and word count where it ends (e.g. from word 10 to word 15).
My intuition says that I could probably instrument the HTML with links or some JavaScript according to phrases spec and then listen for clicks on these links. However, I'm not sure how to achieve this kind of functionality in Android.
In addition, I also need to be able to programmatically observe and manipulate the scrolling position within the shown HTML text. For instance, I'll need to understand when a specific phrase is scrolled off the screen.
I guess I have three closely related questions:
Which View should I use to achieve the above functionality (TextView, WebView, other)?
How can I listen for clicks on specific parts of HTML?
How can I observe and manipulate the scrolling position?
Thanks
WebView is a quick way to do this.
You can map a java/kotlin function to the javascript function on the webpage to track clicks.
Again using simple jquery , you can achieve it.
Refer to : slymax web view
I think you can do this by using this method :
1.) You need to get all links from the html text you have. So to do this use this method :
public static ArrayList<String> extractUrls(String text) {
ArrayList<String> containedUrls = new ArrayList<>();
String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:##%/;$()~_?\\+-=\\\\\\.&]*)";
Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
Matcher urlMatcher = pattern.matcher(text);
while (urlMatcher.find()) {
containedUrls.add(text.substring(urlMatcher.start(0),
urlMatcher.end(0)));
}
return containedUrls;
}
It will return an ArrayList of URLs, Now you need to convert the HTML data into human readable text :
To do this use :
public void HtmlToString(final String data) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
final String s = String.valueOf(Html.fromHtml(data));
runOnUiThread(new Runnable() {
#Override
public void run() {
processData(s);
}
});
}
});
thread.start();
}
void processData(String s){
// Do whatever you want to do
}
We are doing this work on another thread.
Now, You have text as well as links, do whatever you want with this.
Now if you want to do more work on it you may do this by replacing all the links you get in array list with a special code that you can use as a placeholder like :
for(int i = 0; i < urlArray.size();i++){
yourData.replace(urlArray.get(i),"<<<YOURSPECIALCODE>>>");
}
Now you can break your data using your Special code to get the breaks at the place of URLs. To do that :
ArrayList<String> dataArray = new ArrayList<>(yourData.split("<<<YOURSPECIALCODE>>>"));
Now you can use these two arrays to show according to your requirements
As now You can assign different text views to different data and setOnClick Listeners to them very easily.
Hope it may help!
Thank you
In case you are planning to use TextView (I would prefer to if the content isn't supposed to be rendered as a full HTML, use WebView otherwise) and use Clickable span within the text content to make specific areas clickable. You can handle the click on individual span areas and perform the required actions in the click handler. You need to write multiple CustomClickableSpan classed based on the number of different clickable areas you wish to handle.
I guess for you're use case ideal view would be WebView.
It is easier to handle HTML in a webview rather than TextView.
TextView requires you to make use of spans for handling HTML content which is somewhat difficult when compared to handling HTML in a WebView.
And also for monitoring the scrolling behaviour, we can make use of the scroll event of an element in a webview which makes it easier to handle individual elements scroll behaviour.
So in order to make certain portions of text clickable make use of the below code snippet (Kotlin),
val htmlString = "<div>Handling the click near the specified indices</div>"
val document = Jsoup.parse(htmlString)
document.outputSettings().prettyPrint(false)
var plaintext = document.body().text()
plaintext = plaintext.replaceRange(13,18, "<a href='https://www.google.com'>${plaintext.substring(13, 18)}</a>")
document.body().html(plaintext)
Make use of Jsoup library for parsing through the HTML content.
The above code snippet will make the indexed substring clickable and point it to www.google.com. You can also add other events to it as well.
Then in order to check if an element is visible on screen you can have a javascript function like,
function isElementVisible(element)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(element).offset().top;
var elemBottom = elemTop + $(element).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
which takes in the element and returns true if element is visible onscreen or false if the element is not visible.
You can do that with SpannableString - find every link tags in your html text and set spannable wherever you need (for example for every between tag: SPANNABLE STRING).
Follow this topic, make your clickable spannable strings and show it in TextView. It's not so hard :)
Android: ClickableSpan in clickable TextView

Android - Enabling only URL link, but disabling the others when it touches something non-URL link in TextView

I am implementing a board. And I want the View that the users can include links.
Now, my TextView has
android:autoLink="web"
attribute. However, It works a bit differently from what I expected.
As you can see, even though I click the empty area(+lines in the picture), the TextView is detecting the link(blue highlight) and If I let my finger go, a web browser opens and it goes to the URL.
That's not what I want. I just want it to work when I ONLY click the link. (Not other non-URL text nor empty area)
and
I DON'T KNOW what users write, In other words, I can't preset specific links nor guess what URLs would be. It must be applied to all the links even that I don't know.
The number of links can be more than ONE. And I don't know how many links would be included in the user's content.
Somebody tells me I need to make it to HTML using WebView. Well, Do I really just have that option? because I don't think the chat rooms of many messengers such as Kakaotalk, Whatsapp, Wechat, or Telegram, even Instagram are made of WebView.
What if I want to place pictures in the middle of text? I guess it is impossible with TextView. How to make it?
You need to handle links programatically. This way you will have way to separate clickable spans and non-clickable spans. And you can add more code on click of spans if you want.
Below is the way which you can use
private void createUrlSpansInTextView(TextView tv, String text) {
tv.setText(text); // Or you can remove this line if you already set text to textview
SpannableString current=(SpannableString)tv.getText();
URLSpan[] spans=
current.getSpans(0, current.length(), URLSpan.class);
for (URLSpan span : spans) {
int start=current.getSpanStart(span);
int end=current.getSpanEnd(span);
current.removeSpan(span);
current.setSpan(new CustomURLSpan(span.getURL()), start, end,
0);
}
}
Where CustomURLSpan is
private static class CustomURLSpan extends URLSpan {
public CustomURLSpan(String url) {
super(url);
}
#Override
public void onClick(View widget) {
// Write your code to load urls
}
}
What if I want to place pictures in the middle of text? I guess it is
impossible with TextView. How to make it?
No with TextView not possible. You need to look for third party libraries. I am not sure if any exists.

Intercept link LinkMovementMethod with a Yes/No dialog

I have a standard LinkMovementMethod established in my TextView to push a web Activity of some sort when the user touches a link. However, I want to establish a "do you want to see the link" dialog rather than taking the user straight to the webpage. I've tried overriding the touch methods but it all gets a little convoluted. A little help?
You can accomplish it in two ways:
Create custom Spans: more complicated, but you can accomplish more customised text consisting of clickable parts (or bold, differently coloured etc). To know more, check out ClickableSpan and SpannableStringBuilder
Extend LinkMovementMethod to accept custom click listener
In my opinion second solution is better in basic cases like yours. Here is how you can do it:
Copy this java class: InternalLinkMovementMethod to your project
Add set the link movement method of your TextView to this custom one, providing a click listener:
OnLinkClickedListener clickListener = new OnLinkClickedListener() {
#Override
public boolean onLinkClicked(String linkText) {
// here you can handle your click, eg show the dialog
// `linkText` is the text being clicked (the link)
// return true if handled, false otherwise
}
}
yourTextView.setMovementMethod(new InternalLinkMovementMethod(clickListener));

How to make a TextView clickable but not to launch with the phone's browser

I am creating an Android Browser and within my browser i am making a Favorites page.
In my favorite page, i have an EditText, where i insert the adress of the website i want to add, a remove button which removes all favorites and a TextView where the added websites are displayed.
My question is ...how can i make the adresses displayed in the TextView to be links, not only strings, BUT to be opened inside my browser?
All my tries so far ended up opening it with the phone's browser. My browser is structured like this: A menu, which is an OnListItemClick, where i can select HomePage, which has the main thing where you can browse the internet, with back and forward, refresh buttons.
In the menu, after the HomePage, i have Favorites, History and Settings. I need it to start the HomePage and to acces the site when i click the link from the favorites TextView. Can anyone give me an idea how to do it? I am sure i need to make a huge method for that, but I don't know how to start.
Know this is pretty late. Just think others might also find this useful.
You can implement your own ClickableSpan to achieve that. You can create a Spannable from scratch and assign to TextView like:
Spannable text = Spannable.newSpannable("Source text with link");
ClickableSpan link = new ClickableSpan {
public abstract void onClick (View widget) {
// Implement your own link behaviour
}
}
text.setSpan(clickable, startPos, endPos, flags);
textView.setText(text);
Or, if your source is html, you can use Html.fromHtml("Source text with <a href='whatever'>link</a>") which parses the HTML and converts links into URLSpan for you. You then need to replace all URLSpan with your own ClickableSpan like above. (see Spanned#getSpans and Spannable)
This can be tedious. Thus I created a library Textoo to simplify the matter. With Textoo you can achieve the same like:
Spanned linksLoggingText = Textoo
.config("Links: <a href='http://www.google.com'>Google</a>")
.parseHtml()
.addLinksHandler(new LinksHandler() {
#Override
public boolean onClick(View view, String url) {
Log.i("MyActivity", "Linking to google...");
return false; // event not handled. Continue default processing i.e. link to google
}
})
.apply();

make few selective words clickable in a line generated at runtime in a TextvView in Android?

I am working on an application where I am receiving comments which I have to show in a list view. In the comments I am having few names of the tagged friends. The comment string generated at run-time containing few names.
Now, i have to make only those names in the complete comment string as clickable. How can I separate the Name from the complete string to add the click listener on the names.
Please suggest.
you can achieve this with SpannableString and ClickableSpan.
For this you need the indices of the substring you want to make clickable (sadly i haven't yet figured out an efficient way of how to get the indices right). You can even set multiple clickableSpans to one String.
Try something like this:
SpannableString text;
ClickableSpan clickMe;
public void onCreate(...){
text = new SpannableString(yourText);
clickMe = new ClickableSpan(){
#Override
public void onClick(View textView){
// Your ClickEvent
}
};
text.setSpan(clickMe, startIndexOfSubstring, EndIndexOfSubstring, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
Then you just need to apply that text to your TextView or Item in your ListView and it will be clickable.
I sadly have no experience with this Method in ListViews, but in TextViews this worked fine for me. You have to set this too:
yourTextView.setMovementMethod(LinkMovementMethod.getInstance());
Hope this helped you somehow!

Categories

Resources