144

What I am trying to accomplish is to have clickable hyperlinks in the message text displayed by an AlertDialog. While the AlertDialog implementation happily underlines and colors any hyperlinks (defined using <a href="..."> in the string resource passed to Builder.setMessage) supplied the links do not become clickable.

The code I am currently using looks like this:

new AlertDialog.Builder(MainActivity.this).setTitle( R.string.Title_About).setMessage( getResources().getText(R.string.about)) .setPositiveButton(android.R.string.ok, null) .setIcon(R.drawable.icon).show(); 

I'd like to avoid using a WebView to just display a text snippet.

2
  • Hi! Do you really accomplish declared results ("happily underlines and colors any hyperlinks")? What string value are you passing? Commented Jan 4, 2010 at 7:08
  • 1
    Yes, the key is to have the message to be displayed in a string resource, which Resources.getText(...) returns as a android.text.Spanned preserving the HTML formatting. As soon as you convert it to a String, though, the magic vanishes. Commented Jan 4, 2010 at 13:01

19 Answers 19

216

I didn't really like the currently most popular answer because it significantly changes the formatting of the message in the dialog.

Here's a solution that will linkify your dialog text without otherwise changing the text styling:

 // Linkify the message final SpannableString s = new SpannableString(msg); // msg should have url to enable clicking Linkify.addLinks(s, Linkify.ALL); final AlertDialog d = new AlertDialog.Builder(activity) .setPositiveButton(android.R.string.ok, null) .setIcon(R.drawable.icon) .setMessage( s ) .create(); d.show(); // Make the textview clickable. Must be called after show() ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); 
Sign up to request clarification or add additional context in comments.

13 Comments

Cheers, Worked for me from within onCreateDialog of a DialogFragment. Just had to set clickable code at onStart given that show had been called to invoke the DialogFragment
This seems to make the entire TextView clickable as opposed to just the links... Any way around this?
I agree this is a far better option since the original answer is messing up the dialog visually.
View returned by findViewById should be checked with "instanceof TextView", because there is no guarantee that implementation will not change.
As pointed out elsewhere, if using setMessage(R.string.something), it is not necessary to explicitly linkify. It's also not necessary to create() the AlertDialog object prior to calling show() (it can be called on the Builder), and since show() returns the dialog object, the findViewById(android.R.id.message) can be chained. Wrap it all in a try-catch just in case the message view is not a TextView, and you have a concise formulation.
|
131

If you are only showing some text and URL[s] in your dialog perhaps the solution is simpler

