How can I get clickable hyperlinks in AlertDialog

2019-01-01 12:48发布

问题:

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.

回答1:

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



回答2:

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);
    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());


回答3:

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());


回答4:

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);


回答5:

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()).



回答6:

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);


回答7:

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.



回答8:

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()
}
…


回答9:

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>


回答10:

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());


回答11:

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;
}


回答12:

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());
    }
}


回答13:

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)


回答14:

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());