Skip to content

Instantly share code, notes, and snippets.

@sangcomz
Last active April 27, 2016 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sangcomz/6a177c0a8f4ab3f452b9e5e1eb8e7f47 to your computer and use it in GitHub Desktop.
Save sangcomz/6a177c0a8f4ab3f452b9e5e1eb8e7f47 to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by sangcomz on 4/26/16.
*/
public class DecoratableTextView extends TextView implements android.view.ActionMode.Callback {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setMovementMethod(LinkMovementMethod.getInstance());
}
public DecoratableTextView(final Context context) {
super(context);
}
public DecoratableTextView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public DecoratableTextView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
// FIXME simple workaround to https://code.google.com/p/android/issues/detail?id=191430
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
final CharSequence text = getText();
setText(null);
setText(text);
}
return super.dispatchTouchEvent(event);
}
public void setDecoratable(boolean isDecoratable) {
setTextIsSelectable(isDecoratable);
}
public void setAnswerText(int start, int length) {
StringBuilder answerText = new StringBuilder(getText());
for (int i = start; i < start + length; i++) {
answerText.setCharAt(i, '_');
}
setText(answerText);
}
public void setHighlightText(int start, int end) {
SpannableString str = new SpannableString(getText());
str.setSpan(new HighLightText(),
start,
end,
Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
setText(str);
}
public void setUnderlineText(int start, int end) {
SpannableString str = new SpannableString(getText());
str.setSpan(new UnderlineText(),
start,
end,
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
setText(str);
}
public void setClearText(int start, int end) {
SpannableString str = new SpannableString(getText());
CharacterStyle[] styleSpans = str.getSpans(start, end, CharacterStyle.class);
for (CharacterStyle span : styleSpans) {
if (!(span instanceof WordText))
str.removeSpan(span);
}
setText(str);
}
public void setWordText(Context context, int start, int length) {
SpannableString str = new SpannableString(getText());
str.setSpan(new WordText(context),
start,
start + length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(str);
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Remove the "select all" option
menu.removeItem(android.R.id.selectAll);
// Remove the "cut" option
menu.removeItem(android.R.id.cut);
// Remove the "copy all" option
menu.removeItem(android.R.id.copy);
return true;
}
public class HighLightText extends ClickableSpan {
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.bgColor = Color.GREEN;
ds.setARGB(255, 255, 255, 255);
}
@Override
public void onClick(View widget) {
TextView tv = (TextView) widget;
Spanned s = (Spanned) tv.getText();
int start = s.getSpanStart(this);
int end = s.getSpanEnd(this);
String theWord = s.subSequence(start, end).toString();
}
}
public class UnderlineText extends ClickableSpan {
@Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(true);
}
@Override
public void onClick(View widget) {
TextView tv = (TextView) widget;
Spanned s = (Spanned) tv.getText();
int start = s.getSpanStart(this);
int end = s.getSpanEnd(this);
String theWord = s.subSequence(start, end).toString();
}
}
public class WordText extends ClickableSpan {
Context context;
public WordText(Context context) {
this.context = context;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setARGB(255, 51, 51, 51);
ds.setTypeface(Typeface.DEFAULT_BOLD);
}
@Override
public void onClick(View widget) {
TextView tv = (TextView) widget;
Spanned s = (Spanned) tv.getText();
int start = s.getSpanStart(this);
int end = s.getSpanEnd(this);
String theWord = s.subSequence(start, end).toString();
System.out.println(theWord);
Toast.makeText(context, String.format("Tags for tags: %s", theWord), Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here is an example MenuItem
menu.add(0, 1, 0, "HighLight").setIcon(R.mipmap.ic_launcher);
menu.add(0, 2, 0, "Clear").setIcon(R.mipmap.ic_launcher);
menu.add(0, 3, 0, "Underline").setIcon(R.mipmap.ic_launcher);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case 1:
if (isFocused()) {
final int selStart = getSelectionStart();
final int selEnd = getSelectionEnd();
setHighlightText(selStart, selEnd);
}
mode.finish();
return true;
case 2:
if (isFocused()) {
final int selStart = getSelectionStart();
final int selEnd = getSelectionEnd();
setClearText(selStart, selEnd);
}
mode.finish();
return true;
case 3:
if (isFocused()) {
final int selStart = getSelectionStart();
final int selEnd = getSelectionEnd();
setUnderlineText(selStart, selEnd);
}
mode.finish();
return true;
default:
break;
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment