ฉันจะรับไฮเปอร์ลิงก์ที่คลิกได้ใน AlertDialog จากทรัพยากรสตริงได้อย่างไร


134

สิ่งที่ฉันพยายามทำให้สำเร็จคือการมีไฮเปอร์ลิงก์ที่คลิกได้ในข้อความที่แสดงโดยAlertDialogไฟล์. ในขณะที่AlertDialogการนำไปใช้ขีดเส้นใต้และระบายสีไฮเปอร์ลิงก์อย่างมีความสุข (กำหนดโดยใช้<a href="...">ในทรัพยากรสตริงที่ส่งผ่านไปยังBuilder.setMessage) ให้ลิงก์ไม่สามารถคลิกได้

รหัสที่ฉันใช้ในปัจจุบันมีลักษณะดังนี้:

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

ฉันต้องการหลีกเลี่ยงการใช้WebViewเพื่อแสดงข้อมูลโค้ด


ไฮ! คุณบรรลุผลลัพธ์ที่ประกาศไว้จริง ๆ ("ขีดเส้นใต้และระบายสีไฮเปอร์ลิงก์อย่างมีความสุข") หรือไม่ คุณส่งค่าสตริงอะไร
Maksym Gontar

1
ใช่กุญแจสำคัญคือการมีข้อความที่จะแสดงในทรัพยากรสตริงซึ่ง Resources.getText (... ) จะส่งกลับเป็น android.text.Spanned รักษาการจัดรูปแบบ HTML ทันทีที่คุณแปลงเป็น String เวทมนตร์จะหายไป
Thilo-Alexander Ginkel

คำตอบ:


130

หากคุณแสดงเฉพาะข้อความและ URL บางรายการในกล่องโต้ตอบของคุณการแก้ปัญหาอาจจะง่ายกว่านี้

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

ดังที่แสดงไว้ที่นี่ http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

กล่องโต้ตอบการแจ้งเตือนพร้อมลิงก์ที่คลิกได้


1
คุณอาจต้องการสร้างไฟล์เลย์เอาต์และขยายและใช้เป็นมุมมอง
Jeffrey Blattman

5
คุณจะตั้งค่าสไตล์ของ textView ให้ตรงกับรูปแบบที่ใช้โดยค่าเริ่มต้นได้อย่างไร?
นักพัฒนา Android

3
จากนั้นฉันได้รับข้อผิดพลาดCalling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
ViliusK

208

ฉันไม่ชอบคำตอบที่ได้รับความนิยมมากที่สุดในปัจจุบันเพราะมันเปลี่ยนรูปแบบของข้อความในกล่องโต้ตอบอย่างมาก

นี่คือวิธีแก้ปัญหาที่จะเชื่อมโยงข้อความโต้ตอบของคุณโดยไม่ต้องเปลี่ยนรูปแบบข้อความ:

    // 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
ไชโยทำงานให้ฉันจากภายในของonCreateDialog DialogFragmentเพียงแค่ต้องตั้งรหัสที่คลิกได้ตามonStartที่showได้รับการเรียกให้เรียกใช้ DialogFragment
PJL

5
ดูเหมือนว่าจะทำให้ TextView ทั้งหมดคลิกได้เมื่อเทียบกับลิงก์เพียงอย่างเดียว ...
Kavi

1
ฉันยอมรับว่านี่เป็นตัวเลือกที่ดีกว่ามากเนื่องจากคำตอบเดิมทำให้กล่องโต้ตอบสับสน
hcpl

1
มุมมองที่ส่งคืนโดย findViewById ควรตรวจสอบด้วย "instanceof TextView" เนื่องจากไม่มีการรับประกันว่าการใช้งานจะไม่เปลี่ยนแปลง
Denis Gladkiy

6
ตามที่ระบุไว้ที่อื่นหากใช้setMessage(R.string.something)ไม่จำเป็นต้องเชื่อมโยงอย่างชัดเจน นอกจากนี้ยังไม่จำเป็นสำหรับcreate()ออบเจ็กต์ AlertDialog ก่อนที่จะเรียกshow()(สามารถเรียกบน Builder) และเนื่องจากshow()ส่งคืนวัตถุโต้ตอบจึงfindViewById(android.R.id.message)สามารถถูกล่ามโซ่ได้ สรุปทั้งหมดด้วยการลองจับในกรณีที่มุมมองข้อความไม่ใช่ TextView และคุณมีสูตรที่กระชับ
Pierre-Luc Paour

