Bagaimana saya bisa mendapatkan hyperlink yang dapat diklik di AlertDialog dari sumber daya string?

134

Apa yang saya coba capai adalah memiliki hyperlink yang dapat diklik dalam teks pesan yang ditampilkan oleh AlertDialog. Sementara AlertDialogimplementasi dengan senang hati menggarisbawahi dan mewarnai hyperlink apa pun (didefinisikan menggunakan <a href="...">sumber daya yang diteruskan ke string Builder.setMessage) yang disediakan tautan tidak menjadi dapat diklik.

Kode yang saya gunakan saat ini terlihat seperti ini:

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

Saya ingin menghindari menggunakan WebViewhanya menampilkan cuplikan teks.

Thilo-Alexander Ginkel
sumber
Hai! Apakah Anda benar-benar mencapai hasil yang dinyatakan ("dengan senang hati menggarisbawahi dan mewarnai hyperlink")? Nilai string apa yang Anda lewatkan?
Maksym Gontar
1
Ya, kuncinya adalah memiliki pesan untuk ditampilkan dalam sumber daya string, yang Resources.getText (...) kembali sebagai android.text. Direncanakan mempertahankan format HTML. Namun, segera setelah Anda mengonversinya menjadi sebuah String, sihirnya lenyap.
Thilo-Alexander Ginkel

Jawaban:

128

Jika Anda hanya menampilkan beberapa teks dan URL dalam dialog Anda, mungkin solusinya lebih sederhana

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

Seperti yang ditunjukkan di sini http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Dialog peringatan dengan tautan yang dapat diklik

Diego Torres Milano
sumber
1
Anda mungkin ingin membuat file tata letak dan mengembang dan menggunakannya sebagai tampilan.
Jeffrey Blattman
5
Bagaimana Anda mengatur gaya textView agar sesuai dengan yang digunakan secara default?
pengembang android
3
Lalu, saya mendapatkan kesalahanCalling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
ViliusK
207

Saya tidak terlalu menyukai jawaban yang paling populer saat ini karena itu secara signifikan mengubah format pesan dalam dialog.

Berikut adalah solusi yang akan menautkan teks dialog Anda tanpa mengubah gaya teks:

    // 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
sumber
5
Ceria, Bekerja untuk saya dari dalam onCreateDialogdari DialogFragment. Hanya harus menetapkan kode yang dapat diklik pada onStartdiberikan yang showtelah dipanggil untuk memohon DialogFragment
PJL
5
Ini tampaknya membuat seluruh TextView dapat diklik sebagai lawan dari hanya tautan ... Ada cara lain untuk mengatasi ini?
Kavi
1
Saya setuju ini adalah pilihan yang jauh lebih baik karena jawaban aslinya mengacaukan dialog secara visual.
hcpl
1
Tampilan dikembalikan oleh findViewById harus diperiksa dengan "instanceof TextView", karena tidak ada jaminan bahwa implementasi tidak akan berubah.
Denis Gladkiy
6
Seperti yang ditunjukkan di tempat lain, jika menggunakan setMessage(R.string.something), tidak perlu untuk secara eksplisit menghubungkan. Ini juga tidak perlu ke create()objek AlertDialog sebelum memanggil show()(dapat dipanggil pada Builder), dan karena itushow() mengembalikan objek dialog, maka findViewById(android.R.id.message)bisa dirantai. Bungkus semuanya dalam try-catch kalau-kalau tampilan pesan bukan TextView, dan Anda memiliki formulasi ringkas.
Pierre-Luc Paour
50

Ini juga harus membuat <a href>tag untuk disorot. Harap dicatat bahwa saya baru saja menambahkan beberapa baris ke kode emmby. begitu memuji dia

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
sumber
10
Jika Anda menggunakan html di strings.xml, Anda tidak perlu menggunakan Html.fromHtml. setMessage(R.string.cool_link)bekerja dengan<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii
2
Itu benar. Ketika Anda menggabungkan kedua metode (Html.fromHtml dan tag HTML di strings.xml) itu tidak berfungsi.
JerabekJakub
Sudah lama dan fromHtml sudah usang, sekarang apa?
Menasheh
Anda masih dapat menggunakan fromHtml: developer.android.com/reference/android/text/… , int) Cukup gunakanHtml.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB
2
setMovementMethod()adalah bagian penting di sini, jika tidak URL tidak akan dapat diklik.
scai
13

