How to make ClickableSpan links in MaterialAlertDialogBuilder clickable?
F

3

5

I have a SpannableStringBuilder object with a ClickableSpan link like this,

SpannableStringBuilder ssb = new SpannableStringBuilder("Hi StackOverflow!");

ClickableSpan clickableSpan = new ClickableSpan() {
    @Override
    public void onClick(@NonNull View widget) {
        Toast.makeText(MainActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
    }
};

ssb.setSpan(clickableSpan, 3, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

This works fine when I set it to a TextView and after using textView.setMovementMethod(LinkMovementMethod.getInstance())

When I set the ssb object to the MaterialAlertDialogBuilder,

new MaterialAlertDialogBuilder(this)
                .setTitle("My Dialog")
                .setMessage(ssb)
                .show();

It displays as a clickable link but cannot actually click it MaterialAlertDialogBuilder preview I couldn't find a way to use setMovementMethod for the message in MaterialAlertDialogBuilder. Is there any way to make it clickable?

Fuchsin answered 24/5, 2020 at 8:4 Comment(4)
Create a custom view, put a textView within that view, apply setMovementMethod to that textView and then set that custom view to your material alert dialog.Runck
@Runck yes I have tried that and it works, but the problem of using a custom view is it will look different than the MaterialAlertDialogBuilder's message, which defeat the purpose of using it in the first place. I would like to keep the appearance of MaterialAlertDialogBuilder's message view.Fuchsin
Well in that you can use Linkify class to make your string content clickable.Runck
@Amila To apply to your TextView the same style just use in your TextView the style="?attr/materialAlertDialogBodyTextStyle" or style="@style/MaterialAlertDialog.MaterialComponents.Body.Text"Sackman
R
5

Here is code snippet to make your spannable content clickable, give it a try.

SpannableString s = new SpannableString(msg); // Here msg should have url to enable clicking
Linkify.addLinks(s, Linkify.ALL);

After that put your alertdialog code here

//Alert dialog code

Then get id of textview of your MaterialAlertDialog, below line of code must be called after dialog.show() like this,

((TextView)dialog.findViewById(android.R.id.message))
.setMovementMethod(LinkMovementMethod.getInstance());
Runck answered 24/5, 2020 at 8:27 Comment(2)
Thank you! .setMovementMethod(LinkMovementMethod.getInstance()) part helped me.Cyma
That sounds cool, Happy coding @Mike.Runck
D
4

I was wondering how to add a hyperlink to a MaterialAlertDialog message via a static string that contains simple html tags without having to create a custom view (e.g. Hello <a href='https://en.wikipedia.org/wiki/%22Hello,_World!%22_program'> World </a>), @Bhavnik's answer helped a lot:

val dialog = MaterialAlertDialogBuilder(context)
                    .setTitle(getString(R.string.dialog_title))
                    .setMessage(getText(R.string.dialog_content))
                    ...
                    .show()    //must after show()!!
dialog.findViewById<TextView>(android.R.id.message)?.movementMethod = LinkMovementMethod.getInstance()

The main trick is indeed to add the LinkMovementMethod after showing the dialog, but also don't forget to get the string with getText in order to keep the styling.

For more complex html, .setMessage(Html.fromHtml(getText(R.string.dialog_content).toString(), flags)) also seems to work.

Dunn answered 29/6, 2020 at 16:40 Comment(0)
S
3

Just define a TextView with the default style (@style/MaterialAlertDialog.MaterialComponents.Body.Text) provided by the MaterialAlertDialogBuilder:

<TextView
  android:id="@+id/textview1"
  style="?attr/materialAlertDialogBodyTextStyle"
  ...>

Then set the SpannableStringBuilder as text:

SpannableStringBuilder ssb =....
LayoutInflater inflater = this.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.custom_text_view, null);
TextView customTextView = dialogView.findViewById(R.id.textview1);
customTextView.setText(ssb);
customTextView.setMovementMethod(LinkMovementMethod.getInstance());

Finally:

 MaterialAlertDialogBuilder(this)
        .setTitle("My Dialog")
        .setView(dialogView)
        ...
Sackman answered 24/5, 2020 at 8:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.