Comment puis-je obtenir des liens hypertexte cliquables dans AlertDialog à partir d'une ressource de chaîne?

134

Ce que j'essaie d'accomplir, c'est d'avoir des hyperliens cliquables dans le texte du message affiché par un fichier AlertDialog. Alors que l' AlertDialogimplémentation souligne et colore joyeusement les hyperliens (définis à l'aide <a href="...">de la ressource de chaîne transmise à Builder.setMessage), les liens ne deviennent pas cliquables.

Le code que j'utilise actuellement ressemble à ceci:

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

Je voudrais éviter d'utiliser un WebViewpour afficher simplement un extrait de texte.

Thilo-Alexander Ginkel
la source
Salut! Accomplissez-vous vraiment les résultats déclarés ("souligne et colore joyeusement les hyperliens")? Quelle valeur de chaîne passez-vous?
Maksym Gontar le
1
Oui, la clé est d'avoir le message à afficher dans une ressource de chaîne, que Resources.getText (...) renvoie comme un android.text.Spanned en préservant le formatage HTML. Dès que vous le convertissez en String, la magie disparaît.
Thilo-Alexander Ginkel le

Réponses:

128

Si vous n’affichez que du texte et des URL dans votre boîte de dialogue, la solution est peut-être plus simple

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

Comme indiqué ici http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Boîte de dialogue d'alerte avec liens cliquables

Diego Torres Milan
la source
1
vous souhaitez probablement créer un fichier de mise en page, le gonfler et l'utiliser comme vue.
Jeffrey Blattman
5
Comment définiriez-vous le style du textView pour qu'il corresponde à celui utilisé par défaut?
développeur android
3
Ensuite, Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
j'obtiens une
207

Je n'ai pas vraiment aimé la réponse la plus populaire actuellement car elle modifie considérablement la mise en forme du message dans la boîte de dialogue.

Voici une solution qui liera le texte de votre boîte de dialogue sans changer autrement le style du texte:

    // 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());
emmby
la source
5
Cheers, a travaillé pour moi de l'intérieur onCreateDialogd'un DialogFragment. Juste eu à définir le code cliquable à onStartdonné qui showavait été appelé pour invoquer le DialogFragment
PJL
5
Cela semble rendre l'ensemble de TextView cliquable, par opposition aux liens seulement ...
Kavi
1
Je suis d'accord que c'est une bien meilleure option car la réponse originale gâche visuellement le dialogue.
hcpl
1
La vue renvoyée par findViewById doit être vérifiée avec "instanceof TextView", car il n'y a aucune garantie que l'implémentation ne changera pas.
Denis Gladkiy
6
Comme indiqué ailleurs, en cas d'utilisation setMessage(R.string.something), il n'est pas nécessaire de lier explicitement. Il n'est pas non plus nécessaire d' create()utiliser l'objet AlertDialog avant l'appel show()(il peut être appelé sur le générateur), et comme show()renvoie l'objet de dialogue, le findViewById(android.R.id.message)peut être chaîné. Enveloppez le tout dans un try-catch juste au cas où la vue du message ne serait pas un TextView, et vous avez une formulation concise.
Pierre-Luc Paour
50

Cela devrait également faire en sorte que les <a href>balises soient mises en évidence. Veuillez noter que je viens d'ajouter quelques lignes au code d'emmby. tellement crédit à lui

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());
DeRagan
la source
10
Si vous utilisez html dans strings.xml, vous n'avez pas besoin d'utiliser Html.fromHtml. setMessage(R.string.cool_link)fonctionne avec<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii
2
C'est vrai. Lorsque vous combinez les deux méthodes (Html.fromHtml et balise HTML dans strings.xml) cela ne fonctionne pas.
JerabekJakub
Cela fait un moment et fromHtml est obsolète, et maintenant?
Menasheh
Vous pouvez toujours utiliser fromHtml: developer.android.com/reference/android/text/… , int) Utilisez simplementHtml.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB
2
setMovementMethod()est la partie importante ici, sinon l'URL ne sera pas cliquable.
scai
13