public static class MyOtherAlertDialog { public static AlertDialog create(Context context) { final TextView message = new TextView(context); // i.e.: R.string.dialog_message => // "Test this dialog following the link to dtmilano.blogspot.com" final SpannableString s = new SpannableString(context.getText(R.string.dialog_message)); Linkify.addLinks(s, Linkify.WEB_URLS); message.setText(s); message.setMovementMethod(LinkMovementMethod.getInstance()); return new AlertDialog.Builder(context) .setTitle(R.string.dialog_title) .setCancelable(true) .setIcon(android.R.drawable.ic_dialog_info) .setPositiveButton(R.string.dialog_action_dismiss, null) .setView(message) .create(); } } 

As shown here http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Alert dialog with clickable links

3 Comments

you probably want to create a layout file and inflate it and use it as the view.
How would you set the style of the textView to match the one used by default?
Then, I'm getting error Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
55

This should make <a href> tags to get highlighted as well. Please note that i have just added a few lines to emmby's code. so credit to him

final AlertDialog d = new AlertDialog.Builder(this) .setPositiveButton(android.R.string.ok, null) .setIcon(R.drawable.icon) .setMessage(Html.fromHtml("<a href=\"http://www.google.com\">Check this link out</a>")) .create(); d.show(); // Make the textview clickable. Must be called after show() ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); 

6 Comments

If you use html in strings.xml, you don't need to use Html.fromHtml. setMessage(R.string.cool_link) works with <string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
That is true. When you combine both methods (Html.fromHtml and HTML tag in strings.xml) it does notwork.
Its been a while and fromHtml is deprecated, now what?
setMovementMethod() is the important part here, otherwise the URL will not be clickable.
I get a null pointer exception at the last line saying that ((TextView)d.findViewById(android.R.id.message)) is null.
|
13

Actually, if you want to simply use a string without dealing with all the views, the fastest way is to find message textview and linkify it:

d.setMessage("Insert your cool string with links and stuff here"); Linkify.addLinks((TextView) d.findViewById(android.R.id.message), Linkify.ALL); 

Comments

12

JFTR, here comes the solution which I figured out after some time:

View view = View.inflate(MainActivity.this, R.layout.about, null); TextView textView = (TextView) view.findViewById(R.id.message); textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setText(R.string.Text_About); new AlertDialog.Builder(MainActivity.this).setTitle( R.string.Title_About).setView(view) .setPositiveButton(android.R.string.ok, null) .setIcon(R.drawable.icon).show(); 

The corresponding about.xml borrowed as a fragment from the Android sources looks like this:

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scrollView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="2dip" android:paddingBottom="12dip" android:paddingLeft="14dip" android:paddingRight="10dip"> <TextView android:id="@+id/message" style="?android:attr/textAppearanceMedium" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dip" android:linksClickable="true" /> </ScrollView> 

The important parts are setting linksClickable to true and setMovementMethod(LinkMovementMethod.getInstance()).

1 Comment

Thank you, this solved the problem for me. In my case, it wasn't necessary to setLinksClickable(true) (I guess it already was), but setMovementMethod(...) made all the difference.
10

Instead of ...

AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); dialogBuilder.setTitle(R.string.my_title); dialogBuilder.setMessage(R.string.my_text); 

... I now use:

AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); dialogBuilder.setTitle(R.string.my_title); TextView textView = new TextView(this); textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setText(R.string.my_text); dialogBuilder.setView(textView); 

2 Comments

Hey, your soln works. do you know why the whole textview flashes when clicking on the link though?
It does not scroll like the default one does.
7

Simplest way:

final AlertDialog dlg = new AlertDialog.Builder(this) .setTitle(R.string.title) .setMessage(R.string.message) .setNeutralButton(R.string.close_button, null) .create(); dlg.show(); // Important! android.R.id.message will be available ONLY AFTER show() ((TextView)dlg.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); 

Comments

6

All the above answer will not remove html tag like , etc if the given string contains, I tried to remove all the tags, and this is work fine for me

AlertDialog.Builder builder = new AlertDialog.Builder(ctx); builder.setTitle("Title"); LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.custom_dialog, null); TextView text = (TextView) layout.findViewById(R.id.text); text.setMovementMethod(LinkMovementMethod.getInstance()); text.setText(Html.fromHtml("<b>Hello World</b> This is a test of the URL <a href=http://www.example.com> Example</a><p><b>This text is bold</b></p><p><em>This text is emphasized</em></p><p><code>This is computer output</code></p><p>This is<sub> subscript</sub> and <sup>superscript</sup></p>";)); builder.setView(layout); AlertDialog alert = builder.show(); 

and the custom_dialog would be like;

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_root" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="fill_parent" android:textColor="#FFF" /> </LinearLayout> 

The above code will remove all the html tag and shows Example as Click able URL all others in the specified html formatting text.

Comments

6

For me the best solution to create privacy policy dialog is :

 private void showPrivacyDialog() { if (!PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean(PRIVACY_DIALOG_SHOWN, false)) { String privacy_pol = "<a href='https://sites.google.com/view/aiqprivacypolicy/home'> Privacy Policy </a>"; String toc = "<a href='https://sites.google.com/view/aiqprivacypolicy/home'> T&C </a>"; AlertDialog dialog = new AlertDialog.Builder(this) .setMessage(Html.fromHtml("By using this application, you agree to " + privacy_pol + " and " + toc + " of this application.")) .setPositiveButton("ACCEPT", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit().putBoolean(PRIVACY_DIALOG_SHOWN, true).apply(); } }) .setNegativeButton("DECLINE", null) .setCancelable(false) .create(); dialog.show(); TextView textView = dialog.findViewById(android.R.id.message); textView.setLinksClickable(true); textView.setClickable(true); textView.setMovementMethod(LinkMovementMethod.getInstance()); } } 

