Wie kann ich aus einer Zeichenfolgenressource anklickbare Hyperlinks in AlertDialog abrufen?

134

Ich versuche, anklickbare Hyperlinks im Nachrichtentext zu haben, die von einem angezeigt werden AlertDialog. Während die AlertDialogImplementierung alle Hyperlinks (die <a href="...">in der übergebenen Zeichenfolgenressource definiert wurden) gerne unterstreicht und einfärbt, können Builder.setMessagedie angegebenen Links nicht angeklickt werden.

Der Code, den ich derzeit verwende, sieht folgendermaßen aus:

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

Ich möchte vermeiden, ein WebViewzu verwenden, um nur einen Textausschnitt anzuzeigen.

Thilo-Alexander Ginkel
quelle
Hallo! Erzielen Sie wirklich deklarierte Ergebnisse ("unterstreicht und färbt Hyperlinks gerne")? Welchen String-Wert übergeben Sie?
Maksym Gontar
1
Ja, der Schlüssel besteht darin, dass die Nachricht in einer Zeichenfolgenressource angezeigt wird, die Resources.getText (...) als android.text.Spanned unter Beibehaltung der HTML-Formatierung zurückgibt. Sobald Sie es jedoch in einen String konvertieren, verschwindet die Magie.
Thilo-Alexander Ginkel

Antworten:

128

Wenn Sie in Ihrem Dialogfeld nur Text und URLs anzeigen, ist die Lösung möglicherweise einfacher

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

Wie hier gezeigt: http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Warndialog mit anklickbaren Links

Diego Torres Milano
quelle
1
Sie möchten wahrscheinlich eine Layoutdatei erstellen, diese aufblasen und als Ansicht verwenden.
Jeffrey Blattman
5
Wie würden Sie den Stil der Textansicht so einstellen, dass er dem standardmäßig verwendeten entspricht?
Android-Entwickler
3
Dann bekomme ich FehlerCalling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
ViliusK
206

Die derzeit beliebteste Antwort hat mir nicht wirklich gefallen, da sie die Formatierung der Nachricht im Dialogfeld erheblich ändert.

Hier ist eine Lösung, mit der Sie Ihren Dialogtext verknüpfen können, ohne das Textformat zu ändern:

    // 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
quelle
5
Prost, arbeitete für mich aus onCreateDialogeinem DialogFragment. Musste nur anklickbaren Code setzen onStart, showder aufgerufen wurde, um das DialogFragment
PJL
5
Dies scheint die gesamte Textansicht anklickbar zu machen und nicht nur die Links ... Wie kann man das umgehen?
Kavi
1
Ich bin damit einverstanden, dass dies eine weitaus bessere Option ist, da die ursprüngliche Antwort den Dialog visuell durcheinander bringt.
hcpl
1
Die von findViewById zurückgegebene Ansicht sollte mit "instanceof TextView" überprüft werden, da nicht garantiert werden kann, dass sich die Implementierung nicht ändert.
Denis Gladkiy
6
Wie bereits an anderer Stelle erwähnt, ist bei Verwendung setMessage(R.string.something)keine explizite Verknüpfung erforderlich. Es ist auch nicht erforderlich, create()das AlertDialog-Objekt vor dem Aufruf aufzurufen show()(es kann im Builder aufgerufen werden), und da show()das Dialogobjekt zurückgegeben wird, findViewById(android.R.id.message)kann das verkettet werden. Wickeln Sie alles in einen Try-Catch ein, nur für den Fall, dass die Nachrichtenansicht keine Textansicht ist und Sie eine präzise Formulierung haben.
Pierre-Luc Paour
50

Dadurch sollten auch <a href>Tags hervorgehoben werden. Bitte beachten Sie, dass ich gerade ein paar Zeilen zu embyys Code hinzugefügt habe. so danke ihm

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
quelle
10
Wenn Sie HTML in strings.xml verwenden, müssen Sie Html.fromHtml nicht verwenden. setMessage(R.string.cool_link)arbeitet mit<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii
2
Das ist wahr. Wenn Sie beide Methoden kombinieren (Html.fromHtml und HTML-Tag in strings.xml), funktioniert dies nicht.
JerabekJakub
Es ist schon eine Weile her und fromHtml ist veraltet, was nun?
Menasheh
Sie können weiterhin fromHtml verwenden: developer.android.com/reference/android/text/… , int) Einfach verwendenHtml.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB
2
setMovementMethod()ist hier der wichtige Teil, sonst kann die URL nicht angeklickt werden.
Scai
13