51

สิ่งนี้ควรทำให้<a href>แท็กถูกไฮไลต์ด้วย โปรดทราบว่าฉันเพิ่งเพิ่มไปไม่กี่บรรทัดในรหัสของ emmby ให้เครดิตกับเขา

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
หากคุณใช้ html ใน strings.xml คุณไม่จำเป็นต้องใช้ Html.fromHtml setMessage(R.string.cool_link)ทำงานร่วมกับ<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii

2
มันเป็นความจริง. เมื่อคุณรวมทั้งสองวิธี (Html.fromHtml และแท็ก HTML ใน strings.xml) จะไม่ได้ผล
JerabekJakub

เป็นเวลานานแล้วและ fromHtml เลิกใช้แล้วตอนนี้คืออะไร?
Menasheh

คุณยังสามารถใช้ได้ fromHtml: developer.android.com/reference/android/text/… , int) เพียงใช้Html.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB

2
setMovementMethod()เป็นส่วนสำคัญที่นี่มิฉะนั้น URL จะไม่สามารถคลิกได้
scai

13

อันที่จริงหากคุณต้องการใช้สตริงโดยไม่ต้องจัดการกับมุมมองทั้งหมดวิธีที่เร็วที่สุดคือค้นหา textview ข้อความและเชื่อมโยง:

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

12

JFTR นี่คือวิธีแก้ปัญหาที่ฉันคิดออกหลังจากเวลาผ่านไป:

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 ที่เกี่ยวข้องที่ยืมมาเป็นส่วนย่อยจากแหล่งที่มาของ Android มีลักษณะดังนี้:

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

ส่วนที่สำคัญคือการตั้งค่า linkClickable เป็น true และ setMovementMethod (LinkMovementMethod.getInstance ())


ขอบคุณสิ่งนี้ช่วยแก้ปัญหาให้ฉันได้ ในกรณีของฉันมันไม่จำเป็นต้องsetLinksClickable(true)(ฉันเดาว่ามันเป็นอยู่แล้ว) แต่setMovementMethod(...)สร้างความแตกต่างทั้งหมด
LarsH

10

แทน ...

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

... ตอนนี้ฉันใช้:

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

เฮ้ Soln ของคุณได้ผล คุณรู้หรือไม่ว่าเหตุใดมุมมองข้อความทั้งหมดจึงกะพริบเมื่อคลิกที่ลิงก์
aimango

มันไม่เลื่อนเหมือนค่าเริ่มต้น
แมวเหมียว 2012

7

วิธีที่ง่ายที่สุด:

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

คำตอบทั้งหมดข้างต้นจะไม่ลบแท็ก html เช่น ฯลฯ หากสตริงที่ระบุมีฉันพยายามลบแท็กทั้งหมดและมันก็ใช้ได้ดีสำหรับฉัน

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

และ custom_dialog จะเป็นเช่นนั้น

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

โค้ดด้านบนจะลบแท็ก html ทั้งหมดและแสดง Example as Click able URL อื่น ๆ ทั้งหมดในข้อความการจัดรูปแบบ html ที่ระบุ


5

ฉันไม่ค่อยพอใจกับคำตอบในปัจจุบัน มีสองสิ่งที่สำคัญเมื่อคุณต้องการไฮเปอร์ลิงก์ที่คลิกได้ในรูปแบบ href โดยใช้ AlertDialog:

  1. ตั้งค่าเนื้อหาเป็น View และไม่ใช่ด้วยsetMessage(…)เนื่องจาก Views เท่านั้นที่อนุญาตให้มีเนื้อหา HTML ที่คลิกได้
  2. ตั้งค่าวิธีการเคลื่อนไหวที่ถูกต้อง ( setMovementMethod(…))

นี่คือตัวอย่างขั้นต่ำที่ใช้งานได้:

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

วิธีนี้ใช้งานได้อย่างสมบูรณ์ แต่ข้อความในการแจ้งเตือนจะเริ่มจากด้านซ้ายสุดโดยไม่มีช่องว่างใด ๆ คุณสามารถปรับได้ง่ายๆด้วยtextView.setPadding()
Mike

