ata*_*oyh 89 android textview uitextview
text = text + CepVizyon.getPhoneCode() + "\n\n"
+ getText(R.string.currentversion) + CepVizyon.getLicenseText();
activationText.setText(text);
myTextView.setText(text);
Run Code Online (Sandbox Code Playgroud)
我想改变CepVizyon.getPhoneCode()字符串的颜色.我怎样才能做到这一点?
and*_*oot 154
Spannable更灵活:
String text2 = text + CepVizyon.getPhoneCode() + "\n\n"
+ getText(R.string.currentversion) + CepVizyon.getLicenseText();
Spannable spannable = new SpannableString(text2);
spannable.setSpan(new ForegroundColorSpan(Color.WHITE), text.length(), (text + CepVizyon.getPhoneCode()).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
myTextView.setText(spannable, TextView.BufferType.SPANNABLE);
Run Code Online (Sandbox Code Playgroud)
Man*_*esh 66
myTextView.setText(Html.fromHtml(text + "<font color=white>" + CepVizyon.getPhoneCode() + "</font><br><br>"
+ getText(R.string.currentversion) + CepVizyon.getLicenseText()));
Run Code Online (Sandbox Code Playgroud)
Fon*_*nix 48
如果您有需要颜色的静态文本,可以通过strings文件添加它而不需要任何代码:
<string name="already_have_an_account">Already have an account? <font color='#01C6DB'>Login</font></string>
Run Code Online (Sandbox Code Playgroud)
然后
<TextView
android:layout_width="wrap_content"
android:layout_height="64dp"
android:text="@string/already_have_an_account"/>
Run Code Online (Sandbox Code Playgroud)
结果
不确定这个api版本是什么工作,但是到目前为止我测试的api 19都不起作用,所以可能只有一些最新的api版本支持这个
编辑:正如@hairraisin在评论中提到的,尝试使用fgcolor而不是color字体颜色,那么它应该适用于较低的api级别,但需要更多测试才能确定
Joe*_*ouz 15
关于Maneesh的答案,这将有效,但您需要添加和转义color属性的引号.
myTextView.setText(Html.fromHtml(text + "<font color=\"#FFFFFF\">" + CepVizyon.getPhoneCode() + "</font><br><br>"
+ getText(R.string.currentversion) + CepVizyon.getLicenseText()));
Run Code Online (Sandbox Code Playgroud)
Dmi*_*nov 12
这是 Kotlin 中用于SpannableString更改字符串部分颜色的解决方案。
val phoneCodeColor = ContextCompat.getColor(this, R.color.myColor)
val text = SpannableStringBuilder()
.color(phoneCodeColor) { append("${ CepVizyon.getPhoneCode() }") }
.append("\n\n")
.append(getString(R.string.currentversion))
.append(${ CepVizyon.getLicenseText() })
activationText.text = text
myTextView.text = text
Run Code Online (Sandbox Code Playgroud)
使用通用 Kotlin 扩展函数,它看起来像这样:
/**
* Change the color of a part of the text contained in this textView
*
* @param subStringToColorize has to already be set in the textView's text
* @param colorResId
*/
fun TextView.colorize(subStringToColorize: String, @ColorRes colorResId: Int) {
val spannable: Spannable = SpannableString(text)
val startIndex = text.indexOf(subStringToColorize, startIndex = 0, ignoreCase = false)
val endIndex = startIndex + subStringToColorize.length
val color: Int = ContextCompat.getColor(context, colorResId)
if (startIndex != -1) {
spannable.setSpan(ForegroundColorSpan(color),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setText(spannable, TextView.BufferType.SPANNABLE)
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个colorize基于 andyboot 回答的函数:
/**
* Colorize a specific substring in a string for TextView. Use it like this: <pre>
* textView.setText(
* Strings.colorized("The some words are black some are the default.","black", Color.BLACK),
* TextView.BufferType.SPANNABLE
* );
* </pre>
* @param text Text that contains a substring to colorize
* @param word The substring to colorize
* @param argb The color
* @return the Spannable for TextView's consumption
*/
public static Spannable colorized(final String text, final String word, final int argb) {
final Spannable spannable = new SpannableString(text);
int substringStart=0;
int start;
while((start=text.indexOf(word,substringStart))>=0){
spannable.setSpan(
new ForegroundColorSpan(argb),start,start+word.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
substringStart = start+word.length();
}
return spannable;
}
Run Code Online (Sandbox Code Playgroud)
如何将字符串存储在字符串资源文件夹中
<string name="textFromRes">
<font color="#FF0000">This is colored in red </font> This is not
</string>
Run Code Online (Sandbox Code Playgroud)
如何在 TextView 中显示?
String text = this.getResources().getString(R.string.textFromRes);
htmlText.setText(Html.fromHtml(text));
Run Code Online (Sandbox Code Playgroud)
输出中的字符串如下所示
<string name="textFromRes">
<font color="#FF0000">This is colored in red </font> This is not
<br />
<h1> This is h1 heading </h1>
<br />
<h3> This is h2 subheading</h3>
<br />
<b> This text is bold</b>
<br />
<i> This text is italic</i>
<br />
Android users expect your app to look and behave in a way that is
consistent with the platform. Not only should you follow material
design guidelines for visual and navigation patterns,
but you should also follow quality guidelines for compatibility,
performance, security, and more.
<br />
<br />
The following links provide everything you need to design a high quality Android app.
</string>
Run Code Online (Sandbox Code Playgroud)
这对我有好处!
Spannable spannable = new SpannableString("ABC In-Network DEF");
String str = spannable.toString();
iStart = str.indexOf("In-Network");
iEnd = iStart + 10;/*10 characters = in-network. */
SpannableString ssText = new SpannableString(spannable);
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View widget) {
//your code at here.
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(true);
ds.setColor(getResources().getColor(R.color.green));
}
};
ssText.setSpan(clickableSpan, iStart, iEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.setText(ssText);
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
mTextView.setHighlightColor(Color.TRANSPARENT);
mTextView.setEnabled(true);
Run Code Online (Sandbox Code Playgroud)
我不喜欢每次我想要对文本的某些部分进行着色时都通过代码执行此操作的想法,我在所有应用程序中都做了很多事情(并且因为在某些情况下文本是在运行时使用不同的内联设置的)定义的颜色)所以我创建了自己的MarkableTextView.
我们的想法是:
这是一步一步的过程:
首先,我需要一种在给定字符串中查找 XML 标签的方法,并且Regex成功了。
<([a-zA-Z]+(?:-[a-zA-Z0-9]+)*)(?:\s+([^>]*))?>([^>][^<]*)</\1\s*>
Run Code Online (Sandbox Code Playgroud)
为了使上述内容与 XML 标签相匹配,它必须满足以下条件:
<a> <a > <a-a> <a ..attrs..>但不是< a> <1><a></a>但不匹配的结束标记<a></b>现在对于属性我们将使用这个..
([a-zA-Z]+)\s*=\s*(['"])\s*([^'"]+?)\s*\2
Run Code Online (Sandbox Code Playgroud)
它具有相同的概念,通常我不需要为两者走得太远,因为如果有任何内容不符合格式,编译器将处理其余的事情。
现在我们需要一个可以保存提取数据的类:
public class MarkableSheet {
private String attributes;
private String content;
private int outset;
private int ending;
private int offset;
private int contentLength;
public MarkableSheet(String attributes, String content, int outset, int ending, int offset, int contentLength) {
this.attributes = attributes;
this.content = content;
this.outset = outset;
this.ending = ending;
this.offset = offset;
this.contentLength = contentLength;
}
public String getAttributes() {
return attributes;
}
public String getContent() {
return content;
}
public int getOutset() {
return outset;
}
public int getContentLength() {
return contentLength;
}
public int getEnding() {
return ending;
}
public int getOffset() {
return offset;
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我们要添加这个很酷的迭代器,我已经使用它很长时间来循环匹配(不记得作者了):
public static Iterable<MatchResult> matches(final Pattern p, final CharSequence input) {
return new Iterable<MatchResult>() {
public Iterator<MatchResult> iterator() {
return new Iterator<MatchResult>() {
// Use a matcher internally.
final Matcher matcher = p.matcher(input);
// Keep a match around that supports any interleaving of hasNext/next calls.
MatchResult pending;
public boolean hasNext() {
// Lazily fill pending, and avoid calling find() multiple times if the
// clients call hasNext() repeatedly before sampling via next().
if (pending == null && matcher.find()) {
pending = matcher.toMatchResult();
}
return pending != null;
}
public MatchResult next() {
// Fill pending if necessary (as when clients call next() without
// checking hasNext()), throw if not possible.
if (!hasNext()) { throw new NoSuchElementException(); }
// Consume pending so next call to hasNext() does a find().
MatchResult next = pending;
pending = null;
return next;
}
/** Required to satisfy the interface, but unsupported. */
public void remove() { throw new UnsupportedOperationException(); }
};
}
};
}
Run Code Online (Sandbox Code Playgroud)
可标记文本视图:
public class MarkableTextView extends AppCompatTextView {
public MarkableTextView(Context context) {
super(context);
}
public MarkableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MarkableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setText(CharSequence text, BufferType type) {
// Intercept and process text
text = prepareText(text.toString());
super.setText(text, type);
}
public Spannable Markable;
private Spannable prepareText(String text) {
String parcel = text;
Multimap<String, MarkableSheet> markableSheets = ArrayListMultimap.create();
// Used to correct content position after tossing tags
int totalOffset = 0;
// Iterate through text
for (MatchResult match : matches(Markable.Patterns.XML, parcel)) {
// Get tag name
String tag = match.group(1);
// Match with a defined tag name "case-sensitive"
if (!tag.equals(Markable.Tags.MARKABLE)) {
// Break if no match
break;
}
// Extract data
String attributes = match.group(2);
String content = match.group(3);
int outset = match.start(0);
int ending = match.end(0);
int offset = totalOffset; // offset=0 since no preceded changes happened
int contentLength = match.group(3).length();
// Calculate offset for the next element
totalOffset = (ending - outset) - contentLength;
// Add to markable sheets
MarkableSheet sheet =
new MarkableSheet(attributes, content, outset, ending, offset, contentLength);
markableSheets.put(tag, sheet);
// Toss the tag and keep content
Matcher reMatcher = Markable.Patterns.XML.matcher(parcel);
parcel = reMatcher.replaceFirst(content);
}
// Initialize spannable with the modified text
Markable = new SpannableString(parcel);
// Iterate through markable sheets
for (MarkableSheet sheet : markableSheets.values()) {
// Iterate through attributes
for (MatchResult match : matches(Markable.Patterns.ATTRIBUTES, sheet.getAttributes())) {
String attribute = match.group(1);
String value = match.group(3);
// Apply styles
stylate(attribute,
value,
sheet.getOutset(),
sheet.getOffset(),
sheet.getContentLength());
}
}
return Markable;
}
Run Code Online (Sandbox Code Playgroud)
最后,样式,所以这是我为此答案制作的一个非常简单的样式器:
public void stylate(String attribute, String value, int outset, int offset, int length) {
// Correct position
outset -= offset;
length += outset;
if (attribute.equals(Markable.Tags.TEXT_STYLE)) {
if (value.contains(Markable.Tags.BOLD) && value.contains(Markable.Tags.ITALIC)) {
Markable.setSpan(
new StyleSpan(Typeface.BOLD_ITALIC),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.contains(Markable.Tags.BOLD)) {
Markable.setSpan(
new StyleSpan(Typeface.BOLD),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.contains(Markable.Tags.ITALIC)) {
Markable.setSpan(
new StyleSpan(Typeface.ITALIC),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (value.contains(Markable.Tags.UNDERLINE)) {
Markable.setSpan(
new UnderlineSpan(),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
if (attribute.equals(Markable.Tags.TEXT_COLOR)) {
if (value.equals(Markable.Tags.ATTENTION)) {
Markable.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(
getContext(),
R.color.colorAttention)),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.equals(Markable.Tags.INTERACTION)) {
Markable.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(
getContext(),
R.color.colorInteraction)),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Markable包含定义的类如下所示:
public class Markable {
public static class Patterns {
public static final Pattern XML =
Pattern.compile("<([a-zA-Z]+(?:-[a-zA-Z0-9]+)*)(?:\\s+([^>]*))?>([^>][^<]*)</\\1\\s*>");
public static final Pattern ATTRIBUTES =
Pattern.compile("(\\S+)\\s*=\\s*(['\"])\\s*(.+?)\\s*\\2");
}
public static class Tags {
public static final String MARKABLE = "markable";
public static final String TEXT_STYLE = "textStyle";
public static final String BOLD = "bold";
public static final String ITALIC = "italic";
public static final String UNDERLINE = "underline";
public static final String TEXT_COLOR = "textColor";
public static final String ATTENTION = "attention";
public static final String INTERACTION = "interaction";
}
}
Run Code Online (Sandbox Code Playgroud)
我们现在需要的只是引用一个字符串,基本上它应该如下所示:
<string name="markable_string">
<![CDATA[Hello <markable textStyle=\"underline\" textColor=\"interaction\">world</markable>!]]>
</string>
Run Code Online (Sandbox Code Playgroud)
确保用 a 包裹标签并用CDATA Section转义。"\
我将其作为一个模块化解决方案,以各种不同的方式处理文本的各个部分,而不需要在后面填充不必要的代码。
我按照安迪·布特所说的做了,但我也有一个可点击的跨度,但它不起作用,因为setSpans调用了顺序。所以你必须先调用spannable.setSpan(clickableSpanand...thenspannable.setSpan(new ForegroundColorSpan...来获取 TextView 中的颜色
我做了这个小功能,只需将您的文本传递给颜色,您想要为该文本着色的开始和结束索引以及颜色本身
private fun colorMyText(inputText:String,startIndex:Int,endIndex:Int,textColor:Int):Spannable{
val outPutColoredText: Spannable = SpannableString(inputText)
outPutColoredText.setSpan(
ForegroundColorSpan(textColor), startIndex, endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
return outPutColoredText
}
Run Code Online (Sandbox Code Playgroud)
txt_comment.text = colorMyText("Comentario: ${item.comentario}",0,13,Color.BLACK)
Run Code Online (Sandbox Code Playgroud)
小智 5
受到上面Alejandro H. Cruz 的回答的启发。
他的函数仅适用于单个子字符串匹配,我已经更新了他的方法以使用正则表达式,并且应该更新所有匹配的颜色:
fun TextView.colorizeAll(subStringToColorize: String, @ColorRes colorResId: Int) {
val color: Int = ContextCompat.getColor(context, colorResId)
val spannable: Spannable = SpannableString(text)
val pattern = subStringToColorize.toRegex()
val matches = pattern.findAll(text, 0)
matches.forEach { match ->
val startIndex = match.range.first
val endIndex = match.range.last + match.range.step
spannable.setSpan(ForegroundColorSpan(color),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setText(spannable, TextView.BufferType.SPANNABLE)
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了这个小助手方法,可以从以下位置调用TextView:
fun TextView.attributedString(
forText: String,
foregroundColor: Int? = null,
style: StyleSpan? = null
) {
val spannable: Spannable = SpannableString(text)
// check if the text we're highlighting is empty to abort
if (forText.isEmpty()) {
return
}
// compute the start and end indices from the text
val startIdx = text.indexOf(forText)
val endIdx = startIdx + forText.length
// if the indices are out of bounds, abort as well
if (startIdx < 0 || endIdx > text.length) {
return
}
// check if we can apply the foreground color
foregroundColor?.let {
spannable.setSpan(
ForegroundColorSpan(it),
startIdx,
endIdx,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
}
// check if we have a stylespan
style?.let {
spannable.setSpan(
style,
startIdx,
endIdx,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
}
// apply it
text = spannable
}
Run Code Online (Sandbox Code Playgroud)
使用方法:
plateText.text = "Hello world!"
// This will color the part "world" to whatever color you have defined
// And make the word **bold**.
plateText.attributedString(
"world",
getColor(R.color.colorMatchingText, null),
StyleSpan(Typeface.BOLD)
)
Run Code Online (Sandbox Code Playgroud)
在 API 29 上测试,干杯!
| 归档时间: |
|
| 查看次数: |
69493 次 |
| 最近记录: |