I want to place a button at end of the textview paragraph, like as "Go" button that when user click on it the app going to another page.
for example:
if you have good endurance,
for killing the monster you must
going to section 2. [Go->]
-if you haven't good endurance,
flee to section 3. [Go->]
in above example [Go->] is a tiny button that must placing exactly in end of line.
how I can do it in runtime?
You can use spans for this.
Let's assume you have a TextView called myText.
Drawable goButtonDrawable = getResources().getDrawable(R.drawable.go_button);
String text = "If you have good endurance, for killing the monster you must go to section 2. [GO]"
String replace = "[GO]";
final int index = text.indexOf(replace);
final int endIndex = index + replace.length();
final ImageSpan imageSpan = new ImageSpan(goButtonDrawable, ImageSpan.ALIGN_BASELINE);
final ClickableSpan clickSpan = new ClickableSpan() {
#Override public void onClick(View clicked) {
// Do your [GO] action
}
};
SpannableString spannedText = new SpannableString(text);
spannedText.setSpan(imageSpan, index, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannedText.setSpan(clickSpan, index, endIndex , Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
myText.setText(spannedText);
Obviously this could be better abstracted (you could just make a custom TextView that handles this internally), but that's the general idea.
You can achieve this by setting the text as html
Append the HTML img tag to your text and set it to text view like this
String htmlText = "Your multi line text <img src=\"ic_go_icon\">";
textView.setText(Html.fromHtml(htmlText, new Html.ImageGetter() {
#Override
public Drawable getDrawable(String source) {
int resourceId = getResources().getIdentifier(source, "drawable",getPackageName());
Drawable drawable = getResources().getDrawable(resourceId);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
return drawable;
}
}, null));
But handling the click will be for complete text view.
Is it possible to have a textview to have different color for every word? Or even every letter? I tried extending textview and creating it but however I thought of the problem is, how would I draw all the the text out at the same time with different colors?
Use android.text.Spannable
final SpannableStringBuilder str = new SpannableStringBuilder(text);
str.setSpan(
new ForegroundColorSpan(Color.BLUE),
wordStart,
wordEnd,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE
);
myTextView.setText(str);
EDIT: To make all "Java" green
final Pattern p = Pattern.compile("Java");
final Matcher matcher = p.matcher(text);
final SpannableStringBuilder spannable = new SpannableStringBuilder(text);
final ForegroundColorSpan span = new ForegroundColorSpan(Color.GREEN);
while (matcher.find()) {
spannable.setSpan(
span, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
myTextView.setText(spannable);
The SpannableString class allows you to easily format certain pieces (spans) of a string one way and other pieces another by applying extensions of CharacterStyle (i.e. ForegroundColorSpan) via the setSpan method.
You can try This:
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
richTextView = (TextView)findViewById(R.id.rich_text);
// this is the text we'll be operating on
SpannableString text = new SpannableString("Lorem ipsum dolor sit amet");
// make "Lorem" (characters 0 to 5) red
text.setSpan(new ForegroundColorSpan(Color.RED), 0, 5, 0);
// make "ipsum" (characters 6 to 11) one and a half time bigger than the textbox
text.setSpan(new RelativeSizeSpan(1.5f), 6, 11, 0);
// make "dolor" (characters 12 to 17) display a toast message when touched
final Context context = this;
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View view) {
Toast.makeText(context, "dolor", Toast.LENGTH_LONG).show();
}
};
text.setSpan(clickableSpan, 12, 17, 0);
// make "sit" (characters 18 to 21) struck through
text.setSpan(new StrikethroughSpan(), 18, 21, 0);
// make "amet" (characters 22 to 26) twice as big, green and a link to this site.
// it's important to set the color after the URLSpan or the standard
// link color will override it.
text.setSpan(new RelativeSizeSpan(2f), 22, 26, 0);
text.setSpan(new URLSpan("http://www.chrisumbel.com"), 22, 26, 0);
text.setSpan(new ForegroundColorSpan(Color.GREEN), 22, 26, 0);
// make our ClickableSpans and URLSpans work
richTextView.setMovementMethod(LinkMovementMethod.getInstance());
// shove our styled text into the TextView
richTextView.setText(text, BufferType.SPANNABLE);
}
The result will look like this:
For more detail see Chris Umbel blog.
Yes, you can do this with Spannable and SpannableStringBuilder. See Is there any example about Spanned and Spannable text for one example.
For the various ways to format text (background color, foreground color, clickable, etc.), see CharacterStyle.
Is it possible to set the color of just span of text in a TextView?
I would like to do something similar to the Twitter app, in which a part of the text is blue. See image below:
(source: twimg.com)
Another answer would be very similar, but wouldn't need to set the text of the TextView twice
TextView TV = (TextView)findViewById(R.id.mytextview01);
Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");
wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TV.setText(wordtoSpan);
Here is a little help function. Great for when you have multiple languages!
private void setColor(TextView view, String fulltext, String subtext, int color) {
view.setText(fulltext, TextView.BufferType.SPANNABLE);
Spannable str = (Spannable) view.getText();
int i = fulltext.indexOf(subtext);
str.setSpan(new ForegroundColorSpan(color), i, i + subtext.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
I always find visual examples helpful when trying to understand a new concept.
Background Color
SpannableString spannableString = new SpannableString("Hello World!");
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(backgroundSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
Foreground Color
SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
Combination
SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(foregroundSpan, 0, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(backgroundSpan, 3, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
Further Study
Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE
Android Spanned, SpannedString, Spannable, SpannableString and CharSequence
If you want more control, you might want to check the TextPaint class. Here is how to use it:
final ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(final View textView) {
//Your onClick code here
}
#Override
public void updateDrawState(final TextPaint textPaint) {
textPaint.setColor(yourContext.getResources().getColor(R.color.orange));
textPaint.setUnderlineText(true);
}
};
Set your TextView´s text spannable and define a ForegroundColorSpan for your text.
TextView textView = (TextView)findViewById(R.id.mytextview01);
Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");
wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(wordtoSpan);
Another way that could be used in some situations is to set the link color in the properties of the view that is taking the Spannable.
If your Spannable is going to be used in a TextView, for example, you can set the link color in the XML like this:
<TextView
android:id="#+id/myTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorLink="#color/your_color"
</TextView>
You can also set it in the code with:
TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setLinkTextColor(your_color);
Here's a Kotlin Extension Function I have for this
fun TextView.setColouredSpan(word: String, color: Int) {
val spannableString = SpannableString(text)
val start = text.indexOf(word)
val end = text.indexOf(word) + word.length
try {
spannableString.setSpan(ForegroundColorSpan(color), start, end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
text = spannableString
} catch (e: IndexOutOfBoundsException) {
println("'$word' was not not found in TextView text")
}
}
Use it after you have set your text to the TextView like so
private val blueberry by lazy { getColor(R.color.blueberry) }
textViewTip.setColouredSpan("Warning", blueberry)
String text = "I don't like Hasina.";
textView.setText(spannableString(text, 8, 14));
private SpannableString spannableString(String text, int start, int end) {
SpannableString spannableString = new SpannableString(text);
ColorStateList redColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{0xffa10901});
TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, redColor, null);
spannableString.setSpan(highlightSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new BackgroundColorSpan(0xFFFCFF48), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new RelativeSizeSpan(1.5f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableString;
}
Output:
Set Color on Text by passing String and color:
private String getColoredSpanned(String text, String color) {
String input = "<font color=" + color + ">" + text + "</font>";
return input;
}
Set text on TextView / Button / EditText etc by calling below code:
TextView:
TextView txtView = (TextView)findViewById(R.id.txtView);
Get Colored String:
String name = getColoredSpanned("Hiren", "#800000");
Set Text on TextView:
txtView.setText(Html.fromHtml(name));
Done
There's a factory for creating the Spannable, and avoid the cast, like this:
Spannable span = Spannable.Factory.getInstance().newSpannable("text");
Just to add to the accepted answer, as all the answers seem to talk about android.graphics.Color only: what if the color I want is defined in res/values/colors.xml?
For example, consider Material Design colors defined in colors.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="md_blue_500">#2196F3</color>
</resources>
(android_material_design_colours.xml is your best friend)
Then use ContextCompat.getColor(getContext(), R.color.md_blue_500) where you would use Color.BLUE, so that:
wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
becomes:
wordtoSpan.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.md_blue_500)), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Where I found that:
Working with spans in Android – Michael Spitsin – Medium
Using kotlin-ktx, you can achieve it easily
bindView?.oneTimePasswordTitle?.text = buildSpannedString {
append("One Time Password ")
inSpans(
ForegroundColorSpan(ContextCompat.getColor(bindView?.oneTimePasswordTitle?.context!!,R.color.colorPrimaryText))
){
append(" (As Registered Email)")
}
}
Some answers here aren't up to date. Because, you will (in most of cases) add a custom clic action on your link.
Besides, as provided by the documentation help, your spanned string link color will have a default one.
"The default link color is the theme's accent color or android:textColorLink if this attribute is defined in the theme".
Here is the way to do it safely.
private class CustomClickableSpan extends ClickableSpan {
private int color = -1;
public CustomClickableSpan(){
super();
if(getContext() != null) {
color = ContextCompat.getColor(getContext(), R.color.colorPrimaryDark);
}
}
#Override
public void updateDrawState(#NonNull TextPaint ds) {
ds.setColor(color != -1 ? color : ds.linkColor);
ds.setUnderlineText(true);
}
#Override
public void onClick(#NonNull View widget) {
}
}
Then to use it.
String text = "my text with action";
hideText= new SpannableString(text);
hideText.setSpan(new CustomClickableSpan(){
#Override
public void onClick(#NonNull View widget) {
// your action here !
}
}, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
yourtextview.setText(hideText);
// don't forget this ! or this will not work !
yourtextview.setMovementMethod(LinkMovementMethod.getInstance());
Hope this will strongly help !
create textview in ur layout
paste this code in ur MainActivity
TextView textview=(TextView)findViewById(R.id.textviewid);
Spannable spannable=new SpannableString("Hello my name is sunil");
spannable.setSpan(new ForegroundColorSpan(Color.BLUE), 0, 5,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
textview.setText(spannable);
//Note:- the 0,5 is the size of colour which u want to give the strring
//0,5 means it give colour to starting from h and ending with space i.e.(hello), if you want to change size and colour u can easily
Below works perfectly for me
tvPrivacyPolicy = (TextView) findViewById(R.id.tvPrivacyPolicy);
String originalText = (String)tvPrivacyPolicy.getText();
int startPosition = 15;
int endPosition = 31;
SpannableString spannableStr = new SpannableString(originalText);
UnderlineSpan underlineSpan = new UnderlineSpan();
spannableStr.setSpan(underlineSpan, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
ForegroundColorSpan backgroundColorSpan = new ForegroundColorSpan(Color.BLUE);
spannableStr.setSpan(backgroundColorSpan, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
StyleSpan styleSpanItalic = new StyleSpan(Typeface.BOLD);
spannableStr.setSpan(styleSpanItalic, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
tvPrivacyPolicy.setText(spannableStr);
Output for above code
From the developer docs, to change the color and size of a spannable:
1- create a class:
class RelativeSizeColorSpan(size: Float,#ColorInt private val color: Int): RelativeSizeSpan(size) {
override fun updateDrawState(textPaint: TextPaint?) {
super.updateDrawState(textPaint)
textPaint?.color = color
}
}
2 Create your spannable using that class:
val spannable = SpannableStringBuilder(titleNames)
spannable.setSpan(
RelativeSizeColorSpan(1.5f, Color.CYAN), // Increase size by 50%
titleNames.length - microbe.name.length, // start
titleNames.length, // end
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
You can use extension function in Kotlin
fun CharSequence.colorizeText(
textPartToColorize: CharSequence,
#ColorInt color: Int
): CharSequence = SpannableString(this).apply {
val startIndexOfText = this.indexOf(textPartToColorize.toString())
setSpan(ForegroundColorSpan(color), startIndexOfText, startIndexOfText.plus(textPartToColorize.length), 0)
}
Usage:
val colorizedText = "this text will be colorized"
val myTextToColorize = "some text, $colorizedText continue normal text".colorizeText(colorizedText,ContextCompat.getColor(context, R.color.someColor))
viewBinding.myTextView.text = myTextToColorize
Now you can use the CodeView library to highlight patterns with different colors easily, for example, to highlight all URLs inside the text with the blue color you just need to write
CodeView codeView = findViewById(R.id.codeview);
codeView.addSyntaxPattern(Patterns.WEB_URL, Color.BLUE);
codeView.setTextHighlighted(text);
CodeView Repository URL: https://github.com/amrdeveloper/codeview
I got the same issue.
#Dano's answer is absolutely correct. But it doesn't work for me.
After that, I found the issue I have added ClickableSpan. So it will change my color with another color (accent color)
Issue
SpannableStringBuilder will not change color and undline when you add a ClickableSpan after ForegroundColorSpan or UnderlineSpan.
Solution
1. With ClickableSpan
You can Override the updateDrawState method inside ClickableSpan.
In the updateDrawState method, you should remove the super callback.
After that, you should Modify your text paint as required.
2. Without ClickableSpan
Add ForegroundColorSpan to change the text color
Add UnderlineSpan to add underline in text.
First Part **Second Part should be Bold** last Part
This text should be changed using SpannableString
import android.graphics.Typeface.BOLD
import android.text.Spannable
import android.text.Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
import android.text.SpannableString
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
val firstPart = "First Part "
val secondPart = "Second Part should be Bold"
val thirdPart = " last Part"
val finalString = firstPart + secondPart + thirdPart
val sb: Spannable = SpannableString(finalString).also {
// ... Change text Colour
it.setSpan(
ForegroundColorSpan(getColor(requireContext(), R.color.pink)),
finalString.indexOf(secondPart),
finalString.indexOf(secondPart) + secondPart.length,
SPAN_EXCLUSIVE_EXCLUSIVE
)
// ... Make the text Bold
it.setSpan(
StyleSpan(BOLD),
finalString.indexOf(secondPart),
finalString.indexOf(secondPart) + secondPart.length,
SPAN_EXCLUSIVE_EXCLUSIVE
)
// ... Change Background Colour
it.setSpan(
BackgroundColorSpan(getColor(requireContext(), R.color.lightPink)),
finalString.indexOf(secondPart) - 1,
finalString.indexOf(secondPart) + secondPart.length + 1,
SPAN_EXCLUSIVE_EXCLUSIVE
)
}
yourTextView.text = sb