如何从字符串资源中获取可点击的超链接,并在AlertDialog中实现?

143

我的目标是让AlertDialog中显示的消息文本中有可点击的超链接。虽然AlertDialog实现可以很好地为任何超链接(在传递给Builder.setMessage的字符串资源中使用<a href="...">进行定义)添加下划线和颜色,但这些链接无法被点击。

我当前正在使用的代码如下:

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(...)会返回一个保留HTML格式的android.text.Spanned。但是一旦你将其转换为字符串,魔法就消失了。 - Thilo-Alexander Ginkel
19个回答

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>

3
如果您正在使用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
我结合了上面讨论的一些选项,得出了这个对我有效的函数。将结果传递给对话框生成器的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

简单的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()
        }

这个解决方案很棒,但我认为它在Android 13上不再起作用了。 - Jim Clermonts

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

1

我通过在 XML 资源中指定警告框并加载该资源来实现这一点。例如,参见 about.xml(请参阅 ABOUT_URL ID),该资源在 ChandlerQE.java 的末尾被实例化。以下是 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

0
AlertDialog中的可点击超链接
 /*Dialog Agreement*/
    private fun agreed() {
        if (agreed != "yes") {
            val inflater: LayoutInflater = this.layoutInflater
            val dialogView: View = inflater.inflate(R.layout.dialog_agreed, null)
            val btnAccept: TextView = dialogView.findViewById(R.id.btn_accept)
            val btnDecline: TextView = dialogView.findViewById(R.id.btn_decline)
            val txtMessage: TextView = dialogView.findViewById(R.id.txt_message)
            btnAccept.setOnClickListener {
                //Saving data to preference manager
                val sharedPref = getSharedPreferences("Janta24", Context.MODE_PRIVATE)
                val editor = sharedPref.edit()
                editor.putString("agreed", "yes")
                editor.apply()
                alertDialog.dismiss()
            }
            btnDecline.setOnClickListener {
                finish()
            }
            txtMessage.text = Html.fromHtml(
                "We have revised our<a href=\"http://app.janta24.in/term.html\">Terms of Use</a> & " +
                        "<a href=\"http://app.janta24.in/privacy.html\">Privacy Policy</a> " +
                        "By accepting, you agreed to our updated terms and policies. Please take few minutes to read and understand them."
            )
            txtMessage.movementMethod = LinkMovementMethod.getInstance()
            val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(this)
            dialogBuilder.setOnDismissListener { }
            dialogBuilder.setView(dialogView)
            dialogBuilder.setCancelable(false)
            alertDialog = dialogBuilder.create()
            alertDialog.show()
        }
    }

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>

帮助对话框类
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

预览

enter image description here


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接