check the working example : app link

Comments

5

I was not really satisfied with the current answers. There are two things that are important when you want clickable hyperlinks in href style withing an AlertDialog:

  1. Set the content as View and not with setMessage(…), as only Views allow clickable HTML content
  2. Set the correct movement method (setMovementMethod(…))

Here is a working minimal example:

strings.xml

<string name="dialogContent"> Cool Links:\n <a href="http://stackoverflow.com">Stackoverflow</a>\n <a href="http://android.stackexchange.com">Android Enthusiasts</a>\n </string> 

MyActivity.java

… public void showCoolLinks(View view) { final TextView textView = new TextView(this); textView.setText(R.string.dialogContent); textView.setMovementMethod(LinkMovementMethod.getInstance()); // this is important to make the links clickable final AlertDialog alertDialog = new AlertDialog.Builder(this) .setPositiveButton("OK", null) .setView(textView) .create(); alertDialog.show() } … 

1 Comment

This works perfectly but the text in the Alert is starting from the very left, without any blank space. You can easily adjust that with textView.setPadding()
3

I've checked many questions and answers, but it doesn't work. I did it myself. This is the code snippet on MainActivity.java.

private void skipToSplashActivity() { final TextView textView = new TextView(this); final SpannableString str = new SpannableString(this.getText(R.string.dialog_message)); textView.setText(str); textView.setMovementMethod(LinkMovementMethod.getInstance()); .... } 

Put this tag on res\values\String.xml

<string name="dialog_message"><a href="http://www.nhk.or.jp/privacy/english/">NHK Policy on Protection of Personal Information</a></string> 

Comments

3

If you are using a DialogFragment, this solution should help.

public class MyDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // dialog_text contains "This is a http://test.org/" String msg = getResources().getString(R.string.dialog_text); SpannableString spanMsg = new SpannableString(msg); Linkify.addLinks(spanMsg, Linkify.ALL); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.dialog_title) .setMessage(spanMsg) .setPositiveButton(R.string.ok, null); return builder.create(); } @Override public void onStart() { super.onStart(); // Make the dialog's TextView clickable ((TextView)this.getDialog().findViewById(android.R.id.message)) .setMovementMethod(LinkMovementMethod.getInstance()); } } 

2 Comments

If you set the SpannableString as the dialog's message, the link is highlighted, but not clickable.
@bk138 The call to .setMovementMethod() in onStart() is what makes the link clickable.
2

I combined some of the options discussed above to come up with this function that works for me. pass the result to dialog builder's SetView() method.

public ScrollView LinkifyText(String message) { ScrollView svMessage = new ScrollView(this); TextView tvMessage = new TextView(this); SpannableString spanText = new SpannableString(message); Linkify.addLinks(spanText, Linkify.ALL); tvMessage.setText(spanText); tvMessage.setMovementMethod(LinkMovementMethod.getInstance()); svMessage.setPadding(14, 2, 10, 12); svMessage.addView(tvMessage); return svMessage; } 

Comments

2

Easy Kotlin implementation

String resource:

<string name="foo"><a href="https://www.google.com/">some link</a></string> 

Code:

AlertDialog.Builder(context) .setMessage(R.string.foo) .show() .apply { findViewById<TextView>(android.R.id.message) ?.movementMethod = LinkMovementMethod.getInstance() } 

1 Comment

this solution is great, but doesn't work from Android 13 anymore I think.
1

I do this by specifying the alert box in an XML resource and loading that. See for example the about.xml (see the ABOUT_URL id) that gets instantiated near the end of ChandlerQE.java. The relevant parts from the java code:

LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = (View) inflater.inflate(R.layout.about, null); new AlertDialog.Builder(ChandlerQE.this) .setTitle(R.string.about) .setView(view) 

1 Comment

link is dead, can you fix it?
1

This is my solution. It creates a normal link without html tags involved and without any URL visible. It also keeps the design intact.

SpannableString s = new SpannableString("This is my link."); s.setSpan(new URLSpan("http://www.google.com"), 11, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); AlertDialog.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert); } else { builder = new AlertDialog.Builder(this); } final AlertDialog d = builder .setPositiveButton("CLOSE", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Do nothing, just close } }) .setNegativeButton("SHARE", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Share the app share("Subject", "Text"); } }) .setIcon(R.drawable.photo_profile) .setMessage(s) .setTitle(R.string.about_title) .create(); d.show(); ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); 

