2016-06-22 1 views
1

J'ai un TextView dans lequel tous les mots sont cliquables individuellement. Je veux commencer par chaque mot sans style. En cliquant sur un mot, le mot devrait devenir et rester souligné. Je suis en mesure d'effacer le soulignement par défaut, mais rien ne se passe au clic. (Je capture et même traite le clic, mais je n'arrive pas à changer le style Span).Android ClickableSpan ne change pas de style onclick

Le code pertinent est ci-dessous. Merci d'avance pour l'aide.

sur mesure ClickableSpan:

class WordSpan extends ClickableSpan { 
    private TextPaint textpaint; 
    public boolean clicked = false; 

    @Override 
    public void updateDrawState(TextPaint ds) { 
    textpaint = ds; 
    ds.setUnderlineText(false); 

    if (clicked) 
     ds.setUnderlineText(true); 
    } 

    @Override 
    public void onClick(View v) {} 

    public void setClicked(boolean c) { 
    clicked = c; 
    updateDrawState(textpaint); 
    } 
} 

De onCreate() Je suis l'analyse d'un fichier txt et en ajoutant chaque mot à un TextView. Au sein de cette boucle d'analyse syntaxique je le code suivant:

SpannableString ss = new SpannableString(word.toString()); 

    WordSpan clickableSpan = new WordSpan() { 
    @Override 
    public void onClick(View view) { 
    setClicked(true); 
    view.invalidate(); 
    }}; 

    ss.setSpan(clickableSpan, 0, word.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 

    tvText.append(ss); 
    tvText.append(" "); 
} 

tvText.setMovementMethod(LinkMovementMethod.getInstance()); 
+0

1. individualy mot ne sont pas cliquables. 2. Lorsque je clique sur un seul texte, tous les textes sont soulignés, ce qui signifie que l'on change de style onclick. Donc, je ne comprends pas exactement vos besoins. – Chitrang

+0

Le clickablespan rend les mots individuels cliquables. Je suis capable de gérer un clic sur chaque mot et de détecter quel mot a été cliqué avec ce code. Maintenant, j'ai juste besoin de changer le style du mot qui a été cliqué, pour montrer à l'utilisateur qu'il a effectivement été cliqué. –

Répondre

1

Pour mot individuel cliquable vous devrez ajouter plusieurs durée cliquable à la chaîne spannable. Par exemple, pour rendre "foo" et "bar" cliquables individuellement en simple Textview vous devrez ajouter deux span cliquables, un pour "foo" et un autre pour "bar" et les ajouter à la chaîne spannable.

Dans l'exemple, j'ai divisé la chaîne en utilisant l'espace pour plus de simplicité, plus vous devez écrire une logique pour un clic de la durée.

Intervalle qui supprime le soulignement. De plus, vous pouvez configurer l'arrière-plan et la couleur du texte en cliquant. Vous pouvez le retirer si vous ne l'utilisez pas.

import android.text.TextPaint; 
import android.text.style.ClickableSpan; 

public abstract class TouchableSpan extends ClickableSpan { 
    private boolean mIsPressed; 
    private int mPressedBackgroundColor; 
    private int mNormalTextColor; 
    private int mPressedTextColor; 
    private int mBackgroundColor; 

    public TouchableSpan(int normalTextColor,int backgroundColor, int pressedTextColor, int pressedBackgroundColor) { 
     mBackgroundColor = backgroundColor; 
     mNormalTextColor = normalTextColor; 
     mPressedTextColor = pressedTextColor; 
     mPressedBackgroundColor = pressedBackgroundColor; 
    } 

    public void setPressed(boolean isSelected) { 
     mIsPressed = isSelected; 
    } 

    @Override 
    public void updateDrawState(TextPaint ds) { 
     super.updateDrawState(ds); 
     ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor); 
     ds.bgColor = mIsPressed ? mPressedBackgroundColor : mBackgroundColor; 
     ds.setUnderlineText(!mIsPressed); 
    } 
} 

Créez un LinkMovementMethod qui prendra en charge votre Span. Si vous supprimez la disposition de couleurs que vous pouvez modifier cela aussi bien

import android.text.Layout; 
import android.text.Selection; 
import android.text.Spannable; 
import android.text.method.LinkMovementMethod; 
import android.text.method.MovementMethod; 
import android.view.MotionEvent; 
import android.widget.TextView; 

public class LinkTouchMovementMethod extends LinkMovementMethod { 

    private TouchableSpan mPressedSpan; 

    @Override 
    public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN) { 
      mPressedSpan = getPressedSpan(textView, spannable, event); 
      if (mPressedSpan != null) { 
       mPressedSpan.setPressed(true); 
       Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan), 
         spannable.getSpanEnd(mPressedSpan)); 
      } 
     } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 
      TouchableSpan touchedSpan = getPressedSpan(textView, spannable, event); 
      if (mPressedSpan != null && touchedSpan != mPressedSpan) { 
       mPressedSpan.setPressed(false); 
       mPressedSpan = null; 
       Selection.removeSelection(spannable); 
      } 
     } else { 
      if (mPressedSpan != null) { 
       mPressedSpan.setPressed(false); 
       super.onTouchEvent(textView, spannable, event); 
      } 
      mPressedSpan = null; 
      Selection.removeSelection(spannable); 
     } 
     return true; 
    } 

    private TouchableSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) { 

     int x = (int) event.getX(); 
     int y = (int) event.getY(); 

     x -= textView.getTotalPaddingLeft(); 
     y -= textView.getTotalPaddingTop(); 

     x += textView.getScrollX(); 
     y += textView.getScrollY(); 

     Layout layout = textView.getLayout(); 
     int line = layout.getLineForVertical(y); 
     int off = layout.getOffsetForHorizontal(line, x); 

     TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class); 
     TouchableSpan touchedSpan = null; 
     if (link.length > 0) { 
      touchedSpan = link[0]; 
     } 
     return touchedSpan; 
    } 

} 

Ensuite, vous pouvez l'utiliser de la manière suivante:

TextView textView = (TextView)findViewById(R.id.hello_world); 
String fooBar = "asdfasdfasdfasf asdfasfasfasd"; 
String[] clickSpans = fooBar.split(" "); 
int clickSpanLength = clickSpans.length; 
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); 
int totalLength = 0; 
int normalColor = getResources().getColor(android.R.color.black); 
int clickColor = getResources().getColor(android.R.color.holo_blue_bright); 
String separator = " , "; 
int separatorLength = separator.length(); 
for (int i = 0; i < clickSpanLength; i++) { 
    int currentWordLength = clickSpans[i].length(); 
    spannableStringBuilder.append(clickSpans[i]); 
    if (i < clickSpanLength - 1) { 
     spannableStringBuilder.append(" , "); 
    } 

    spannableStringBuilder.setSpan(new TouchableSpan(normalColor, Color.TRANSPARENT, clickColor, Color.TRANSPARENT) { 
     @Override 
     public void onClick(View widget) { 

     } 
    }, totalLength, totalLength + currentWordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 
    totalLength = totalLength + currentWordLength + separatorLength; 
} 

textView.setText(spannableStringBuilder); 
textView.setMovementMethod(new LinkTouchMovementMethod()); 
+0

Merci, cette solution fonctionne. Cependant, le TextView ne défilera pas, même si maxLines et les barres de défilement sont définies dans le fichier XML. –

+0

Pour que le texte défilement défilant l'entoure avec scrollview. L'autre façon de définir la méthode de mouvement à scrollview ne fonctionnera pas même si vous étendez ScrollingMovementMethod au lieu de LinkMovementMethod –