如何从字符串资源获取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();

我想避免只使用a WebView来显示文本片段。


嗨!您是否真的完成了声明的结果(“在所有超链接下划线并涂上颜色”)?您传递什么字符串值?
Maksym Gontar

1
是的,关键是要在字符串资源中显示消息,Resources.getText(...)作为android.text.Spanned返回,并保留HTML格式。但是,一旦将其转换为字符串,魔术就消失了。
Thilo-Alexander Ginkel,2010年

Answers:


128

如果您仅在对话框中显示一些文本和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
您可能想要创建一个布局文件并对其进行充气并将其用作视图。
杰弗里·布拉特曼

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,2016年

206

我不太喜欢当前最流行的答案,因为它大大改变了对话框中消息的格式。

这是一个解决方案,它将链接您的对话框文本,而无需更改文本样式:

    // 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
欢呼声中,从内部为我工作onCreateDialogDialogFragment。刚刚在设置点击代码,onStart因为show已被叫到调用DialogFragment
PJL

5
这似乎使整个TextView都可以单击,而不是仅单击链接。
卡维2012年

1
我同意这是一个更好的选择,因为原始答案在视觉上使对话框变得混乱。
hcpl 2012年

1
由findViewById返回的视图应使用“ instanceof TextView”进行检查,因为不能保证实现不会更改。
Denis Gladkiy 2014年

6
如在其他地方指出的,如果使用setMessage(R.string.something),则无需显式链接。也没有必要create()调用之前 AlertDialog对象进行调用show()(可以在Builder上调用它),并且由于show()返回了对话框对象,因此findViewById(android.R.id.message)可以将其链接起来。如果消息视图不是TextView,并且使用简洁的格式,则将所有内容包装在try-catch中。
Pierre-Luc Paour 2014年

50

这也应该使<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
如果您在strings.xml中使用html,则无需使用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和strings.xml中的HTML标记)时,它将不起作用。
JerabekJakub 2014年

已经有一段时间了,fromHtml被弃用了,现在呢?
Menasheh '16

您仍然可以使用fromHtml:developer.android.com/reference/android/text/…、int)简单使用Html.fromHtml("string with links", Html.FROM_HTML_MODE_LEGACY)
BVB

2
setMovementMethod()是此处的重要部分,否则该URL将不可单击。
scai 2016年

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看起来像这样:

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

重要的部分是将linksClickable设置为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);

嘿,你的工作原理。您知道为什么单击链接时整个textview闪烁吗?
aimango 2012年

它不会像默认滚动条那样滚动。
猫喵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标记,并在指定的html格式文本中将“其他示例”显示为“可点击的URL”。


5

我对当前的答案并不真正满意。当您需要带有AlertDialog的href样式的可单击超链接时,有两点很重要:

  1. 将内容设置为“查看”而不是 setMessage(…),因为只有View允许可点击的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()
}

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

如果您使用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 onStart()中对.setMovementMethod()的调用使链接可单击。
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资源中指定警报框并加载该框来做到这一点。例如,参见在ChandlerQE.java末尾实例化的about.xml(请参阅ABOUT_URL id)。来自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)

链接已消失,您可以修复它吗?
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)。这里的startPoint和endPoint是要点选以突出显示的单词
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

对不起。我不知道科特林
哈维尔·卡斯特拉诺斯·克鲁兹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.