Android 工作室将本地化资源中的字符串的一部分(在文本视图中)设为可点击的网址



我想将TextView文本的一部分变成可点击的Url,我知道我可以使用SpannableString通过使用这样的东西来实现可点击的部分

SpannableString mySpannableString = new SpannableString("a string");
ClickableSpan myClickableSpan = new ClickableSpan() {
    @Override
    public void onClick(View textView) {
        // do something
    }
    @Override
    public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setUnderlineText(false);
        }
};
mySpannableString.setSpan(myClickableSpan, 2, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

但是,如果我使用本地化资源中的字符串作为我的SpannableString,那么字符串的长度可能会有所不同,这意味着可以单击错误的字符集。我该怎么做?

我发现的只是两种次优方法。它仍然使用Spannable,但请听我说,因为我处于您所说的确切情况

首先,有你提到的方法,你可以通过一个巨大的语言开关语句并解决每个语言的跨度。当然,这很可怕,但这是确保正确跨度可点击的最准确方法。

例如

if (Locale.getDefault().getLanguage().contentEquals("en") {
    // spannable gets substring a,b
else if (Locale.getDefault().getLanguage().contentEquals("fr") {
    // spannable gets substring x,y
}

再次,不好。

现在,如果您的翻译人员可以处理分解为子字符串的字符串,IE

<string name=suba>Some intro text to</string>
<string name=sublinka>linkable A</string>
<string name=subb>and then some intro text to</string>
<string name=sublinka>linkable B</string>

然后,您可以通过编程方式构建 Spannable 字符串,如下所示:

TextView textView = (TextView) findViewById(R.id.text_view);
String subA = getString(R.string.suba);
String subLinkA = getString(R.string.sublinka);
String subB = getString(R.string.subb);
String subLinkB = getString(R.string.sublinkb);
SpannableStringBuilder spannableText = new 
SpannableStringBuilder(subA);
    spannableText.append(subLinkA);
    spannableText.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            Toast.makeText(this, "Sub Link A Clicked", Toast.LENGTH_SHORT).show();
        }
    }, spannableText.length() - subLinkA.length(), spannableText.length(), 0);
    spannableText.append(subB);
    spannableText.append(subLinkB);
    spannableText.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            Toast.makeText(this, "Sub Link B Clicked", Toast.LENGTH_SHORT).show();
        }
    }, spannableText.length() - subLinkB.length(), spannableText.length(), 0);
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setText(spannableText, TextView.BufferType.SPANNABLE);

就像我说的,这确实是一种"最糟糕"的情况,但我想我至少会把它扔在那里,因为我认为没有任何其他方法可以通过本地化做到这一点,因为编译器不知道字符串是如何翻译的。

在你的

字符串中.xml像这样做html:

中文 : <![CDATA[Makan <b>daging</b> adalah terlalu banyak karbohidrat]]>

印度尼西亚 : <![CDATA[Eating <b>meat</b> is too much carbohydrates]]>

然后在您的活动中,您可以跟踪跨度位置并添加ClickableSpan

class MainActivity: AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setupView()
    }
    private fun setupView() {
        val htmlSpan = SpannableString(HtmlCompat.fromHtml(
            getString(R.string.click_me_button),
            HtmlCompat.FROM_HTML_MODE_COMPACT
        ))
        val styleSpan = htmlSpan.getSpans(0, htmlSpan.length, StyleSpan::class.java).first()
        val spanStart = htmlSpan.getSpanStart(styleSpan)
        val spanEnd = htmlSpan.getSpanEnd(styleSpan)
        val clickSpan = object:ClickableSpan() {
            override fun onClick(widget: View) {
                Toast.makeText(this@MenghubungkanProdukActivity, "Hehehehe", Toast.LENGTH_LONG).show()
                Timber.d("HEHEHE")
            }
        }
        htmlSpan.setSpan(clickSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        binding.textWarning.text = htmlSpan
        binding.textWarning.movementMethod = LinkMovementMethod.getInstance()
    }
}

来源 : 本地化可点击跨度安卓

最新更新