Wenn Sie einfach eine Zeichenfolge verwenden möchten, ohne alle Ansichten zu bearbeiten, ist es am schnellsten, die Textansicht der Nachricht zu finden und zu verknüpfen:

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

JFTR, hier kommt die Lösung, die ich nach einiger Zeit herausgefunden habe:

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

Die entsprechende about.xml, die als Fragment aus den Android-Quellen ausgeliehen wurde, sieht folgendermaßen aus:

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

Die wichtigen Teile sind das Setzen von linksClickable auf true und setMovementMethod (LinkMovementMethod.getInstance ()).

Thilo-Alexander Ginkel
quelle
Danke, das hat das Problem für mich gelöst. In meinem Fall war das nicht nötig setLinksClickable(true)(ich denke, das war es schon), aber es setMovementMethod(...)machte den Unterschied.
LarsH
10

Anstatt ...

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

... ich benutze jetzt:

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
quelle
Hey, deine Lösung funktioniert. Wissen Sie, warum die gesamte Textansicht blinkt, wenn Sie auf den Link klicken?
Aimango
Es wird nicht wie in der Standardeinstellung gescrollt.
Meow Cat 2012
7

Einfachster Weg:

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
quelle
6

Alle oben genannten Antworten entfernen keine HTML-Tags wie usw. Wenn die angegebene Zeichenfolge enthält, habe ich versucht, alle Tags zu entfernen, und dies funktioniert gut für mich

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

und der custom_dialog wäre wie;

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

Der obige Code entfernt das gesamte HTML-Tag und zeigt Beispiel als klickfähige URL aller anderen im angegebenen HTML-Formatierungstext an.

Lakshmanan
quelle
5

Mit den aktuellen Antworten war ich nicht wirklich zufrieden. Es gibt zwei Dinge, die wichtig sind, wenn Sie mit einem AlertDialog anklickbare Hyperlinks im href-Stil wünschen:

  1. Legen Sie den Inhalt als Ansicht und nicht mit fest setMessage(…), da nur Ansichten anklickbaren HTML-Inhalt zulassen
  2. Stellen Sie die richtige Bewegungsmethode ein ( setMovementMethod(…))

Hier ist ein funktionierendes Minimalbeispiel:

string.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()
}
Fließen
quelle
3

Ich habe viele Fragen und Antworten überprüft, aber es funktioniert nicht. Ich habe es selbst gemacht. Dies ist das Code-Snippet auf 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());

    ....
}

Setzen Sie dieses Tag in 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
quelle
2

Ich habe einige der oben beschriebenen Optionen kombiniert, um diese Funktion zu entwickeln, die für mich funktioniert. Übergeben Sie das Ergebnis an die SetView () -Methode des Dialog-Builders.

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
quelle
2

Wenn Sie a verwenden DialogFragment, sollte diese Lösung helfen.

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
quelle
Wenn Sie den SpannableString als Dialognachricht festlegen, wird der Link hervorgehoben, kann jedoch nicht angeklickt werden.
bk138
@ bk138 Der Aufruf von .setMovementMethod () in onStart () macht den Link anklickbar.
Tronman
2

Für mich ist die beste Lösung zum Erstellen eines Datenschutzdialogs:

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

Überprüfen Sie das Arbeitsbeispiel: App-Link

Günstling
quelle
1

Dazu gebe ich das Warnfeld in einer XML-Ressource an und lade es. Siehe zum Beispiel die Datei about.xml (siehe die ID ABOUT_URL), die gegen Ende von ChandlerQE.java instanziiert wird . Die relevanten Teile aus dem 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)
Heikki Toivonen
quelle
Link ist tot, kannst du das beheben?
Bijoy Thangaraj
1

Das ist meine Lösung. Es wird ein normaler Link ohne HTML-Tags und ohne sichtbare URL erstellt. Es hält auch das Design intakt.

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.
quelle
1
Vielen Dank, nur um setSpan hinzuzufügen (URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE). Hier sind Startpunkt und Endpunkt Wörter, die zum Klicken hervorgehoben werden
Manish
0

Der einfachste und kürzeste Weg ist so

Android-Link im 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());
Javier Castellanos Cruz
quelle
Können Sie mir sagen, wie das in Kotlin geht?
Thomas Williams
Tut mir leid. Ich kenne Kotlin nicht
Javier Castellanos Cruz