I have a textview in my app that change the size of a word when click on it, my problem is that if i click this word one time it become bigger, if i click again his size become the double. I need to make it smaller in the second click, by checking the text size of this spannable word before make it bigger.
private ClickableSpan getClickableSpan(final String word,final int start, final int end) {
return new ClickableSpan() {
final String mWord;
{
mWord = word;
}
#Override
public void onClick(View widget) {
TextView tv = (TextView) widget;
// TODO add check if tv.getText() instanceof Spanned
Spanned s = (Spanned) tv.getText();
int start = s.getSpanStart(this);
int end = s.getSpanEnd(this);
Log.d("Sd", "onClick [" + s.subSequence(start, end) + "]");
spans.setSpan(new RelativeSizeSpan(3f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//check the size before make it bigger how to do so??
Toast.makeText(widget.getContext(), s.subSequence(start, end), Toast.LENGTH_SHORT)
.show();
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(Color.WHITE);
}
};
}
I would use a simple boolean isBig and check it.
if (isBig) {
// make textview smaller
isBig = false;
} else {
// make textview bigger
isBig = true;
}
Related
I have a link in android textview. I am not able to capture the link click event.
String text = "http:://www.google.com is a google link";
textview.setText(text);
"http:://www.google.com" this span of string is clickable in textview. I want to capture that particular click event.
I tried the following.
public static void setTextView(TextView text, CharSequence sequence) {
UoloLogger.i(TAG, "Setting string :: "+sequence);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
for(URLSpan span : urls) {
makeLinkClickable(strBuilder, span);
}
text.setText(strBuilder);
text.setMovementMethod(LinkMovementMethod.getInstance());
}
public static void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span) {
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan clickable = new ClickableSpan() {
public void onClick(View view) {
UoloLogger.i(TAG, span.getURL());
}
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
}
I started setting text into my textview using setTextView() method. I am getting URLSpan array is empty even if i am having the links.
String text = "http:://www.google.com is a google link";
setTextView(textView, text);
Sorry for the bad english. I think, i have explained my problem. Can someone help me.
public static void setLinkclickEvent(TextView tv, HandleLinkClickInsideTextView clickInterface) {
String text = tv.getText().toString();
String str = "([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])";
Pattern pattern = Pattern.compile(str);
Matcher matcher = pattern.matcher(tv.getText());
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
InternalURLSpan span = new InternalURLSpan();
span.setText(text.substring(x, y));
span.setClickInterface(clickInterface);
f.setSpan(span, x, y,
android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
}
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setFocusable(false);
}
public static class InternalURLSpan extends android.text.style.ClickableSpan {
private String text;
private HandleLinkClickInsideTextView clickInterface;
#Override
public void onClick(View widget) {
getClickInterface().onLinkClicked(getText());
}
public void setText(String textString) {
this.text = textString;
}
public String getText() {
return this.text;
}
public void setClickInterface(HandleLinkClickInsideTextView clickInterface) {
this.clickInterface = clickInterface;
}
public HandleLinkClickInsideTextView getClickInterface() {
return this.clickInterface;
}
}
public interface HandleLinkClickInsideTextView {
public void onLinkClicked(String url);
}
After this i just used the method send click event.
textview.setText("http://google.com is google website and http://youtube.com is youtube site");
setLinkclickEvent(textview, new HandleLinkClickInsideTextView() {
public void onLinkClicked(String url) {
// Here I added my code
}
});
You can achieved the same using SpannableStringBuilder.
Simply initialize the TextView that you want to add 2 or more listeners and then pass that to the following method that I have created:
SAMPLE CODE:
private void customTextView(TextView view) {
SpannableStringBuilder spanTxt = new SpannableStringBuilder(
"I agree to the ");
spanTxt.append("Term of services");
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Terms of services Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - "Term of services".length(), spanTxt.length(), 0);
spanTxt.append(" and");
spanTxt.setSpan(new ForegroundColorSpan(Color.BLACK), 32, spanTxt.length(), 0);
spanTxt.append(" Privacy Policy");
spanTxt.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Privacy Policy Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - " Privacy Policy".length(), spanTxt.length(), 0);
view.setMovementMethod(LinkMovementMethod.getInstance());
view.setText(spanTxt, BufferType.SPANNABLE);
}
And in your XML, use android:textColorLink to add custom link color of your choice. Like this:
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColorLink="#C36241" />
If you want to open a link after textview click, there are two options:
Using java code:
Spanned text = Html.fromHtml("<u>GOOGLE.COM</u>");
textView.setText(text);
Uri uri = Uri.parse("http://shopwhere.com.au/");
Intent webIntent = new Intent(Intent.ACTION_VIEW,uri);
// Create and start the chooser
Intent chooser = Intent.createChooser(webIntent, "Open with");
startActivityForResult(chooser,0);
Using XML:
Use android:autoLink="web" inside textview tag. You can also change link color android:textColorHighlight="#android:color/transparent" and android:textColorLink="#color/white".
I am making a basic text editor app for Android and currently working on formatting the text.
I have an EditText named text_area where the user types his text and a ToggleButton called bold that sets the text to bold. Initially, using the EditText.setTypeface method, all of the text in text_area would change to bold when the button is on. Using the answer provided in this question, I was able to change only the selected text to bold.
What I really want to do though is that when the button is pressed, all the previously typed text (normal and/or bold) remain unchanged, and whatever the user types next is typed in bold.
Here's my code (Could someone also tell me what the code under the else statement does):
bold.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(bold.isChecked()==true) {
Spannable str = textarea.getText();
if(textarea.getSelectionEnd() > textarea.getSelectionStart())
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
textarea.getSelectionStart(), textarea.getSelectionEnd(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
else
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
textarea.getSelectionEnd(),
textarea.getSelectionStart(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
});
I was stuck on the same issue, and after hours of trying, this is what I came up with.
First, whenever you check the bold/italics whatever styled checkbox you want to apply, you want to get the current cursor position.
//if bold is checked
YourEditText.getSelectionStart();
YourEditText.getSelectionEnd();
both gives you the current cursor position of the EditText if no text is highlighted.
Store this value into a variable.
int lastCursorPosition = YourEditText.getSelectionStart();
Then, I overrode the onTextChanged function of the EditText. Since we only want to set span from the last cursor position to the end of wherever change is made, we set the span from lastCursorPosition to the end of the text.
int endOfString = YourEditText.getText().toString().length();
StyleSpan ss = new StyleSpan(Typeface.BOLD);
str.setSpan(ss, lastCursorPosition, endOfString, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
While doing this, I ran into another problem. Whenever I applied another span to another part of the text, previous styles disappeared. I fixed this by creating new StyleSpan for each time a new style was applied. Minimal code to understand:
public static final int TYPEFACE_NORMAL = 0;
public static final int TYPEFACE_BOLD = 1;
public static final int TYPEFACE_ITALICS = 2;
public static final int TYPEFACE_BOLD_ITALICS = 3;
private int currentTypeface;
private int lastCursorPosition;
...
#Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
Spannable str = this.getText();
StyleSpan ss;
int endOfString = text.toString().length();
//current typeface is determined by bold, italics, checkboxes, etc
switch(currentTypeface) {
case TYPEFACE_NORMAL:
ss = new StyleSpan(Typeface.NORMAL);
break;
case TYPEFACE_BOLD:
ss = new StyleSpan(Typeface.BOLD);
break;
case TYPEFACE_ITALICS:
ss = new StyleSpan(Typeface.ITALIC);
break;
case TYPEFACE_BOLD_ITALICS:
ss = new StyleSpan(Typeface.BOLD_ITALIC);
break;
default:
ss = new StyleSpan(Typeface.NORMAL);
}
str.setSpan(ss, lastCursorPosition, endOfString, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
Full TextArea class I've written:
public class TextArea extends EditText {
public static final int TYPEFACE_NORMAL = 0;
public static final int TYPEFACE_BOLD = 1;
public static final int TYPEFACE_ITALICS = 2;
public static final int TYPEFACE_BOLD_ITALICS = 3;
private int currentTypeface;
private int lastCursorPosition;
private int tId;
public TextArea(Context context) {
super(context);
lastCursorPosition = this.getSelectionStart();
}
public TextArea(Context context, AttributeSet attrs) {
super(context, attrs);
}
public int gettId() {
return tId;
}
public void settId(int tId) {
this.tId = tId;
}
public void changeTypeface(int tfId) {
currentTypeface = tfId;
lastCursorPosition = this.getSelectionStart();
}
#Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
Spannable str = this.getText();
StyleSpan ss;
int endLength = text.toString().length();
switch(currentTypeface) {
case TYPEFACE_NORMAL:
ss = new StyleSpan(Typeface.NORMAL);
break;
case TYPEFACE_BOLD:
ss = new StyleSpan(Typeface.BOLD);
break;
case TYPEFACE_ITALICS:
ss = new StyleSpan(Typeface.ITALIC);
break;
case TYPEFACE_BOLD_ITALICS:
ss = new StyleSpan(Typeface.BOLD_ITALIC);
break;
default:
ss = new StyleSpan(Typeface.NORMAL);
}
str.setSpan(ss, lastCursorPosition, endLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
From MainActivity.java
TextArea t = new TextArea(context);
int typefaceStyle = TextArea.TYPEFACE_NORMAL;
CheckBox boldCheckbox = (CheckBox) findViewById(R.id.post_bold_checkbox);
boldCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
boldChecked = isChecked;
if(italicsChecked && boldChecked) {
typefaceStyle = TextArea.TYPEFACE_BOLD_ITALICS;
} else if (boldChecked){
typefaceStyle = TextArea.TYPEFACE_BOLD;
} else if (italicsChecked) {
typefaceStyle = TextArea.TYPEFACE_ITALICS;
} else {
typefaceStyle = TextArea.TYPEFACE_NORMAL;
}
t.changeTypeface(typefaceStyle);
}
});
My very first reply on StackOverflow! Hope this helped :-)
I want to change the color of one word when I touch it.
For example: Hello, my name is Robert.
(by default, all black)
Now if the user touches the word "Robert", I want the color of "Robert" to change to RED.
How do I do that? (I'm new to Android)
textview.setTextColor() changes the whole thing, I only want one word.
I believe the SpannableString and ClickableSpan are the things you are looking for.
For more information, check this.
And Html.fromHtml is also work for this.
L. Swifter is on the right track.
Here's a very simple version you can build off of.
SpannableString spannableString = new SpannableString(yourstring);
ClickableSpan clickableSpan = new ClickableSpan() {
boolean clicked = false;
#Override
public void onClick(View view) {
clicked = true;
view.invalidate();
}
#Override
public void updateDrawState(TextPaint ds) {
if (this.clicked) ds.setColor(Color.RED);
}
};
spannableString.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(spannableString);
textview.setMovementMethod(LinkMovementMethod.getInstance());
start and end are the index positions of "Robert"
Make sure your setText is using the spannableString, not the original string.
Have fun!
You can add an HTML <font> tag to the TextView's text.
Use onTouch to calculate which word you just touched, look at this.
And :
TextView.setText(Html.fromHtml("assumble your html style string to change specified word color"));
Summarize the answer of L. Swifter and TML, also used the answer from
select a word on a tap in TextView/EditText
The following code should be work if you click any word in the TextView.
The color would be changed to red if you clicked it. Other words color will be reset to black.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView lTextView = (TextView) findViewById(R.id.textView);
breakEveryWord("Clickable words in text view ", lTextView);
}
...
private void breakEveryWord(String passage, final TextView pTextView) {
String definition = passage.trim();
pTextView.setMovementMethod(LinkMovementMethod.getInstance());
pTextView.setText(definition, TextView.BufferType.SPANNABLE);
final Spannable spans = (Spannable) pTextView.getText();
BreakIterator iterator = BreakIterator.getWordInstance(Locale.US);
iterator.setText(definition);
int start = iterator.first();
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator
.next()) {
String possibleWord = definition.substring(start, end);
if (Character.isLetterOrDigit(possibleWord.charAt(0))) {
ClickableSpan clickSpan = new CustomClickableSpan(possibleWord, new CallBack() {
#Override
public void clearAll() {
CustomClickableSpan[] toRemoveSpans = spans.getSpans(0, pTextView.getText().length(), CustomClickableSpan.class);
for (CustomClickableSpan toRemoveSpan : toRemoveSpans) {
toRemoveSpan.reset(pTextView);
}
}
});
spans.setSpan(clickSpan, start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
public static class CustomClickableSpan extends ClickableSpan {
final String mWord;
boolean clicked = false;
final CallBack mCallBack;
public CustomClickableSpan(String pWord, CallBack pCallBack) {
mWord = pWord;
mCallBack = pCallBack;
}
public void reset(View widget) {
clicked = false;
widget.invalidate();
}
#Override
public void onClick(View widget) {
Log.d("tapped on:", mWord);
mCallBack.clearAll();
clicked = true;
widget.invalidate();
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(Color.BLACK);
if (this.clicked) ds.setColor(Color.RED);
}
}
public interface CallBack {
void clearAll();
}
}
I'm working on ClickableSpan in a TextView, and I'm trying to get the clicked span's text. This is my code.
// this is the text we'll be operating on
SpannableString text = new SpannableString("Lorem ipsum dolor sit amet");
// make "dolor" (characters 12 to 17) display a toast message when touched
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View view) {
// This will get "Lorem ipsum dolor sit amet", but I just want "dolor"
String text = ((TextView) view).getText().toString();
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
};
text.setSpan(clickableSpan, 12, 17, 0);
As you can see, I set the clickablespan to the TextView from characters 12 to 17, and I want to get these characters in the onClick event.
Is there anyway I can do that? Or at least can I pass the 12, 17 parameter to onClick event?
Thank you!
try this:
public class LoremIpsumSpan extends ClickableSpan {
#Override
public void onClick(View widget) {
// TODO add check if widget instanceof TextView
TextView tv = (TextView) widget;
// TODO add check if tv.getText() instanceof Spanned
Spanned s = (Spanned) tv.getText();
int start = s.getSpanStart(this);
int end = s.getSpanEnd(this);
Log.d(TAG, "onClick [" + s.subSequence(start, end) + "]");
}
}
A little simpler, could also pass a model reference if necessary.
public class SpecialClickableSpan extends ClickableSpan {
String text;
public SpecialClickableSpan(String text){
super();
this.text = text;
}
#Override
public void onClick(View widget) {
Log.d(TAG, "onClick [" + text + "]");
}
}
Then call new SpecialClickableSpan("My Text")
Edited: previous code was wrong, this works
// make "dolor" (characters 12 to 17) display a toast message when touched
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View view) {
TextView textView = (TextView) view;
CharSequence charSequence = textView.getText();
if (charSequence instanceof Spannable) {
Spannable spannableText = (Spannable)charSequence;
ClickableSpan[] spans = spannableText.getSpans(0, textView.length(), ClickableSpan.class);
for (ClickableSpan span : spans) {
int start = spannableText.getSpanStart(span);
int end = spannableText.getSpanEnd(span);
Toast.makeText(MainActivity.this, charSequence.subSequence(start, end), Toast.LENGTH_LONG).show();
}
}
}
};
You can also use to make string spannable like this
String htmlLinkText = "Lorem ipsum <a href='http://www.google.com'>dolor</a> sit amet";
testView.setText(Html.fromHtml(htmlLinkText));
testView.setMovementMethod(LinkMovementMethod.getInstance());
CharSequence text = testView.getText();
if (text instanceof Spannable) {
int end = text.length();
Spannable sp = (Spannable) testView.getText();
URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
SpannableStringBuilder style = new SpannableStringBuilder(text);
style.clearSpans();//should clear old spans
for (URLSpan url : urls) {
CustomerTextClick click = new CustomerTextClick(url.getURL());
style.setSpan(click, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
testView.setText(style);
}
and CustomerTextClick will be
private static class CustomerTextClick extends ClickableSpan {
private String mUrl;
CustomerTextClick(String url) {
mUrl = url;
}
#Override
public void onClick(View widget) {
// TODO Auto-generated method stub
//Toast.makeText(ctx, "hello google!",Toast.LENGTH_LONG).show();
// Do your action here
}
}
Tested and working code.
I have one TextView. In this view I want to make it as some portion of text is clickable. if you click on that text then I want to open WebView.
I did the following way:
textView.setText(Html.fromHtml("I have read and agree to the " +
"<a href='id.web.freelancer.example.TCActivity://Kode'>TERMS AND CONDITIONS</a>"));
textView.setClickable(true);
textView.setMovementMethod(LinkMovementMethod.getInstance());
Here if you click on the TERMS AND CONDITIONS then it opens in the browser but I want to open it in the WebView.
Another way, borrows a bit from Linkify but allows you to customize your handling.
Custom Span Class:
public class ClickSpan extends ClickableSpan {
private OnClickListener mListener;
public ClickSpan(OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View widget) {
if (mListener != null) mListener.onClick();
}
public interface OnClickListener {
void onClick();
}
}
Helper function:
public static void clickify(TextView view, final String clickableText,
final ClickSpan.OnClickListener listener) {
CharSequence text = view.getText();
String string = text.toString();
ClickSpan span = new ClickSpan(listener);
int start = string.indexOf(clickableText);
int end = start + clickableText.length();
if (start == -1) return;
if (text instanceof Spannable) {
((Spannable)text).setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
SpannableString s = SpannableString.valueOf(text);
s.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(s);
}
MovementMethod m = view.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
view.setMovementMethod(LinkMovementMethod.getInstance());
}
}
Usage:
clickify(textView, clickText,new ClickSpan.OnClickListener()
{
#Override
public void onClick() {
// do something
}
});
try this may it works
SpannableString span = new SpannableString(
"Click here to for gmail page.");
span.setSpan(new URLSpan("http://www.gmail.com"), 6, 10,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv = (TextView) findViewById(R.id.text);
tv.setText(span);
tv.setMovementMethod(LinkMovementMethod.getInstance());
change start and end position according to your text size
How do I make links in a TextView clickable?
or u can create a linear layout with horizontal orientation having 2 textviews making second textview clickable..
Why don't you make the textView call on onClick method:
<TextView
...
android:onClick"openWebView"
...
/>
And then just have a method in your activity called:
public void openWebView (View v) {
....
// Do something
}