Sebenarnya, jika Anda hanya ingin menggunakan string tanpa berurusan dengan semua tampilan, cara tercepat adalah menemukan textview pesan dan menautkannya:

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

JFTR, inilah solusi yang saya temukan setelah beberapa waktu:

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

About.xml yang sesuai dipinjam sebagai fragmen dari sumber Android terlihat seperti ini:

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

Bagian-bagian penting adalah pengaturan linksClickable ke true dan setMovementMethod (LinkMovementMethod.getInstance ()).

Thilo-Alexander Ginkel
sumber
Terima kasih, ini menyelesaikan masalah untuk saya. Dalam kasus saya, itu tidak perlu setLinksClickable(true)(saya kira sudah), tetapi setMovementMethod(...)membuat semua perbedaan.
LarsH
10

Dari pada ...

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

... Saya sekarang menggunakan:

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
sumber
Hei, perusahaanmu bekerja. apakah Anda tahu mengapa seluruh tampilan teks berkedip saat mengklik tautan?
aimango
Itu tidak gulir seperti yang default.
Kucing Meow 2012
7

Cara termudah:

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

Semua jawaban di atas tidak akan menghapus tag html seperti, dll jika string yang diberikan berisi, saya mencoba untuk menghapus semua tag, dan ini berfungsi dengan baik untuk saya

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

dan custom_dialog akan seperti;

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

Kode di atas akan menghapus semua tag html dan menampilkan Contoh sebagai URL yang dapat diklik, semua yang lain dalam teks format html yang ditentukan.

Lakshmanan
sumber
5

Saya tidak benar-benar puas dengan jawaban saat ini. Ada dua hal yang penting ketika Anda ingin hyperlink yang dapat diklik dalam gaya href dengan AlertDialog:

  1. Tetapkan konten sebagai Tampilan dan bukan dengan setMessage(…), karena hanya Tampilan yang memungkinkan konten HTML yang dapat diklik
  2. Setel metode gerakan yang benar ( setMovementMethod(…))

Berikut adalah contoh minimal yang berfungsi:

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()
}
Mengalir
sumber
3

Saya sudah memeriksa banyak pertanyaan dan jawaban, tetapi tidak berhasil. Saya melakukannya sendiri. Ini adalah cuplikan kode di 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());

    ....
}

Letakkan tag ini di 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
sumber
2

Saya menggabungkan beberapa opsi yang dibahas di atas untuk menghasilkan fungsi yang sesuai untuk saya. meneruskan hasilnya ke metode SetView () pembangun 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;
}
Alex
sumber
2

Jika Anda menggunakan DialogFragment, solusi ini akan membantu.

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());
    }
}
tukang trem
sumber
Jika Anda mengatur SpannableString sebagai pesan dialog, tautan disorot, tetapi tidak dapat diklik.
bk138
@ bk138 Panggilan ke .setMovementMethod () di onStart () adalah apa yang membuat tautan dapat diklik.
tronman
2

Bagi saya solusi terbaik untuk membuat dialog kebijakan privasi adalah:

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

periksa contoh yang berfungsi: tautan aplikasi

Antek
sumber
1

Saya melakukan ini dengan menetapkan kotak peringatan di sumber XML dan memuatnya. Lihat misalnya about.xml (lihat id ABOUT_URL) yang akan dipakai di akhir ChandlerQE.java . Bagian yang relevan dari kode 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
sumber
tautan sudah mati, bisakah Anda memperbaikinya?
Bijoy Thangaraj
1

Ini solusi saya. Ini membuat tautan normal tanpa melibatkan tag html dan tanpa URL apa pun yang terlihat. Itu juga membuat desain tetap utuh.

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
sumber
1
Terima kasih, Hanya untuk menambahkan setSpan (URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE). Di sini startPoint dan endPoint adalah kata-kata yang akan disorot untuk mengklik
Manish
0

Cara termudah dan terpendek adalah seperti ini

Tautan Android dalam 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
sumber
Bisakah Anda memberi tahu saya cara melakukan ini di Kotlin?
Thomas Williams
Saya menyesal. Saya tidak tahu Kotlin
Javier Castellanos Cruz