Handle localized string contains a link in a single TextView

Viewed 1277

i have a string in strings.xml file. clicks on some part of this string redirect to a task. that some part where made based on the index of the string.

Now i am trying to translate it to french but i am getting index out of bound exception as its less then the length of English strings.

Could anyone please say, what will be the best way to handle this scenario?

String separation is one thing we can do.

but i want to handle it in one text view itself.

Code for the English String:

    SpannableString spannableString = new SpannableString(getResources().getString(R.string.desc));
    ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            Log.v("dosomething", "dosomething");
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            Log.v("task one", "task one");
        }
    };

    spannableString.setSpan(clickableSpan, 87, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    mDesc.setText(spannableString);
    mDesc.setMovementMethod(LinkMovementMethod.getInstance());
3 Answers

You can use annotations and then set the ClickableSpan on the annotated part. That way, the translations should contain that information.

Define localized strings in resources like this:

<string name="complete_phrase">By clicking on continue, you agree to the terms and conditions and privacy policy.</string>
<string name="tos_part">terms and conditions</string>
<string name="pp_part">privacy policy</string>

tos_part and pp_part contain the text that is clickable in the complete_phrase.

Then build the span and set it to a TextView like this:

val someTextView = ...
val phrase = resources.getString(R.string.complete_phrase)
val spannable = SpannableStringBuilder(phrase)
    .apply {
        val tosPart = resources.getString(R.string.tos_part)
        val tosStart = phrase.indexOf(tosPart)
        setSpan(object : ClickableSpan() {

            override fun onClick(textView: View) {
                view.context.startActivity(Intent(view.context, ThermsAndConditionsActivity::class.java))
            }
        }, tosStart, tosStart + tosPart.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)

        val ppPart = resources.getString(R.string.pp_part)
        val ppStart = phrase.indexOf(ppPart)
                setSpan(object : ClickableSpan() {

            override fun onClick(textView: View) {
                            view.context.startActivity(Intent(view.context, DataPrivacyActivity::class.java))
                        }
        }, ppStart, ppStart + ppPart.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
    }
someTextView.setText(spannable)
someTextView.movementMethod = LinkMovementMethod.getInstance()
Related