Làm cách nào tôi có thể nhận được các siêu liên kết có thể nhấp trong AlertDialog từ tài nguyên chuỗi?


134

Những gì tôi đang cố gắng thực hiện là có các siêu liên kết có thể nhấp trong văn bản thông báo được hiển thị bởi một AlertDialog. Mặc dù việc AlertDialogtriển khai vui vẻ gạch chân và tô màu bất kỳ siêu liên kết nào (được xác định bằng cách sử dụng <a href="...">trong tài nguyên chuỗi được truyền đến Builder.setMessage) được cung cấp, các liên kết không thể trở thành có thể nhấp được.

Mã tôi hiện đang sử dụng trông như thế này:

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

Tôi muốn tránh sử dụng một WebViewđể chỉ hiển thị một đoạn văn bản.


Chào! Bạn có thực sự đạt được kết quả khai báo ("vui vẻ gạch chân và tô màu bất kỳ siêu liên kết nào") không? Giá trị chuỗi nào bạn đang vượt qua?
Maksym Gontar

1
Có, điều quan trọng là phải có thông báo được hiển thị trong tài nguyên chuỗi, mà Resources.getText (...) trả về dưới dạng android.text.Spned giữ định dạng HTML. Tuy nhiên, ngay khi bạn chuyển đổi nó thành Chuỗi, ma thuật sẽ biến mất.
Thilo-Alexander Ginkel

Câu trả lời:


128

Nếu bạn chỉ hiển thị một số văn bản và URL [s] trong hộp thoại của mình thì có lẽ giải pháp đơn giản hơn

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

Như được hiển thị ở đây http://picasaweb.google.com/lh/photo/up29wTQeK_zuz-LLvre9wQ?feat=directlink

Hộp thoại cảnh báo với các liên kết có thể nhấp


1
bạn có thể muốn tạo một tệp bố cục và thổi phồng nó và sử dụng nó làm dạng xem.
Jeffrey Blattman

5
Làm thế nào bạn có thể đặt kiểu của textView để khớp với kiểu được sử dụng theo mặc định?
nhà phát triển Android

3
Sau đó, tôi đang gặp lỗiCalling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
ViliusK

206

Tôi không thực sự thích câu trả lời phổ biến nhất hiện nay vì nó thay đổi đáng kể định dạng của tin nhắn trong hộp thoại.

Đây là một giải pháp sẽ liên kết văn bản hộp thoại của bạn mà không thay đổi kiểu văn bản:

    // 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
Chúc mừng, làm việc cho tôi từ bên trong onCreateDialoga DialogFragment. Chỉ cần đặt mã có thể nhấp theo onStartyêu cầu showđã được gọi để gọi DialogFragment
PJL

5
Điều này dường như làm cho toàn bộ TextView có thể nhấp được thay vì chỉ các liên kết ... Có cách nào khác không?
Kavi

1
Tôi đồng ý rằng đây là một lựa chọn tốt hơn nhiều vì câu trả lời ban đầu đang làm rối hộp thoại một cách trực quan.
hcpl

1
Chế độ xem được trả về bởi findViewById nên được kiểm tra bằng "instanceof TextView", vì không có gì đảm bảo rằng việc triển khai sẽ không thay đổi.
Denis Gladkiy

6
Như đã chỉ ra ở nơi khác, nếu sử dụng setMessage(R.string.something), không cần thiết phải liên kết rõ ràng. create()Đối tượng AlertDialog cũng không cần thiết trước khi gọi show()(nó có thể được gọi trên Builder) và vì show()trả về đối tượng hộp thoại, nên findViewById(android.R.id.message)có thể bị xích. Gói tất cả trong một lần thử chỉ trong trường hợp chế độ xem tin nhắn không phải là TextView và bạn có một công thức ngắn gọn.
Pierre-Luc Paour

50

Điều này sẽ làm cho <a href>các thẻ để được làm nổi bật là tốt. Xin lưu ý rằng tôi vừa thêm một vài dòng vào mã của emmby. rất tin tưởng anh ấy

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
Nếu bạn sử dụng html trong chuỗi XML, bạn không cần sử dụng Html.fromHtml. setMessage(R.string.cool_link)làm việc với<string name="cool_link"><a href="http://www.google.com">Check this link out</a></string>
idbrii

2
Điều đó đúng. Khi bạn kết hợp cả hai phương thức (thẻ Html.fromHtml và HTML trong chuỗi DOM), nó không hoạt động.
JerabekJakub

Đã được một thời gian và fromHtml không được dùng nữa, bây giờ thì sao?
Menasheh