3

ฉันได้ตรวจสอบคำถามและคำตอบมากมาย แต่ไม่ได้ผล ฉันทำมันด้วยตัวเอง นี่คือข้อมูลโค้ดบน 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());

    ....
}

ใส่แท็กนี้ใน 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>

2

ฉันรวมตัวเลือกบางอย่างที่กล่าวถึงข้างต้นเพื่อให้ได้ฟังก์ชันนี้ที่เหมาะกับฉัน ส่งผลลัพธ์ไปยังเมธอด SetView () ของตัวสร้างไดอะล็อก

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

หากคุณใช้ a DialogFragmentวิธีนี้น่าจะช่วยได้

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

หากคุณตั้งค่า SpannableString เป็นข้อความของกล่องโต้ตอบลิงก์จะถูกไฮไลต์ แต่คลิกไม่ได้
bk138

@ bk138 การเรียกไปที่. setMovementMethod () ใน onStart () คือสิ่งที่ทำให้ลิงก์คลิกได้
tronman

2

สำหรับฉันทางออกที่ดีที่สุดในการสร้างกล่องโต้ตอบนโยบายความเป็นส่วนตัวคือ:

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

ตรวจสอบตัวอย่างการทำงาน: ลิงค์แอป


1

ฉันทำได้โดยระบุกล่องแจ้งเตือนในทรัพยากร XML และโหลดสิ่งนั้น ดูตัวอย่างabout.xml (ดูรหัส ABOUT_URL) ที่ได้รับการ instantiated ใกล้ถึงจุดสิ้นสุดของChandlerQE.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)

link ตายแล้วแก้ไขได้ไหม
Bijoy Thangaraj

1

นี่คือทางออกของฉัน จะสร้างลิงก์ปกติโดยไม่มีแท็ก html เกี่ยวข้องและไม่มี URL ที่มองเห็นได้ อีกทั้งยังคงดีไซน์ไว้เหมือนเดิม

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
ขอขอบคุณเพียงเพิ่ม setSpan (URL, startPoint, endPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) จุดเริ่มต้นและจุดสิ้นสุดคือคำที่จะไฮไลต์สำหรับการคลิก
Manish

0

วิธีที่ง่ายและสั้นที่สุดคือแบบนี้

ลิงก์ Android ในกล่องโต้ตอบ

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

ช่วยบอกวิธีทำใน Kotlin ได้ไหม?
Thomas Williams

ฉันขอโทษ. ฉันไม่รู้จัก Kotlin
Javier Castellanos Cruz

0

นี่เป็นวิธีง่ายๆที่ฉันใช้

สตริงใน strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <string name="credits_title">Credits</string>
    <string name="confirm">OK</string>
    <string name="credits">All rights reserved.
         <a href="https://google.com">Source</a>
    </string>
</resources>

ขนาดใน dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <dimen name="margin_8dp">8dp</dimen>
    <dimen name="margin_32dp">32dp</dimen>
</resources>

คลาส Helper Dialog

public class MessageHelper {

    public static void showCreditsDialog(Context context) {

        AlertDialog alertDialog = new AlertDialog.Builder(context).create();
        alertDialog.setTitle(R.string.credits_title);
        TextView textView = new TextView(context);
        int padding = (int) context.getResources().getDimension(R.dimen.margin_32dp);
        int topPadding = (int) context.getResources().getDimension(R.dimen.margin_8dp);
        textView.setPadding(padding, topPadding, padding, 0);
        textView.setMovementMethod(LinkMovementMethod.getInstance());
        textView.setText(R.string.credits);
        alertDialog.setView(textView);

        alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, context.getResources().getString(R.string.confirm),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
        alertDialog.show();
    }
}

วิธีใช้

MessageHelper.showCreditsDialog(this); // this is the context

ดูตัวอย่าง

ป้อนคำอธิบายภาพที่นี่


0

ใช้งาน Kotlin ได้ง่าย

ทรัพยากรสตริง:

<string name="foo"><a href="https://www.google.com/">some link</a></string>

รหัส:

AlertDialog.Builder(context)
        .setMessage(R.string.foo)
        .show()
        .apply {
            findViewById<TextView>(android.R.id.message)
            ?.movementMethod = LinkMovementMethod.getInstance()
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.