289 votes

Comment définir la partie de la vue texte qui est cliquable ?

J'ai le texte " Android est une pile logicielle ". Dans ce texte, je veux mettre le " pile Le texte " " est cliquable. Ainsi, si vous cliquez dessus, vous serez redirigé vers une nouvelle activité (pas dans le navigateur).

J'ai essayé mais je ne trouve pas de solution.

12voto

Dan Bray Points 576

Voici un Kotlin pour faire des parties d'un TextView cliquable :

private fun makeTextLink(textView: TextView, str: String, underlined: Boolean, color: Int?, action: (() -> Unit)? = null) {
    val spannableString = SpannableString(textView.text)
    val textColor = color ?: textView.currentTextColor
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(textView: View) {
            action?.invoke()
        }
        override fun updateDrawState(drawState: TextPaint) {
            super.updateDrawState(drawState)
            drawState.isUnderlineText = underlined
            drawState.color = textColor
        }
    }
    val index = spannableString.indexOf(str)
    spannableString.setSpan(clickableSpan, index, index + str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    textView.text = spannableString
    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.highlightColor = Color.TRANSPARENT
}

Elle peut être appelée plusieurs fois pour créer plusieurs liens dans un TextView :

makeTextLink(myTextView, str, false, Color.RED, action = { Log.d("onClick", "link") })
makeTextLink(myTextView, str1, true, null, action = { Log.d("onClick", "link1") })

8voto

Ather Points 11
 t= (TextView) findViewById(R.id.PP1);

 t.setText(Html.fromHtml("<bThis is normal text </b>" +
                "<a href=\"http://www.xyz-zyyx.com\">This is cliclable text</a> "));
 t.setMovementMethod(LinkMovementMethod.getInstance());

6voto

Giorgio Daino Points 101

Je voudrais suggérer une approche différente qui, à mon avis, nécessite moins de code et est plus "conviviale" pour la localisation.

Supposons que votre activité de destination s'appelle "ActivityStack", définissez dans le manifeste un filtre d'intention pour celle-ci avec un schéma personnalisé (par exemple, "myappscheme") dans AndroidManifest.xml :

<activity
    android:name=".ActivityStack">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:host="stack"/>
        <data android:scheme="myappscheme" />
    </intent-filter>
</activity>

Définissez le TextView sans aucune balise spéciale (il est important de ne PAS utiliser la balise "Android:autoLink", voir : https://stackoverflow.com/a/20647011/1699702 ) :

<TextView
    android:id="@+id/stackView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/stack_string" />

puis utiliser un lien avec un schéma personnalisé et l'héberger dans le texte du TextView comme (dans String.xml) :

<string name="stack_string">Android is a Software <a href="myappscheme://stack">stack</a></string>

et "activer" le lien avec setMovementMethod() (dans onCreate() pour les activités ou onCreateView() pour les fragments) :

TextView stack = findViewById(R.id.stackView);
stack.setMovementMethod(LinkMovementMethod.getInstance());

Cela ouvrira l'activité de la pile en tapant sur le mot "pile".

4voto

Rammohan Raja Points 101

Version de Kotlin de la réponse de Phan Van Linh.

Veuillez noter qu'il présente quelques modifications mineures.

fun makeLinks(textView: TextView, links: Array<String>, clickableSpans: Array<ClickableSpan>) {
    val spannableString = SpannableString(textView.text)

    for (i in links.indices) {
        val clickableSpan = clickableSpans[i]
        val link = links[i]

        val startIndexOfLink = textView.text.indexOf(link)

        spannableString.setSpan(clickableSpan, startIndexOfLink, startIndexOfLink + link.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    }

    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.setText(spannableString, TextView.BufferType.SPANNABLE)
}

fun setupClickableTextView() {
    val termsOfServicesClick = object : ClickableSpan() {
        override fun onClick(p0: View?) {
            Toast.makeText(applicationContext, "ToS clicked", Toast.LENGTH_SHORT).show()
        }
    }

    val privacyPolicyClick = object : ClickableSpan() {
        override fun onClick(p0: View?) {
            Toast.makeText(applicationContext, "PP clicked", Toast.LENGTH_SHORT).show()
        }
    }

    makeLinks(termsTextView, arrayOf("terms", "privacy policy"), arrayOf(termsOfServicesClick, privacyPolicyClick))
}

4voto

shinta Points 150

Vous pouvez utiliser cette méthode pour définir la valeur cliquable.

public void setClickableString(String clickableValue, String wholeValue, TextView yourTextView){
    String value = wholeValue;
    SpannableString spannableString = new SpannableString(value);
    int startIndex = value.indexOf(clickableValue);
    int endIndex = startIndex + clickableValue.length();
    spannableString.setSpan(new ClickableSpan() {
                                @Override
                                public void updateDrawState(TextPaint ds) {
                                    super.updateDrawState(ds);
                                    ds.setUnderlineText(false); // <-- this will remove automatic underline in set span
                                }

                                @Override
                                public void onClick(View widget) {
                                    // do what you want with clickable value
                                }
                            }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    yourTextView.setText(spannableString);
    yourTextView.setMovementMethod(LinkMovementMethod.getInstance()); // <-- important, onClick in ClickableSpan won't work without this
}

Voici comment l'utiliser :

TextView myTextView = findViewById(R.id.myTextView);
setClickableString("stack", "Android is a Software stack", myTextView);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X