Bạn vẫn có thể sử dụng fromHtml: developer.android.com/reference/android/text/iêu , int) Đơn giản chỉ cần sử dụngHtml.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB

2
setMovementMethod()là phần quan trọng ở đây, nếu không URL sẽ không thể nhấp được.
scai

13

Trên thực tế, nếu bạn chỉ muốn sử dụng một chuỗi mà không xử lý tất cả các khung nhìn, cách nhanh nhất là tìm textview tin nhắn và liên kết nó:

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

12

JFTR, đây là giải pháp mà tôi đã tìm ra sau một thời gian:

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

AboutDB tương ứng được mượn dưới dạng một đoạn từ các nguồn Android trông như thế này:

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

Các phần quan trọng là thiết lập linksClickable thành true và setMovementMethod (LinkMovementMethod.getInstance ()).


Cảm ơn bạn, điều này đã giải quyết vấn đề cho tôi. Trong trường hợp của tôi, nó không cần thiết setLinksClickable(true)(tôi đoán nó đã như vậy), nhưng setMovementMethod(...)đã tạo ra sự khác biệt.
LarsH

10

Thay vì ...

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

... Bây giờ tôi sử dụng:

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

Hey, soln của bạn hoạt động. Bạn có biết tại sao toàn bộ textview nhấp nháy khi nhấp vào liên kết không?
aimango

Nó không cuộn giống như mặc định.
Mèo Meow 2012

7

Cách đơn giản nhất:

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

Tất cả các câu trả lời ở trên sẽ không xóa thẻ html như, v.v. nếu chuỗi đã cho chứa, tôi đã cố xóa tất cả các thẻ và điều này hoạt động tốt với tôi

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

và custom_dialog sẽ như thế nào;

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

Đoạn mã trên sẽ xóa tất cả các thẻ html và hiển thị Ví dụ như URL có thể nhấp vào tất cả các thẻ khác trong văn bản định dạng html được chỉ định.


5

Tôi không thực sự hài lòng với câu trả lời hiện tại. Có hai điều quan trọng khi bạn muốn các siêu liên kết có thể nhấp theo kiểu href với AlertDialog:

  1. Đặt nội dung là Chế độ xem và không với setMessage(…), vì chỉ Chế độ xem mới cho phép nội dung HTML có thể nhấp
  2. Đặt phương thức di chuyển đúng ( setMovementMethod(…))

Đây là một ví dụ tối thiểu làm việc:

chuỗi DOM

<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

Tôi đã kiểm tra nhiều câu hỏi và câu trả lời, nhưng nó không hoạt động. Tôi đã tự làm điều đó. Đây là đoạn mã trên 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());

    ....
}

Đặt thẻ này vào res \ value \ 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

Tôi đã kết hợp một số tùy chọn được thảo luận ở trên để đưa ra chức năng này phù hợp với tôi. chuyển kết quả cho phương thức SetView () của trình tạo hộp thoại.

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

Nếu bạn đang sử dụng một DialogFragment, giải pháp này sẽ giúp.

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

Nếu bạn đặt SpannableString làm thông báo của hộp thoại, liên kết sẽ được tô sáng, nhưng không thể nhấp được.
bk138

@ bk138 Cuộc gọi đến .setMovementMethod () trong onStart () là điều làm cho liên kết có thể nhấp được.
tronman

2

Đối với tôi giải pháp tốt nhất để tạo hộp thoại chính sách bảo mật là:

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

kiểm tra ví dụ làm việc: liên kết ứng dụng


1

Tôi làm điều này bằng cách chỉ định hộp cảnh báo trong tài nguyên XML và tải nó. Xem ví dụ về about.xml (xem id GIỚI THIỆU ) được khởi tạo gần cuối ChandlerQE.java . Các phần có liên quan từ mã 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)

Liên kết đã chết, bạn có thể sửa nó không?
Bijoy Thangaraj

1

Đây là giải pháp của tôi. Nó tạo ra một liên kết bình thường mà không có thẻ html liên quan và không có bất kỳ URL nào hiển thị. Nó cũng giữ cho thiết kế nguyên vẹn.

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
Cảm ơn, Chỉ cần thêm setSpan (URL, startpoint, endPoint, Spned.SPAN_EXCLUSIVE_EXCLUSIVE). Ở đây startpoint và endPoint là những từ sẽ được tô sáng để nhấp
Manish

0

Cách dễ nhất và ngắn nhất là như thế này

Liên kết Android trong hộp thoại

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

Bạn có thể cho tôi biết làm thế nào để làm điều này trong Kotlin?
Thomas Williams

Tôi xin lỗi. Tôi không biết Kotlin
Javier Castellanos Cruz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.