Last active
April 27, 2016 20:30
-
-
Save sangcomz/6a177c0a8f4ab3f452b9e5e1eb8e7f47 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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