下面列出了android.text.SpannableStringBuilder#charAt ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void handleP(SpannableStringBuilder text) {
int len = text.length();
if (len >= 1 && text.charAt(len - 1) == '\n') {
if (len >= 2 && text.charAt(len - 2) == '\n') {
return;
}
text.append("\n");
return;
}
if (len != 0) {
text.append("\n\n");
}
}
private static void endHeader(SpannableStringBuilder text) {
int len = text.length();
Object obj = getLast(text, Header.class);
int where = text.getSpanStart(obj);
text.removeSpan(obj);
// Back off not to change only the text, not the blank line.
while (len > where && text.charAt(len - 1) == '\n') {
len--;
}
if (where != len) {
Header h = (Header) obj;
text.setSpan(new RelativeSizeSpan(HEADER_SIZES[h.mLevel]), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new StyleSpan(Typeface.BOLD), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
/**
* Utility method to append newlines while making sure that there are never
* more than 2 consecutive newlines in the text (if whitespace stripping was
* enabled).
*
* @param builder
* @return true if a newline was added
*/
protected boolean appendNewLine(SpannableStringBuilder builder) {
int len = builder.length();
if (this.spanner.isStripExtraWhiteSpace()) {
// Should never have more than 2 \n characters in a row.
if (len > 2 && builder.charAt(len - 1) == '\n'
&& builder.charAt(len - 2) == '\n') {
return false;
}
}
builder.append("\n");
return true;
}
public static CharSequence format(CharSequence seq, Object... args) {
int argI = 0;
SpannableStringBuilder builder = new SpannableStringBuilder(seq);
for (int i = 0; i < builder.length() - 1; i++) {
if (builder.charAt(i) == '%') {
int c = builder.charAt(++i);
CharSequence replacement = null;
switch (c) {
case 's':
replacement = (CharSequence) args[argI++];
break;
case '%':
replacement = "%";
break;
}
if (replacement != null) {
builder.replace(i - 1, i + 1, replacement);
i += replacement.length() - 2;
}
}
}
return builder;
}
private static void handleP(SpannableStringBuilder text) {
int len = text.length();
if (len >= 1 && text.charAt(len - 1) == '\n') {
if (len >= 2 && text.charAt(len - 2) == '\n') {
return;
}
text.append("\n");
return;
}
if (len != 0) {
text.append("\n\n");
}
}
private static CharSequence obtainThreadComment(String comment, String chanName, ChanMarkup.MarkupExtra extra) {
SpannableStringBuilder commentBuilder = new SpannableStringBuilder(obtainComment(comment,
chanName, null, extra));
int linebreaks = 0;
// Remove more than one linebreaks in sequence
for (int i = commentBuilder.length() - 1; i >= 0; i--) {
char c = commentBuilder.charAt(i);
if (c == '\n') {
linebreaks++;
} else {
if (linebreaks > 1) {
// Remove linebreaks - 1 characters, keeping one line break
commentBuilder.delete(i + 1, i + linebreaks);
}
linebreaks = 0;
}
}
return commentBuilder;
}
private void replaceSpannable(SpannableStringBuilder spannable, char what, String with) {
for (int i = 0; i < spannable.length(); i++) {
if (spannable.charAt(i) == what) {
spannable.replace(i, i + 1, with);
}
}
}
/**
* Called when the end of a paragraph is encountered. Adds a newline if there are one or more
* non-space characters since the previous newline.
*
* @param builder The builder.
*/
/* package */ static void endParagraph(SpannableStringBuilder builder) {
int position = builder.length() - 1;
while (position >= 0 && builder.charAt(position) == ' ') {
position--;
}
if (position >= 0 && builder.charAt(position) != '\n') {
builder.append('\n');
}
}
/**
* Strips quotation marks from the {@code formatString} and appends the result back to the
* {@code formatString}.
*
* @param formatString the format string, as described in
* {@link android.text.format.DateFormat}, to be modified
* @param index index of the first quote
* @return the length of the quoted text that was appended.
* @hide
*/
public static int appendQuotedText(SpannableStringBuilder formatString, int index) {
int length = formatString.length();
if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) {
formatString.delete(index, index + 1);
return 1;
}
int count = 0;
// delete leading quote
formatString.delete(index, index + 1);
length--;
while (index < length) {
char c = formatString.charAt(index);
if (c == QUOTE) {
// QUOTEQUOTE -> QUOTE
if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) {
formatString.delete(index, index + 1);
length--;
count++;
index++;
} else {
// Closing QUOTE ends quoted text copying
formatString.delete(index, index + 1);
break;
}
} else {
index++;
count++;
}
}
return count;
}
/**
* Called when the end of a paragraph is encountered. Adds a newline if there are one or more
* non-space characters since the previous newline.
*
* @param builder The builder.
*/
/* package */ static void endParagraph(SpannableStringBuilder builder) {
int position = builder.length() - 1;
while (position >= 0 && builder.charAt(position) == ' ') {
position--;
}
if (position >= 0 && builder.charAt(position) != '\n') {
builder.append('\n');
}
}
private void addNewLine(SpannableStringBuilder text) {
final int len = text.length();
if (len >= 1 && text.charAt(len - 1) == '\n') {
return;
}
if (len != 0) {
text.append("\n");
}
}
@Override
public void beforeChildren(TagNode node, SpannableStringBuilder builder, SpanStack spanStack) {
Style useStyle = spanStack.getStyle( node, getStyle() );
if (builder.length() > 0 && useStyle.getDisplayStyle() == Style.DisplayStyle.BLOCK ) {
if ( builder.charAt(builder.length() -1) != '\n' ) {
builder.append('\n');
}
}
//If we have a top margin, we insert an extra newline. We'll manipulate the line height
//of this newline to create the margin.
if ( useStyle.getMarginTop() != null ) {
StyleValue styleValue = useStyle.getMarginTop();
if ( styleValue.getUnit() == StyleValue.Unit.PX ) {
if ( styleValue.getIntValue() > 0 ) {
if ( appendNewLine(builder) ) {
spanStack.pushSpan( new VerticalMarginSpan( styleValue.getIntValue() ),
builder.length() -1, builder.length() );
}
}
} else {
if ( styleValue.getFloatValue() > 0f ) {
if ( appendNewLine(builder) ) {
spanStack.pushSpan( new VerticalMarginSpan( styleValue.getFloatValue() ),
builder.length() -1, builder.length() );
}
}
}
}
}
private static void addBulletsToText(SpannableStringBuilder builder, char bulletChar, int gapWidth, int color, int radius) {
for (int i = 0, until = builder.length() - 2; i < until; i++) {
if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == bulletChar && builder.charAt(i + 2) == ' ') {
final BulletSpan span = new BulletSpan(gapWidth, color, radius);
builder.replace(i + 1, i + 3, "\0\0");
builder.setSpan(span, i + 1, i + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
/**
* Called when the end of a paragraph is encountered. Adds a newline if there are one or more
* non-space characters since the previous newline.
*
* @param builder The builder.
*/
/* package */ static void endParagraph(SpannableStringBuilder builder) {
int position = builder.length() - 1;
while (position >= 0 && builder.charAt(position) == ' ') {
position--;
}
if (position >= 0 && builder.charAt(position) != '\n') {
builder.append('\n');
}
}
/**
* Called when the end of a paragraph is encountered. Adds a newline if there are one or more
* non-space characters since the previous newline.
*
* @param builder The builder.
*/
/* package */ static void endParagraph(SpannableStringBuilder builder) {
int position = builder.length() - 1;
while (position >= 0 && builder.charAt(position) == ' ') {
position--;
}
if (position >= 0 && builder.charAt(position) != '\n') {
builder.append('\n');
}
}
private SpannableStringBuilder cleanUpText(SpannableStringBuilder builder) {
// Having joined the text elements, we need to do some final cleanup on the result.
// 1. Collapse multiple consecutive spaces into a single space.
int builderLength = builder.length();
for (int i = 0; i < builderLength; i++) {
if (builder.charAt(i) == ' ') {
int j = i + 1;
while (j < builder.length() && builder.charAt(j) == ' ') {
j++;
}
int spacesToDelete = j - (i + 1);
if (spacesToDelete > 0) {
builder.delete(i, i + spacesToDelete);
builderLength -= spacesToDelete;
}
}
}
// 2. Remove any spaces from the start of each line.
if (builderLength > 0 && builder.charAt(0) == ' ') {
builder.delete(0, 1);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == ' ') {
builder.delete(i + 1, i + 2);
builderLength--;
}
}
// 3. Remove any spaces from the end of each line.
if (builderLength > 0 && builder.charAt(builderLength - 1) == ' ') {
builder.delete(builderLength - 1, builderLength);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == ' ' && builder.charAt(i + 1) == '\n') {
builder.delete(i, i + 1);
builderLength--;
}
}
// 4. Trim a trailing newline, if there is one.
if (builderLength > 0 && builder.charAt(builderLength - 1) == '\n') {
builder.delete(builderLength - 1, builderLength);
/*builderLength--;*/
}
return builder;
}
private SpannableStringBuilder cleanUpText(SpannableStringBuilder builder) {
// Having joined the text elements, we need to do some final cleanup on the result.
// 1. Collapse multiple consecutive spaces into a single space.
int builderLength = builder.length();
for (int i = 0; i < builderLength; i++) {
if (builder.charAt(i) == ' ') {
int j = i + 1;
while (j < builder.length() && builder.charAt(j) == ' ') {
j++;
}
int spacesToDelete = j - (i + 1);
if (spacesToDelete > 0) {
builder.delete(i, i + spacesToDelete);
builderLength -= spacesToDelete;
}
}
}
// 2. Remove any spaces from the start of each line.
if (builderLength > 0 && builder.charAt(0) == ' ') {
builder.delete(0, 1);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == ' ') {
builder.delete(i + 1, i + 2);
builderLength--;
}
}
// 3. Remove any spaces from the end of each line.
if (builderLength > 0 && builder.charAt(builderLength - 1) == ' ') {
builder.delete(builderLength - 1, builderLength);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == ' ' && builder.charAt(i + 1) == '\n') {
builder.delete(i, i + 1);
builderLength--;
}
}
// 4. Trim a trailing newline, if there is one.
if (builderLength > 0 && builder.charAt(builderLength - 1) == '\n') {
builder.delete(builderLength - 1, builderLength);
/*builderLength--;*/
}
return builder;
}
private SpannableStringBuilder cleanUpText(SpannableStringBuilder builder) {
// Having joined the text elements, we need to do some final cleanup on the result.
// 1. Collapse multiple consecutive spaces into a single space.
int builderLength = builder.length();
for (int i = 0; i < builderLength; i++) {
if (builder.charAt(i) == ' ') {
int j = i + 1;
while (j < builder.length() && builder.charAt(j) == ' ') {
j++;
}
int spacesToDelete = j - (i + 1);
if (spacesToDelete > 0) {
builder.delete(i, i + spacesToDelete);
builderLength -= spacesToDelete;
}
}
}
// 2. Remove any spaces from the start of each line.
if (builderLength > 0 && builder.charAt(0) == ' ') {
builder.delete(0, 1);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == ' ') {
builder.delete(i + 1, i + 2);
builderLength--;
}
}
// 3. Remove any spaces from the end of each line.
if (builderLength > 0 && builder.charAt(builderLength - 1) == ' ') {
builder.delete(builderLength - 1, builderLength);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == ' ' && builder.charAt(i + 1) == '\n') {
builder.delete(i, i + 1);
builderLength--;
}
}
// 4. Trim a trailing newline, if there is one.
if (builderLength > 0 && builder.charAt(builderLength - 1) == '\n') {
builder.delete(builderLength - 1, builderLength);
/*builderLength--;*/
}
return builder;
}
private SpannableStringBuilder cleanUpText(SpannableStringBuilder builder) {
// Having joined the text elements, we need to do some final cleanup on the result.
// 1. Collapse multiple consecutive spaces into a single space.
int builderLength = builder.length();
for (int i = 0; i < builderLength; i++) {
if (builder.charAt(i) == ' ') {
int j = i + 1;
while (j < builder.length() && builder.charAt(j) == ' ') {
j++;
}
int spacesToDelete = j - (i + 1);
if (spacesToDelete > 0) {
builder.delete(i, i + spacesToDelete);
builderLength -= spacesToDelete;
}
}
}
// 2. Remove any spaces from the start of each line.
if (builderLength > 0 && builder.charAt(0) == ' ') {
builder.delete(0, 1);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == '\n' && builder.charAt(i + 1) == ' ') {
builder.delete(i + 1, i + 2);
builderLength--;
}
}
// 3. Remove any spaces from the end of each line.
if (builderLength > 0 && builder.charAt(builderLength - 1) == ' ') {
builder.delete(builderLength - 1, builderLength);
builderLength--;
}
for (int i = 0; i < builderLength - 1; i++) {
if (builder.charAt(i) == ' ' && builder.charAt(i + 1) == '\n') {
builder.delete(i, i + 1);
builderLength--;
}
}
// 4. Trim a trailing newline, if there is one.
if (builderLength > 0 && builder.charAt(builderLength - 1) == '\n') {
builder.delete(builderLength - 1, builderLength);
/*builderLength--;*/
}
return builder;
}
/**
* Applies QuoteSpan to group of lines which starts with > or » characters.
* Appends likebreaks and applies DividerSpan to them to show a padding between quote and text.
*/
private boolean handleTextQuotes(SpannableStringBuilder body, boolean darkBackground) {
boolean startsWithQuote = false;
char previous = '\n';
int lineStart = -1;
int lineTextStart = -1;
int quoteStart = -1;
for (int i = 0; i <= body.length(); i++) {
char current = body.length() > i ? body.charAt(i) : '\n';
if (lineStart == -1) {
if (previous == '\n') {
if ((current == '>' && UIHelper.isPositionFollowedByQuoteableCharacter(body, i))
|| current == '\u00bb' && !UIHelper.isPositionFollowedByQuote(body, i)) {
// Line start with quote
lineStart = i;
if (quoteStart == -1) quoteStart = i;
if (i == 0) startsWithQuote = true;
} else if (quoteStart >= 0) {
// Line start without quote, apply spans there
applyQuoteSpan(body, quoteStart, i - 1, darkBackground);
quoteStart = -1;
}
}
} else {
// Remove extra spaces between > and first character in the line
// > character will be removed too
if (current != ' ' && lineTextStart == -1) {
lineTextStart = i;
}
if (current == '\n') {
body.delete(lineStart, lineTextStart);
i -= lineTextStart - lineStart;
if (i == lineStart) {
// Avoid empty lines because span over empty line can be hidden
body.insert(i++, " ");
}
lineStart = -1;
lineTextStart = -1;
}
}
previous = current;
}
if (quoteStart >= 0) {
// Apply spans to finishing open quote
applyQuoteSpan(body, quoteStart, body.length(), darkBackground);
}
return startsWithQuote;
}