En fait, si vous souhaitez simplement utiliser une chaîne sans traiter toutes les vues, le moyen le plus rapide est de trouver le texte du message et de le lier:

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

JFTR, voici la solution que j'ai trouvée après un certain temps:

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

Le about.xml correspondant emprunté sous forme de fragment aux sources Android ressemble à ceci:

<?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>

Les parties importantes sont la définition de linksClickable sur true et setMovementMethod (LinkMovementMethod.getInstance ()).

Thilo-Alexander Ginkel
la source
Merci, cela a résolu le problème pour moi. Dans mon cas, ce n'était pas nécessaire setLinksClickable(true)(je suppose que c'était déjà le cas), mais cela a setMovementMethod(...)fait toute la différence.
LarsH
10

Au lieu de ...

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

... j'utilise maintenant:

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);
neu242
la source
Hé, votre soln fonctionne. savez-vous pourquoi tout le texte clignote lorsque vous cliquez sur le lien?
aimango
Il ne défile pas comme celui par défaut.
Meow Cat 2012
7

Manière la plus simple:

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());
Gabriele
la source
6

Toute la réponse ci-dessus ne supprimera pas la balise html comme, etc. si la chaîne donnée contient, j'ai essayé de supprimer toutes les balises, et cela fonctionne bien pour moi

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

et le custom_dialog serait comme;

<?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>

Le code ci-dessus supprimera toutes les balises html et affichera Exemple comme URL cliquable toutes les autres dans le texte de mise en forme html spécifié.

Lakshmanan
la source
5

Je n'étais pas vraiment satisfait des réponses actuelles. Il y a deux choses qui sont importantes lorsque vous voulez des hyperliens cliquables dans le style href avec un AlertDialog:

  1. Définissez le contenu sur Affichage et non avec setMessage(…), car seules les vues autorisent le contenu HTML cliquable
  2. Définissez la méthode de mouvement correcte ( setMovementMethod(…))

Voici un exemple minimal de travail:

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()
}
Couler
la source
3

J'ai vérifié de nombreuses questions et réponses, mais cela ne fonctionne pas. Je l'ai fait moi-même. Voici l'extrait de code sur 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());

    ....
}

Mettez cette balise sur 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>
Hiroto
la source
2

J'ai combiné certaines des options décrites ci-dessus pour créer cette fonction qui fonctionne pour moi. transmettez le résultat à la méthode SetView () du générateur de dialogue.

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;
}
Alex
la source
2

Si vous utilisez a DialogFragment, cette solution devrait vous aider.

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());
    }
}
tronman
la source
Si vous définissez SpannableString comme message de la boîte de dialogue, le lien est mis en surbrillance, mais pas cliquable.
bk138 le
@ bk138 L'appel à .setMovementMethod () dans onStart () est ce qui rend le lien cliquable.
tronman
2

Pour moi, la meilleure solution pour créer un dialogue de politique de confidentialité est:

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

vérifiez l'exemple de travail: lien d'application

Serviteur
la source
1

Je fais cela en spécifiant la boîte d'alerte dans une ressource XML et en la chargeant. Voir par exemple about.xml (voir l'identifiant ABOUT_URL) qui est instancié vers la fin de ChandlerQE.java . Les parties pertinentes du code java:

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)
Heikki Toivonen
la source
le lien est mort, pouvez-vous le réparer?
Bijoy Thangaraj
1

C'est ma solution. Il crée un lien normal sans balises html impliquées et sans aucune URL visible. Il garde également le 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());
John T
la source
1
Merci, juste pour ajouter setSpan (URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE). Ici, startPoint et endPoint sont des mots qui seront surlignés pour cliquer
Manish
0

Le moyen le plus simple et le plus court est comme ça

Lien Android dans la boîte de dialogue

((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());
Javier Castellanos Cruz
la source
Pouvez-vous me dire comment faire cela à Kotlin?
Thomas Williams le
Je suis désolé. Je ne sais pas Kotlin
Javier Castellanos Cruz