下面列出了android.text.SpannableStringBuilder#append ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 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);
}
/**
* Prepares text to be displayed as the infobar's main message, including setting up a
* clickable link if the infobar requires it.
*/
private CharSequence prepareMainMessageString() {
SpannableStringBuilder fullString = new SpannableStringBuilder();
if (mMessageMainText != null) fullString.append(mMessageMainText);
// Concatenate the text to display for the link and make it clickable.
if (!TextUtils.isEmpty(mMessageLinkText)) {
if (fullString.length() > 0) fullString.append(" ");
int spanStart = fullString.length();
fullString.append(mMessageLinkText);
fullString.setSpan(new ClickableSpan() {
@Override
public void onClick(View view) {
mInfoBarView.onLinkClicked();
}
}, spanStart, fullString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return fullString;
}
@NonNull
@Override
protected StaticLayout makeLayout(CharSequence text, int maxWidth, boolean exactly) {
mWithEllipsisLayout = super.makeLayout(text, maxWidth, exactly);
SpannableStringBuilder textWithExtraEnd = new SpannableStringBuilder(text);
textWithExtraEnd.append(COLLAPSE_NORMAL);
if (mCollapseSpan != null) {
textWithExtraEnd.setSpan(mCollapseSpan, textWithExtraEnd.length() - 1,
textWithExtraEnd.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
StaticLayoutBuilderCompat layoutBuilder =
createAllStaticLayoutBuilder(textWithExtraEnd, 0, textWithExtraEnd.length(), getPaint(),
maxWidth > 0 ? Math.min(maxWidth, mWithEllipsisLayout.getWidth()) :
mWithEllipsisLayout.getWidth());
layoutBuilder.setLineSpacing(mAttrsHelper.mSpacingAdd, mAttrsHelper.mSpacingMultiplier)
.setAlignment(TextViewAttrsHelper.getLayoutAlignment(this, getGravity()))
.setIncludePad(true);
beforeAllStaticLayoutBuild(layoutBuilder);
mAllTextLayout = layoutBuilder.build();
return mWithEllipsisLayout;
}
public static void linkify(Activity activity, TextView textView, String linkText, String url) {
String text = textView.getText().toString();
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(text);
builder.setSpan(
new ClickableSpan() {
@Override
public void onClick(View view) {
showWebPage(activity, url);
}
},
text.indexOf(linkText),
text.indexOf(linkText) + linkText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
textView.setText(builder);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* Sets the edittext's hint icon and text.
*
* @param editText
* @param drawableResource
* @param hintText
*/
public static void setSearchHintWithColorIcon(EditText editText, int drawableResource, int textColor, String hintText) {
try {
SpannableStringBuilder stopHint = new SpannableStringBuilder(" ");
stopHint.append(hintText);
// Add the icon as an spannable
Drawable searchIcon = editText.getContext().getResources().getDrawable(drawableResource);
Float rawTextSize = editText.getTextSize();
int textSize = (int) (rawTextSize * 1.25);
searchIcon.setBounds(0, 0, textSize, textSize);
stopHint.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Set the new hint text
editText.setHint(stopHint);
//searchBox.setTextColor(Color.WHITE);
editText.setHintTextColor(textColor);
} catch (Exception e) {
Log.e("EditTextUtil", e.getMessage(), e);
}
}
public Spannable getChatMessage(Context context) {
if (spannedText == null) {
Spannable dateSpan = createDateSpannable(context);
Spannable textSpan = createText(context);
// Time
SpannableStringBuilder finishedText = new SpannableStringBuilder(dateSpan);
// Delimiter
finishedText.append(delimiterBetweenDateAndName);
// Name
finishedText.append(new NameSpannable(owner, getNameColorId(), context.getResources()));
// Delimiter
finishedText.append(delimiterBetweenNameAndText);
// Message
finishedText.append(textSpan);
// Add overall styles
if (getTypeFace() != null) {
finishedText.setSpan(new StyleSpan(getTypeFace()), DATE_CHAR_LENGTH, finishedText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
spannedText = finishedText;
}
return spannedText;
}
public XImageSpan createAndPutChipForUser(TLRPC.User user) {
LayoutInflater lf = (LayoutInflater) parentActivity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View textView = lf.inflate(R.layout.group_create_bubble, null);
TextView text = (TextView) textView.findViewById(R.id.bubble_text_view);
String name = Utilities.formatName(user.first_name, user.last_name);
if (name.length() == 0 && user.phone != null && user.phone.length() != 0) {
name = PhoneFormat.getInstance().format("+" + user.phone);
}
text.setText(name + ", ");
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
textView.measure(spec, spec);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(textView.getWidth(), textView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
canvas.translate(-textView.getScrollX(), -textView.getScrollY());
textView.draw(canvas);
textView.setDrawingCacheEnabled(true);
Bitmap cacheBmp = textView.getDrawingCache();
Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
textView.destroyDrawingCache();
final BitmapDrawable bmpDrawable = new BitmapDrawable(b);
bmpDrawable.setBounds(0, 0, b.getWidth(), b.getHeight());
SpannableStringBuilder ssb = new SpannableStringBuilder("");
XImageSpan span = new XImageSpan(bmpDrawable, ImageSpan.ALIGN_BASELINE);
allSpans.add(span);
selectedContacts.put(user.jid, span);
for (ImageSpan sp : allSpans) {
ssb.append("<<");
ssb.setSpan(sp, ssb.length() - 2, ssb.length(), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
}
userSelectEditText.setText(ssb);
userSelectEditText.setSelection(ssb.length());
return span;
}
@Override
public CharSequence getText(float textSize) {
Drawable bookImage = DrawableManager.getVectorDrawable(getContext2(), R.drawable.v_book_open_x24);
SpannableStringBuilder ssb = new SpannableStringBuilder(" ");
ssb.append(getResources2().getString(R.string.gallery_list_search_bar_open_gallery));
int imageSize = (int) (textSize * 1.25);
if (bookImage != null) {
bookImage.setBounds(0, 0, imageSize, imageSize);
ssb.setSpan(new ImageSpan(bookImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return ssb;
}
/**
* 增加提示文字
*
* @param span
* @param type
*/
private void addTip(SpannableStringBuilder span, BufferType type) {
if (!(isExpand && !isShowTipAfterExpand)) {
//折叠或者展开并且展开后显示提示
if (mTipGravity == END) {
span.append(" ");
} else {
span.append("\n");
}
int length;
if (isExpand) {
span.append(mExpandText);
length = mExpandText.length();
} else {
span.append(mFoldText);
length = mFoldText.length();
}
if (mTipClickable) {
span.setSpan(mSpan, span.length() - length, span.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
if (isParentClick) {
setMovementMethod(MyLinkMovementMethod.getInstance());
setClickable(false);
setFocusable(false);
setLongClickable(false);
} else {
setMovementMethod(LinkMovementMethod.getInstance());
}
}
span.setSpan(new ForegroundColorSpan(mTipColor), span.length() - length, span.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
super.setText(span, type);
}
public void updateRecognizedText(String stableText, String pendingText) {
if (DEBUG) Log.d(TAG, "updateText(" + stableText + "," + pendingText + ")");
if (stableText == null) {
stableText = "";
}
SpannableStringBuilder displayText = new SpannableStringBuilder(stableText);
if (DOTS_FOR_STABLE) {
addDottySpans(displayText, stableText, 0);
}
if (pendingText != null) {
int pendingTextStart = displayText.length();
displayText.append(pendingText);
if (DOTS_FOR_PENDING) {
addDottySpans(displayText, pendingText, pendingTextStart);
} else {
int pendingColor = getResources().getColor(
R.color.lb_search_plate_hint_text_color);
addColorSpan(displayText, pendingColor, pendingText, pendingTextStart);
}
}
// Start streaming in dots from beginning of partials, or current position,
// whichever is larger
mStreamPosition = Math.max(stableText.length(), mStreamPosition);
// Copy the text and spans to a SpannedString, since editable text
// doesn't redraw in invalidate() when hardware accelerated
// if the text or spans havent't changed. (probably a framework bug)
updateText(new SpannedString(displayText));
if (ANIMATE_DOTS_FOR_PENDING) {
startStreamAnimation();
}
}
@Override public void handleTagNode(TagNode tagNode, SpannableStringBuilder spannableStringBuilder, int i, int i1) {
spannableStringBuilder.append("\n");
SpannableStringBuilder builder = new SpannableStringBuilder("$");
HrSpan hrSpan = new HrSpan(color, width);
builder.setSpan(hrSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new CenterSpan(), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append("\n");
spannableStringBuilder.append(builder);
}
@BindingAdapter("android:text")
public static void setText(TextView text, SubjectWithImportance subjectWithImportance) {
if (subjectWithImportance == null || subjectWithImportance.subject == null) {
text.setText(null);
return;
}
if (subjectWithImportance.important) {
SpannableStringBuilder header = new SpannableStringBuilder(subjectWithImportance.subject);
header.append("\u2004\u00bb"); // 1/3 em - 1/2 em would be 2002
header.setSpan(new ImageSpan(text.getContext(), R.drawable.ic_important_amber_22sp, DynamicDrawableSpan.ALIGN_BASELINE), header.length() - 1, header.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setText(header);
} else {
text.setText(subjectWithImportance.subject);
}
}
private void setSearchBarHint(Context context, SearchBar searchBar) {
Resources resources = context.getResources();
Drawable searchImage = DrawableManager.getVectorDrawable(context, R.drawable.v_magnify_x24);
SpannableStringBuilder ssb = new SpannableStringBuilder(" ");
ssb.append(resources.getString(EhUrl.SITE_EX == Settings.getGallerySite() ?
R.string.gallery_list_search_bar_hint_exhentai :
R.string.gallery_list_search_bar_hint_e_hentai));
int textSize = (int) (searchBar.getEditTextTextSize() * 1.25);
if (searchImage != null) {
searchImage.setBounds(0, 0, textSize, textSize);
ssb.setSpan(new ImageSpan(searchImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
searchBar.setEditTextHint(ssb);
}
/**
* Sets the searchview's hint icon and text.
*
* @param searchView
* @param drawableResource
* @param hintText
*/
public static void setSearchHintIcon(SearchView searchView, int drawableResource, String hintText) {
try {
// Accessing the SearchAutoComplete
int queryTextViewId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
View autoComplete = searchView.findViewById(queryTextViewId);
//Class<?> clazz = Class.forName("android.widget.SearchView$SearchAutoComplete");
TextView searchBox = (TextView) searchView.findViewById(R.id.search_src_text);
SpannableStringBuilder stopHint = new SpannableStringBuilder(" ");
stopHint.append(hintText);
// Add the icon as an spannable
Drawable searchIcon = searchView.getContext().getResources().getDrawable(drawableResource);
Float rawTextSize = searchBox.getTextSize();
int textSize = (int) (rawTextSize * 1.25);
searchIcon.setBounds(0, 0, textSize, textSize);
stopHint.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Set the new hint text
searchBox.setHint(stopHint);
//searchBox.setTextColor(Color.WHITE);
searchBox.setHintTextColor(Color.LTGRAY);
} catch (Exception e) {
Log.e("SearchView", e.getMessage(), e);
}
}
public void doText(SubmissionViewHolder holder, Submission submission, Context mContext,
String baseSub, boolean full) {
SpannableStringBuilder t = SubmissionCache.getTitleLine(submission, mContext);
SpannableStringBuilder l = SubmissionCache.getInfoLine(submission, mContext, baseSub);
SpannableStringBuilder c = SubmissionCache.getCrosspostLine(submission, mContext);
int[] textSizeAttr = new int[]{R.attr.font_cardtitle, R.attr.font_cardinfo};
TypedArray a = mContext.obtainStyledAttributes(textSizeAttr);
int textSizeT = a.getDimensionPixelSize(0, 18);
int textSizeI = a.getDimensionPixelSize(1, 14);
t.setSpan(new AbsoluteSizeSpan(textSizeT), 0, t.length(), 0);
l.setSpan(new AbsoluteSizeSpan(textSizeI), 0, l.length(), 0);
SpannableStringBuilder s = new SpannableStringBuilder();
if (SettingValues.titleTop) {
s.append(t);
s.append("\n");
s.append(l);
} else {
s.append(l);
s.append("\n");
s.append(t);
}
if(!full && c != null){
c.setSpan(new AbsoluteSizeSpan(textSizeI), 0, c.length(), 0);
s.append("\n");
s.append(c);
}
a.recycle();
holder.title.setText(s);
}
private CharSequence getDecoratedHint(CharSequence hintText) {
// If the field is always expanded or we don't have a search hint icon,
// then don't add the search icon to the hint.
if (!mIconifiedByDefault || mSearchHintIcon == null) {
return hintText;
}
final int textSize = (int) (mSearchSrcTextView.getTextSize() * 1.25);
mSearchHintIcon.setBounds(0, 0, textSize, textSize);
final SpannableStringBuilder ssb = new SpannableStringBuilder(" ");
ssb.setSpan(new ImageSpan(mSearchHintIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(hintText);
return ssb;
}
private void updateSearchBar() {
Context context = getContext2();
if (null == context || null == mUrlBuilder || null == mSearchBar || null == mFavCatArray) {
return;
}
// Update title
int favCat = mUrlBuilder.getFavCat();
String favCatName;
if (favCat >= 0 && favCat < 10) {
favCatName = mFavCatArray[favCat];
} else if (favCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
favCatName = getString(R.string.local_favorites);
} else {
favCatName = getString(R.string.cloud_favorites);
}
String keyword = mUrlBuilder.getKeyword();
if (TextUtils.isEmpty(keyword)) {
if (!ObjectUtils.equal(favCatName, mOldFavCat)) {
mSearchBar.setTitle(getString(R.string.favorites_title, favCatName));
}
} else {
if (!ObjectUtils.equal(favCatName, mOldFavCat) || !ObjectUtils.equal(keyword, mOldKeyword)) {
mSearchBar.setTitle(getString(R.string.favorites_title_2, favCatName, keyword));
}
}
// Update hint
if (!ObjectUtils.equal(favCatName, mOldFavCat)) {
Drawable searchImage = DrawableManager.getVectorDrawable(context, R.drawable.v_magnify_x24);
SpannableStringBuilder ssb = new SpannableStringBuilder(" ");
ssb.append(getString(R.string.favorites_search_bar_hint, favCatName));
int textSize = (int) (mSearchBar.getEditTextTextSize() * 1.25);
if (searchImage != null) {
searchImage.setBounds(0, 0, textSize, textSize);
ssb.setSpan(new ImageSpan(searchImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mSearchBar.setEditTextHint(ssb);
}
mOldFavCat = favCatName;
mOldKeyword = keyword;
// Save recent fav cat
Settings.putRecentFavCat(mUrlBuilder.getFavCat());
}
@Override
public Notification buildNotification(Context context) {
Notification.Builder builder = buildBasicNotification(context);
Notification.BigTextStyle style = new Notification.BigTextStyle();
SpannableStringBuilder title = new SpannableStringBuilder();
appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
title.append(" title");
SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
text.append("; ");
appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
text.append("; ");
appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
text.append("; ");
appendStyled(text, "underline", new UnderlineSpan());
text.append("; ");
appendStyled(text, "strikethrough", new StrikethroughSpan());
text.append("; ");
appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
text.append("; ");
appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
text.append("; ");
appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
text.append("; ");
appendStyled(text, "monospace", new TypefaceSpan("monospace"));
text.append("; ");
appendStyled(text, "sub", new SubscriptSpan());
text.append("script");
appendStyled(text, "super", new SuperscriptSpan());
style.setBigContentTitle(title);
style.bigText(text);
builder.setStyle(style);
return builder.build();
}
public Cue build(@Cue.AnchorType int forcedPositionAnchor) {
SpannableStringBuilder cueString = new SpannableStringBuilder();
// Add any rolled up captions, separated by new lines.
for (int i = 0; i < rolledUpCaptions.size(); i++) {
cueString.append(rolledUpCaptions.get(i));
cueString.append('\n');
}
// Add the current line.
cueString.append(buildCurrentLine());
if (cueString.length() == 0) {
// The cue is empty.
return null;
}
int positionAnchor;
// The number of empty columns before the start of the text, in the range [0-31].
int startPadding = indent + tabOffset;
// The number of empty columns after the end of the text, in the same range.
int endPadding = SCREEN_CHARWIDTH - startPadding - cueString.length();
int startEndPaddingDelta = startPadding - endPadding;
if (forcedPositionAnchor != Cue.TYPE_UNSET) {
positionAnchor = forcedPositionAnchor;
} else if (captionMode == CC_MODE_POP_ON
&& (Math.abs(startEndPaddingDelta) < 3 || endPadding < 0)) {
// Treat approximately centered pop-on captions as middle aligned. We also treat captions
// that are wider than they should be in this way. See
// https://github.com/google/ExoPlayer/issues/3534.
positionAnchor = Cue.ANCHOR_TYPE_MIDDLE;
} else if (captionMode == CC_MODE_POP_ON && startEndPaddingDelta > 0) {
// Treat pop-on captions with less padding at the end than the start as end aligned.
positionAnchor = Cue.ANCHOR_TYPE_END;
} else {
// For all other cases assume start aligned.
positionAnchor = Cue.ANCHOR_TYPE_START;
}
float position;
switch (positionAnchor) {
case Cue.ANCHOR_TYPE_MIDDLE:
position = 0.5f;
break;
case Cue.ANCHOR_TYPE_END:
position = (float) (SCREEN_CHARWIDTH - endPadding) / SCREEN_CHARWIDTH;
// Adjust the position to fit within the safe area.
position = position * 0.8f + 0.1f;
break;
case Cue.ANCHOR_TYPE_START:
default:
position = (float) startPadding / SCREEN_CHARWIDTH;
// Adjust the position to fit within the safe area.
position = position * 0.8f + 0.1f;
break;
}
int lineAnchor;
int line;
// Note: Row indices are in the range [1-15].
if (captionMode == CC_MODE_ROLL_UP || row > (BASE_ROW / 2)) {
lineAnchor = Cue.ANCHOR_TYPE_END;
line = row - BASE_ROW;
// Two line adjustments. The first is because line indices from the bottom of the window
// start from -1 rather than 0. The second is a blank row to act as the safe area.
line -= 2;
} else {
lineAnchor = Cue.ANCHOR_TYPE_START;
// Line indices from the top of the window start from 0, but we want a blank row to act as
// the safe area. As a result no adjustment is necessary.
line = row;
}
return new Cue(
cueString,
Alignment.ALIGN_NORMAL,
line,
Cue.LINE_TYPE_NUMBER,
lineAnchor,
position,
positionAnchor,
Cue.DIMEN_UNSET);
}