-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathEllipsisSpannedContainer.java
151 lines (125 loc) · 4.07 KB
/
EllipsisSpannedContainer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package android.text;
import android.text.style.ReplacementSpan;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* Fix Spanned Ellipsis bug.
*/
public class EllipsisSpannedContainer implements Spanned, GetChars{
public static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..."
private final Spanned mSourceSpanned;
private Layout mLayout;
private int mEllipsisStart = -1;
private int mEllipsisEnd = -1;
private ReplacementSpan mCustomEllipsisSpan;
public EllipsisSpannedContainer(Spanned spanned) {
mSourceSpanned = spanned;
}
public void setCustomEllipsisSpan(ReplacementSpan customEllipsisSpan) {
mCustomEllipsisSpan = customEllipsisSpan;
}
public int getEllipsisStart() {
return mEllipsisStart;
}
public int getEllipsisEnd() {
return mEllipsisEnd;
}
public Spanned getSourceSpanned() {
return mSourceSpanned;
}
@Override
public int getSpanEnd(Object tag) {
if (mCustomEllipsisSpan != null && mCustomEllipsisSpan == tag) {
return mEllipsisEnd;
}
return mSourceSpanned.getSpanEnd(tag);
}
@Override
public int getSpanFlags(Object tag) {
if (mCustomEllipsisSpan != null && mCustomEllipsisSpan == tag) {
return Spanned.SPAN_INCLUSIVE_EXCLUSIVE;
}
return mSourceSpanned.getSpanFlags(tag);
}
@Override
public int getSpanStart(Object tag) {
if (mCustomEllipsisSpan != null && mCustomEllipsisSpan == tag) {
return mEllipsisStart;
}
return mSourceSpanned.getSpanStart(tag);
}
@Override
public <T> T[] getSpans(int start, int end, Class<T> type) {
if (mEllipsisEnd >= end && mEllipsisStart <= end) {
T[] spans1 = mSourceSpanned.getSpans(start, Math.max(mEllipsisStart, start), type);
T[] spans2 = mSourceSpanned.getSpans(Math.min(end, mEllipsisEnd), end, type);
int offset = mCustomEllipsisSpan != null
&& (type.isAssignableFrom(ReplacementSpan.class) || type == mCustomEllipsisSpan.getClass()) ?
1 : 0;
int minLen = spans1.length + spans2.length + offset;
T[] spans = (T[]) Array.newInstance(type, minLen);
if (spans.length > minLen) {
spans = Arrays.copyOf(spans, minLen);
}
System.arraycopy(spans1, 0, spans, 0, spans1.length);
if (offset > 0) {
spans[spans1.length] = (T) mCustomEllipsisSpan;
}
System.arraycopy(spans2, 0, spans, spans1.length + offset, spans2.length);
return spans;
}
return mSourceSpanned.getSpans(start, end, type);
}
@Override
public int nextSpanTransition(int start, int limit, Class type) {
return mSourceSpanned.nextSpanTransition(start, limit, type);
}
@Override
public int length() {
return mSourceSpanned.length();
}
@Override
public char charAt(int index) {
return mSourceSpanned.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return mSourceSpanned.subSequence(start, end);
}
@Override
public void getChars(int start, int end, char[] dest, int destoff) {
TextUtils.getChars(mSourceSpanned, start, end, dest, destoff);
if (mLayout != null) {
int line1 = mLayout.getLineForOffset(start);
int line2 = mLayout.getLineForOffset(end);
for (int i = line1; i <= line2; i++) {
ellipsize(start, end, i, dest, destoff);
}
}
}
void ellipsize(int start, int end, int line, char[] dest, int destoff) {
int ellipsisCount = mLayout.getEllipsisCount(line);
if (ellipsisCount == 0) {
return;
}
int ellipsisStart = mLayout.getEllipsisStart(line);
int linestart = mLayout.getLineStart(line);
for (int i = ellipsisStart; i < ellipsisStart + ellipsisCount; i++) {
char c;
if (i == ellipsisStart) {
c = ELLIPSIS_NORMAL[0]; // ellipsis
mEllipsisStart = i + linestart;
mEllipsisEnd = mEllipsisStart + ellipsisCount;
} else {
c = '\uFEFF'; // 0-width space
}
int a = i + linestart;
if (a >= start && a < end) {
dest[destoff + a - start] = c;
}
}
}
public void setLayout(StaticLayout layout) {
mLayout = layout;
}
}