下面列出了怎么用android.text.SpannableStringBuilder的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public CharSequence getMessageText(Context context) {
// Construct text to be displayed on the infobar.
SpannableStringBuilder infobarMessage = new SpannableStringBuilder(mMessage);
// If we have a link text to display, append it.
if (!TextUtils.isEmpty(mLinkText)) {
SpannableStringBuilder spannableLinkText = new SpannableStringBuilder(mLinkText);
ClickableSpan onLinkClicked = new ClickableSpan() {
@Override
public void onClick(View view) {
onLinkClicked();
}
};
spannableLinkText.setSpan(onLinkClicked, 0, spannableLinkText.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
infobarMessage.append(" ");
infobarMessage.append(spannableLinkText);
}
return infobarMessage;
}
@Test
public void spans_reversed() {
// resulting SpannableStringBuilder should have spans reversed
final Object[] spans = {
0,
1,
2
};
for (Object span : spans) {
builder.append(span.toString(), span);
}
final SpannableStringBuilder spannableStringBuilder = builder.spannableStringBuilder();
final Object[] actual = spannableStringBuilder.getSpans(0, builder.length(), Object.class);
for (int start = 0, length = spans.length, end = length - 1; start < length; start++, end--) {
assertEquals(spans[start], actual[end]);
}
}
private CharSequence prepareMainMessageString(final PermissionDialogDelegate delegate) {
SpannableStringBuilder fullString = new SpannableStringBuilder();
String messageText = delegate.getMessageText();
String linkText = delegate.getLinkText();
if (!TextUtils.isEmpty(messageText)) fullString.append(messageText);
// If the linkText exists, then wrap it in a clickable span and concatenate it with the main
// dialog message.
if (!TextUtils.isEmpty(linkText)) {
if (fullString.length() > 0) fullString.append(" ");
int spanStart = fullString.length();
fullString.append(linkText);
fullString.setSpan(new ClickableSpan() {
@Override
public void onClick(View view) {
mDecision = NOT_DECIDED;
delegate.onLinkClicked();
if (mDialog != null) mDialog.dismiss();
}
}, spanStart, fullString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return fullString;
}
@Test
public void process() {
// create markwon
final Markwon markwon = Markwon.create(RuntimeEnvironment.application);
// default punctuation
final MarkwonEditor editor = MarkwonEditor.create(markwon);
final SpannableStringBuilder builder = new SpannableStringBuilder("**bold**");
editor.process(builder);
final PunctuationSpan[] spans = builder.getSpans(0, builder.length(), PunctuationSpan.class);
assertEquals(2, spans.length);
final PunctuationSpan first = spans[0];
assertEquals(0, builder.getSpanStart(first));
assertEquals(2, builder.getSpanEnd(first));
final PunctuationSpan second = spans[1];
assertEquals(6, builder.getSpanStart(second));
assertEquals(8, builder.getSpanEnd(second));
}
private void sendEmoji(String override) {
String code = override != null ? override : (String) getTag();
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(code);
if (override == null) {
if (pager.getCurrentItem() != 0) {
String color = Emoji.emojiColor.get(code);
if (color != null) {
code = addColorToCode(code, color);
}
}
addEmojiToRecent(code);
if (listener != null) {
listener.onEmojiSelected(Emoji.fixEmoji(code));
}
} else {
if (listener != null) {
listener.onEmojiSelected(Emoji.fixEmoji(override));
}
}
}
/**
* 添加了@的加入
*
* @param userModel 用户实体
*/
public void resolveText(UserModel userModel) {
String userName = userModel.getUser_name();
userModel.setUser_name(userName + "\b");
nameList.add(userModel);
int index = getSelectionStart();
SpannableStringBuilder spannableStringBuilder =
new SpannableStringBuilder(getText());
//直接用span会导致后面没文字的时候新输入的一起变色
Spanned htmlText = Html.fromHtml(String.format("<font color='%s'>" + userName + "</font>", colorAtUser));
spannableStringBuilder.insert(index, htmlText);
spannableStringBuilder.insert(index + htmlText.length(), "\b");
setText(spannableStringBuilder);
setSelection(index + htmlText.length() + 1);
}
public HtmlToSpannedConverter(String subject, String source, ThemeColors colors, HtmlParser.ImageGetter imageGetter, boolean openSpoilers,
Parser parser) {
mSource = source;
mSpannableStringBuilder = new SpannableStringBuilder();
if (!TextUtils.isEmpty(subject)) {
mSpannableStringBuilder.append(subject);
int len = mSpannableStringBuilder.length();
mSpannableStringBuilder.setSpan(new RelativeSizeSpan(1.25f), 0, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mSpannableStringBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
if (colors != null) {
mSpannableStringBuilder.setSpan(new ForegroundColorSpan(colors.subjectForeground), 0, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mSpannableStringBuilder.append('\n');
mStartLength = mSpannableStringBuilder.length();
}
mColors = colors;
mOpenSpoilers = openSpoilers;
mImageGetter = imageGetter;
mReader = parser;
}
private static void endBlockquote(SpannableStringBuilder text, ThemeColors colors) {
int len = text.length();
Object obj = getLast(text, Blockquote.class);
int where = text.getSpanStart(obj);
text.removeSpan(obj);
if (where != len) {
Blockquote b = (Blockquote) obj;
if (b.mIsUnkfunc) {
if (colors != null) {
text.setSpan(new ForegroundColorSpan(colors.quoteForeground), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
text.setSpan(new QuoteSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
public static Spannable formatHighlightSpan(String html, Resources res) {
HighlightSpan highlightSpan;
if (Html.fromHtml(html) instanceof SpannableStringBuilder) {
SpannableStringBuilder value = (SpannableStringBuilder) Html.fromHtml(html);
StyleSpan[] spans = value.getSpans(0, html.length(), StyleSpan.class);
for (StyleSpan span : spans) {
int start = value.getSpanStart(span);
int end = value.getSpanEnd(span);
value.removeSpan(span);
highlightSpan = new HighlightSpan(res);
value.setSpan(highlightSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return value;
} else {
return new SpannableStringBuilder(html);
}
}
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
TextView tv = textView.get();
if (tv != null) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(tv.getResources(), bitmap);
// image span doesn't handle scaling so we manually set bounds
if (bitmap.getWidth() > tv.getWidth()) {
float aspectRatio = (float) bitmap.getHeight() / (float) bitmap.getWidth();
bitmapDrawable.setBounds(0, 0, tv.getWidth(), (int) (aspectRatio * tv.getWidth()));
} else {
bitmapDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
}
ImageSpan span = new ImageSpan(bitmapDrawable);
// add the image span and remove our marker
SpannableStringBuilder ssb = new SpannableStringBuilder(tv.getText());
int start = ssb.getSpanStart(loadingSpan);
int end = ssb.getSpanEnd(loadingSpan);
if (start >= 0 && end >= 0) {
ssb.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
ssb.removeSpan(loadingSpan);
// animate the change
TransitionManager.beginDelayedTransition((ViewGroup) tv.getParent());
tv.setText(ssb);
}
}
private static void handleP(SpannableStringBuilder text, int startLength, int[] lastPTagLengthRefs) {
lastPTagLengthRefs[0] = text.length();
int len = text.length() - startLength;
if (len >= 1 && text.charAt(text.length() - 1) == '\n') {
if (len >= 2 && text.charAt(text.length() - 2) == '\n') {
lastPTagLengthRefs[1] = text.length();
return;
}
text.append("\n");
lastPTagLengthRefs[1] = text.length();
return;
}
if (len != 0) {
text.append("\n\n");
}
lastPTagLengthRefs[1] = text.length();
}
@Override
protected String getAccessibilityContentDescription(@NonNull final Context context) {
final SpannableStringBuilder builder = new SpannableStringBuilder();
final PayerCost currentInstallment = getCurrent();
final String money = context.getResources().getString(R.string.px_money);
builder
.append(currentInstallment.getInstallments().toString())
.append(TextUtil.SPACE)
.append(context.getResources().getString(R.string.px_date_divider))
.append(TextUtil.SPACE)
.append(currentInstallment.getInstallmentAmount().toString())
.append(TextUtil.SPACE)
.append(money)
.append(TextUtil.SPACE)
.append(hasAmountDescriptor() ? currentInstallment.getTotalAmount().floatValue() + money : TextUtil.EMPTY)
.append(hasInterestFree() ? interestFree.getInstallmentRow().getMessage() : TextUtil.EMPTY);
updateCFTSpannable(builder, context);
updateInstallmentsInfo(builder, context);
return builder.toString();
}
/**
* Builds a Spannable containing all of the styled text in the supplied ImageLine.
*
* @param line All text fields within this line will be added to the returned Spannable.
* types.
* @param metrics Font metrics which will be used to properly size and layout images and top-
* aligned text.
* @param density Screen density which will be used to properly size and layout images and top-
* aligned text.
*/
static Spannable buildSpannable(
SuggestionAnswer.ImageLine line, Paint.FontMetrics metrics, float density) {
SpannableStringBuilder builder = new SpannableStringBuilder();
// Determine the height of the largest text element in the line. This
// will be used to top-align text and scale images.
int maxTextHeightSp = getMaxTextHeightSp(line);
List<SuggestionAnswer.TextField> textFields = line.getTextFields();
for (int i = 0; i < textFields.size(); i++) {
appendAndStyleText(builder, textFields.get(i), maxTextHeightSp, metrics, density);
}
if (line.hasAdditionalText()) {
builder.append(" ");
SuggestionAnswer.TextField additionalText = line.getAdditionalText();
appendAndStyleText(builder, additionalText, maxTextHeightSp, metrics, density);
}
if (line.hasStatusText()) {
builder.append(" ");
SuggestionAnswer.TextField statusText = line.getStatusText();
appendAndStyleText(builder, statusText, maxTextHeightSp, metrics, density);
}
return builder;
}
/** Classifies a frame from the preview stream. */
void classifyFrame(Bitmap bitmap, SpannableStringBuilder builder) {
if (tflite == null) {
Log.e(TAG, "Image classifier has not been initialized; Skipped.");
builder.append(new SpannableString("Uninitialized Classifier."));
}
convertBitmapToByteBuffer(bitmap);
// Here's where the magic happens!!!
long startTime = SystemClock.uptimeMillis();
runInference();
long endTime = SystemClock.uptimeMillis();
Log.d(TAG, "Timecost to run model inference: " + Long.toString(endTime - startTime));
// Smooth the results across frames.
applyFilter();
// Print the results.
printTopKLabels(builder);
long duration = endTime - startTime;
SpannableString span = new SpannableString(duration + " ms");
span.setSpan(new ForegroundColorSpan(android.graphics.Color.LTGRAY), 0, span.length(), 0);
builder.append(span);
}
public static SpannableStringBuilder highlight(String text) {
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
CharacterStyle span = null;
span = new ForegroundColorSpan(Color.rgb(253, 113, 34));// 需要重复!
spannable.setSpan(span, 0, text.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
protected CharSequence getStyledMessage(@NonNull Recipient recipient, @Nullable CharSequence message) {
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(Util.getBoldedString(recipient.toShortString(context)));
builder.append(": ");
builder.append(message == null ? "" : message);
return builder;
}
@Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) {
String src = node.getAttributeByName("src");
if (!InputHelper.isEmpty(src)) {
builder.append("");
if (isNull()) return;
DrawableGetter imageGetter = new DrawableGetter(textView, width);
builder.setSpan(new ImageSpan(imageGetter.getDrawable(src)), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new CenterSpan(), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
appendNewLine(builder);
}
}
/**
* Creates the ticker text for a notification having |title| and |body|. The notification's
* title will be printed in bold, followed by the text of the body.
*
* @param title Title of the notification.
* @param body Textual contents of the notification.
* @return A character sequence containing the ticker's text.
*/
private CharSequence createTickerText(String title, String body) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append(title);
spannableStringBuilder.append("\n");
spannableStringBuilder.append(body);
// Mark the title of the notification as being bold.
spannableStringBuilder.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
0, title.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
return spannableStringBuilder;
}
public void show(int account, TLRPC.TL_help_termsOfService tos) {
if (getVisibility() != VISIBLE) {
setVisibility(VISIBLE);
}
SpannableStringBuilder builder = new SpannableStringBuilder(tos.text);
MessageObject.addEntitiesToText(builder, tos.entities, false, false, false, false);
addBulletsToText(builder, '-', AndroidUtilities.dp(10f), 0xff50a8eb, AndroidUtilities.dp(4f));
textView.setText(builder);
currentTos = tos;
currentAccount = account;
}
private void ellipsizeAnyTextForMaxLength() {
if (maxLength > 0 && getText().length() > maxLength + 1) {
SpannableStringBuilder newContent = new SpannableStringBuilder();
newContent.append(getText().subSequence(0, maxLength)).append(ELLIPSIS).append(Optional.fromNullable(overflowText).or(""));
EmojiParser.CandidateList newCandidates = EmojiProvider.getInstance(getContext()).getCandidates(newContent);
if (useSystemEmoji || newCandidates == null || newCandidates.size() == 0) {
super.setText(newContent, BufferType.NORMAL);
} else {
CharSequence emojified = EmojiProvider.getInstance(getContext()).emojify(newCandidates, newContent, this);
super.setText(emojified, BufferType.SPANNABLE);
}
}
}
/**
* Helper function to process font objects used for title and subtitle
*
* @param Context - TiApplication context
* @param Object - the properties as hashmap
* @param Text - SpannableStringBuilder that should get the properties applied
* @param TypefaceSpan - font reference (for title or subtitle)
*/
private SpannableStringBuilder applyFontProperties(TiApplication appContext, HashMap<String, String> d, SpannableStringBuilder ssb, TypefaceSpan font){
if (d.containsKey(TiC.PROPERTY_FONTFAMILY)){
String fontFamily = d.get(TiC.PROPERTY_FONTFAMILY).replaceAll("\\.(ttf|otf|fnt)$", "");
font = new TypefaceSpan(appContext, fontFamily);
ssb.setSpan(font, 0, ssb.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
if (d.containsKey(TiC.PROPERTY_FONTSIZE)){
Object value = d.get(TiC.PROPERTY_FONTSIZE);
boolean dip = false;
int fontSize;
if (value instanceof String){
// is there a better way to convert Strings ("16px", "22sp" etc.) to dip?
fontSize = (int) TiUIHelper.getRawSize(
TiUIHelper.getSizeUnits((String) value),
TiUIHelper.getSize((String) value),
appContext
);
}else {
fontSize = (Integer) value;
dip = true;
}
ssb.setSpan(new AbsoluteSizeSpan(fontSize, dip), 0, ssb.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
if (d.containsKey(TiC.PROPERTY_FONTWEIGHT)){
String fontWeight = d.get(TiC.PROPERTY_FONTWEIGHT);
ssb.setSpan(new StyleSpan(TiUIHelper.toTypefaceStyle(fontWeight, null)), 0, ssb.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
return ssb;
}
public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mLauncher = Launcher.getLauncher(context);
mApps = new AlphabeticalAppsList(context);
mAdapter = new AllAppsGridAdapter(mLauncher, mApps, mLauncher, this);
mApps.setAdapter(mAdapter);
mLayoutManager = mAdapter.getLayoutManager();
mSearchQueryBuilder = new SpannableStringBuilder();
mSearchContainerMinHeight
= getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_height);
Selection.setSelection(mSearchQueryBuilder, 0);
}
@Override
@CallSuper
public void setText(CharSequence rawText, BufferType type) {
final CharSequence text = rawText == null ? "" : rawText;
final SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
if (mEmoticonProvider != null)
EmoticonUtils.replaceWithImages(getContext(), spannableStringBuilder, mEmoticonProvider, mEmoticonSize);
super.setText(text, type);
}
@SuppressWarnings("ReferenceEquality")
private static void attachFontFamily(SpannableStringBuilder cueText, String fontFamily,
String defaultFontFamily, int start, int end, int spanPriority) {
if (fontFamily != defaultFontFamily) {
cueText.setSpan(new TypefaceSpan(fontFamily), start, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | spanPriority);
}
}
private static SpannableStringBuilder getRegionOutput(
String resolvedRegionId, Map<String, SpannableStringBuilder> regionOutputs) {
if (!regionOutputs.containsKey(resolvedRegionId)) {
regionOutputs.put(resolvedRegionId, new SpannableStringBuilder());
}
return regionOutputs.get(resolvedRegionId);
}
public static SpannableStringBuilder getCrosspostLine(Submission s, Context mContext) {
if (crosspost == null) crosspost = new WeakHashMap<>();
if (crosspost.containsKey(s.getFullName())) {
return crosspost.get(s.getFullName());
} else {
return getCrosspostSpannable(s, mContext);
}
}
@Override
public void setText(CharSequence text, BufferType type) {
if (!TextUtils.isEmpty(text)) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
EmojiconHandler.addEmojis(getContext(), builder, mEmojiconSize, mTextStart, mTextLength, mUseSystemDefault);
text = builder;
}
super.setText(text, type);
}
@Override
public SpannableStringBuilder ol(CharSequence charSequence, int level, int index) {
SpannableStringBuilder spannableStringBuilder = SpannableStringBuilder.valueOf(charSequence);
BulletSpan bulletSpan = new MarkDownBulletSpan(level, h1_text_color, index);
spannableStringBuilder.setSpan(bulletSpan, 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableStringBuilder;
}
@Override
public void processChatView(ViewGroup parent, final IMessageItem item) {
IMMessage message = item.getMessage();
final Context context = item.getContext();
try {
MedalRemindDataBean meetingDataBean = JsonUtils.getGson().fromJson(message.getExt()
, MedalRemindDataBean.class);
MedalClickRemindView meetingRemindView = ViewPool.getView(MedalClickRemindView.class, context);
SpannableStringBuilder sb = new SpannableStringBuilder();
String[] strs = meetingDataBean.getStrMap().getAllStr().split(meetingDataBean.getStrMap().getHighlightStr());
Spanned color = Html.fromHtml("<font color='#00cabe'>" + meetingDataBean.getStrMap().getHighlightStr() + "</font>");
if (strs.length > 1) {
sb.append(strs[0]);
sb.append(color);
sb.append(strs[1]);
}
meetingRemindView.setSB(sb);
meetingRemindView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// context.startActivity( FlutterMedalActivity.makeIntent(context,CurrentPreference.getInstance().getPreferenceUserId()));
}
});
parent.setVisibility(View.VISIBLE);
parent.addView(meetingRemindView);
} catch (Exception e) {
e.printStackTrace();
}
}
private void appendParagraphNewLines(SpannableStringBuilder out) {
int len = out.length();
if (len >= 1 && out.charAt(len - 1) == '\n') {
if (len >= 2 && out.charAt(len - 2) == '\n') {
return;
}
out.append("\n");
return;
}
if (out.length() != 0) {
out.append("\n\n");
}
}