Come posso ottenere collegamenti ipertestuali cliccabili in AlertDialog da una risorsa stringa?


134

Quello che sto cercando di realizzare è avere collegamenti ipertestuali cliccabili nel testo del messaggio visualizzati da un AlertDialog. Mentre l' AlertDialogimplementazione sottolinea felicemente e colora eventuali collegamenti ipertestuali (definiti utilizzando <a href="...">nella risorsa stringa passata a Builder.setMessage) forniti i collegamenti non diventano selezionabili.

Il codice che sto attualmente usando è simile al seguente:

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

Vorrei evitare di usare a WebViewper visualizzare solo uno snippet di testo.


Ciao! Realizzi davvero i risultati dichiarati ("sottolinea e colora felicemente i collegamenti ipertestuali")? Quale valore di stringa stai passando?
Maksym Gontar il

1
Sì, la chiave è avere il messaggio da visualizzare in una risorsa stringa, che Resources.getText (...) restituisce come android.text.Spanning preservando la formattazione HTML. Non appena lo converti in una stringa, però, la magia svanisce.
Thilo-Alexander Ginkel,

Risposte:


128

Se stai mostrando solo alcuni testi e URL nella tua finestra di dialogo, forse la soluzione è più semplice

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

Come mostrato qui http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Finestra di avviso con collegamenti selezionabili


1
probabilmente si desidera creare un file di layout, gonfiarlo e utilizzarlo come vista.
Jeffrey Blattman,

5
Come imposteresti lo stile di textView affinché corrisponda a quello utilizzato per impostazione predefinita?
sviluppatore Android

3
Quindi, ricevo un erroreCalling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
ViliusK l'

207

Non mi è piaciuta molto la risposta attualmente più popolare perché cambia significativamente la formattazione del messaggio nella finestra di dialogo.

Ecco una soluzione che collegherà il testo della finestra di dialogo senza modificare in altro modo lo stile del testo:

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

5
Saluti, ha funzionato per me dall'interno onCreateDialogdi a DialogFragment. Ho dovuto solo impostare un codice cliccabile onStartdato che showera stato chiamato per invocare DialogFragment
PJL

5
Questo sembra rendere cliccabile l'intero TextView anziché solo i collegamenti ... In ogni caso?
Kavi,

1
Sono d'accordo che questa è un'opzione di gran lunga migliore poiché la risposta originale sta rovinando visivamente il dialogo.
hcpl,

1
La vista restituita da findViewById deve essere verificata con "instanceof TextView", poiché non esiste alcuna garanzia che l'implementazione non cambierà.
Denis Gladkiy,

6
Come indicato altrove, se utilizzato setMessage(R.string.something), non è necessario collegarsi esplicitamente. Inoltre, non è necessario per create()l'oggetto AlertDialog prima di chiamare show()(può essere chiamato sul Builder), e poiché show()restituisce l'oggetto dialog, findViewById(android.R.id.message)può essere incatenato. Avvolgi tutto in un tentativo-catch nel caso in cui la visualizzazione del messaggio non sia un TextView e tu abbia una formulazione concisa.
Pierre-Luc Paour,

50

Questo dovrebbe rendere anche i <a href>tag da evidenziare. Nota che ho appena aggiunto alcune righe al codice di emmby. quindi merito a 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());

10
Se usi html in strings.xml, non è necessario utilizzare Html.fromHtml. setMessage(R.string.cool_link)funziona con<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii il

2
Questo è vero. Quando si combinano entrambi i metodi (Html.fromHtml e tag HTML in strings.xml) non funziona.
JerabekJakub,

È passato un po 'di tempo e fromHtml è obsoleto, e adesso?
Menasheh,

Puoi ancora usare da HTML: developer.android.com/reference/android/text/… , int) Usa semplicementeHtml.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB

2
setMovementMethod()è la parte importante qui, altrimenti l'URL non sarà cliccabile.
scai,

13

In realtà, se vuoi semplicemente usare una stringa senza occuparti di tutte le viste, il modo più veloce è trovare la visualizzazione del testo del messaggio e collegarla:

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

12

JFTR, ecco che arriva la soluzione che ho capito dopo qualche tempo:

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

Il corrispondente about.xml preso in prestito come frammento dalle fonti Android è simile al seguente:

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

Le parti importanti sono l'impostazione di linksClickable su true e setMovementMethod (LinkMovementMethod.getInstance ()).


Grazie, questo ha risolto il problema per me. Nel mio caso, non era necessario setLinksClickable(true)(credo che lo fosse già), ma ha setMovementMethod(...)fatto la differenza.
LarsH,

10

Invece di ...

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

... ora uso:

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

Ehi, il tuo soln funziona. sai perché l'intera visualizzazione del testo lampeggia quando si fa clic sul collegamento?
aimango

Non scorre come quello predefinito.
Meow Cat 2012,

7

Il modo più semplice:

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

6

Tutta la risposta di cui sopra non rimuoverà tag html come, ecc. Se la stringa fornita contiene, ho provato a rimuovere tutti i tag, e questo funziona bene per 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();

e custom_dialog sarebbe come;

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

Il codice sopra rimuoverà tutto il tag html e mostra Esempio come URL in grado di fare clic su tutti gli altri nel testo di formattazione html specificato.


5

Non ero molto soddisfatto delle risposte attuali. Ci sono due cose che sono importanti quando vuoi collegamenti ipertestuali cliccabili in stile href con un AlertDialog:

  1. Imposta il contenuto come Visualizza e non con setMessage(…), poiché solo le Viste consentono il contenuto HTML selezionabile
  2. Imposta il metodo di movimento corretto ( setMovementMethod(…))

Ecco un esempio minimo funzionante:

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

3

Ho controllato molte domande e risposte, ma non funziona. L'ho fatto da solo. Questo è lo snippet di codice su 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());

    ....
}

Metti questo tag su res \ valori \ String.xml

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

2

Ho combinato alcune delle opzioni discusse sopra per creare questa funzione che funziona per me. passare il risultato al metodo SetView () del builder di dialog.

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

2

Se si utilizza a DialogFragment, questa soluzione dovrebbe aiutare.

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

Se si imposta SpannableString come messaggio della finestra di dialogo, il collegamento viene evidenziato, ma non è selezionabile.
bk138,

@ bk138 La chiamata a .setMovementMethod () in onStart () è ciò che rende selezionabile il collegamento.
tronman,

2

Per me la migliore soluzione per creare una finestra di dialogo sulla privacy è:

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

controlla l'esempio funzionante: link dell'app


1

Lo faccio specificando la casella di avviso in una risorsa XML e caricandola. Vedere ad esempio about.xml (consultare l'id ABOUT_URL) che viene istanziato verso la fine di ChandlerQE.java . Le parti rilevanti dal codice 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)

il link è morto, puoi sistemarlo?
Bijoy Thangaraj,

1

Questa è la mia soluzione Crea un collegamento normale senza tag html coinvolti e senza alcun URL visibile. Mantiene anche intatto il design.

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
Grazie, solo per aggiungere setSpan (URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE). Qui startPoint ed endPoint sono le parole che verranno evidenziate facendo clic su
Manish,

0

Il modo più semplice e più breve è così

Collegamento Android nella finestra di dialogo

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

Puoi dirmi come fare a Kotlin?
Thomas Williams,

Mi dispiace. Non conosco Kotlin
Javier Castellanos Cruz il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.