1 Comment

Thanks, Just to add setSpan(URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE). Here startPoint and endPoint are words which will be highlighted for clicking
0

The easiest and shortest way is like this

Android link in dialog

((TextView) new AlertDialog.Builder(this) .setTitle("Info") .setIcon(android.R.drawable.ic_dialog_info) .setMessage(Html.fromHtml("<p>Sample text, <a href=\"http://google.nl\">hyperlink</a>.</p>")) .show() // Need to be called after show(), in order to generate hyperlinks .findViewById(android.R.id.message)) .setMovementMethod(LinkMovementMethod.getInstance()); 

2 Comments

Can you tell me how to do this in Kotlin?
I am sorry. I don't know Kotlin
0

This is the simple way I use

Strings In strings.xml

<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <string name="credits_title">Credits</string> <string name="confirm">OK</string> <string name="credits">All rights reserved. <a href="https://google.com">Source</a> </string> </resources> 

Dimensions In dimens.xml

<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <dimen name="margin_8dp">8dp</dimen> <dimen name="margin_32dp">32dp</dimen> </resources> 

Helper Dialog class

public class MessageHelper { public static void showCreditsDialog(Context context) { AlertDialog alertDialog = new AlertDialog.Builder(context).create(); alertDialog.setTitle(R.string.credits_title); TextView textView = new TextView(context); int padding = (int) context.getResources().getDimension(R.dimen.margin_32dp); int topPadding = (int) context.getResources().getDimension(R.dimen.margin_8dp); textView.setPadding(padding, topPadding, padding, 0); textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setText(R.string.credits); alertDialog.setView(textView); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, context.getResources().getString(R.string.confirm), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialog.show(); } } 

How to use

MessageHelper.showCreditsDialog(this); // this is the context 

Preview

enter image description here

Comments

0

Clickable hyperlinks in AlertDialog

 /*Dialog Agreement*/ private fun agreed() { if (agreed != "yes") { val inflater: LayoutInflater = this.layoutInflater val dialogView: View = inflater.inflate(R.layout.dialog_agreed, null) val btnAccept: TextView = dialogView.findViewById(R.id.btn_accept) val btnDecline: TextView = dialogView.findViewById(R.id.btn_decline) val txtMessage: TextView = dialogView.findViewById(R.id.txt_message) btnAccept.setOnClickListener { //Saving data to preference manager val sharedPref = getSharedPreferences("Janta24", Context.MODE_PRIVATE) val editor = sharedPref.edit() editor.putString("agreed", "yes") editor.apply() alertDialog.dismiss() } btnDecline.setOnClickListener { finish() } txtMessage.text = Html.fromHtml( "We have revised our<a href=\"http://app.janta24.in/term.html\">Terms of Use</a> & " + "<a href=\"http://app.janta24.in/privacy.html\">Privacy Policy</a> " + "By accepting, you agreed to our updated terms and policies. Please take few minutes to read and understand them." ) txtMessage.movementMethod = LinkMovementMethod.getInstance() val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(this) dialogBuilder.setOnDismissListener { } dialogBuilder.setView(dialogView) dialogBuilder.setCancelable(false) alertDialog = dialogBuilder.create() alertDialog.show() } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.