Skip to content

Commit 298a495

Browse files
committed
修复无法在文本多行的情况下显示文本渐变色的问题
1 parent 6259a3e commit 298a495

File tree

9 files changed

+210
-101
lines changed

9 files changed

+210
-101
lines changed

app/src/main/java/com/hjq/shape/demo/MainActivity.java

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
import android.net.Uri;
55
import android.os.Bundle;
66
import android.support.v7.app.AppCompatActivity;
7-
import android.view.View;
87
import com.hjq.bar.OnTitleBarListener;
98
import com.hjq.bar.TitleBar;
9+
import com.hjq.shape.builder.TextColorBuilder;
1010
import com.hjq.shape.view.ShapeButton;
11+
import com.hjq.shape.view.ShapeTextView;
1112

1213
public class MainActivity extends AppCompatActivity {
1314

@@ -27,20 +28,62 @@ public void onTitleClick(TitleBar titleBar) {
2728
});
2829

2930
ShapeButton shapeButton = findViewById(R.id.btn_main_test);
30-
shapeButton.setOnClickListener(new View.OnClickListener() {
31-
@Override
32-
public void onClick(View v) {
31+
shapeButton.setOnClickListener(v -> {
32+
shapeButton.getShapeDrawableBuilder()
33+
.setSolidColor(0xFF000000)
34+
.setStrokeColor(0xFF5A8DDF)
35+
.intoBackground();
36+
37+
shapeButton.getTextColorBuilder()
38+
.setTextColor(0xFFFFFFFF)
39+
.intoTextColor();
40+
41+
shapeButton.setText("颜色已经改变啦");
42+
});
3343

34-
shapeButton.getShapeDrawableBuilder()
35-
.setSolidColor(0xFF000000)
36-
.setStrokeColor(0xFF5A8DDF)
37-
.intoBackground();
44+
ShapeTextView gradientHorizontalTextView = findViewById(R.id.tv_main_gradient_horizontal);
45+
gradientHorizontalTextView.setOnClickListener(v -> {
46+
TextColorBuilder textColorBuilder = gradientHorizontalTextView.getTextColorBuilder();
47+
if (textColorBuilder.isTextGradientColorsEnable()) {
48+
textColorBuilder.clearTextGradientColor();
49+
} else {
50+
textColorBuilder.setTextGradientColors(new int[] {0xFF49DAFA, 0xFFED58FF})
51+
.intoTextColor();
52+
}
53+
});
3854

39-
shapeButton.getTextColorBuilder()
40-
.setTextColor(0xFFFFFFFF)
41-
.intoTextColor();
55+
ShapeTextView gradientVerticalTextView = findViewById(R.id.tv_main_gradient_vertical);
56+
gradientVerticalTextView.setOnClickListener(v -> {
57+
TextColorBuilder textColorBuilder = gradientVerticalTextView.getTextColorBuilder();
58+
if (textColorBuilder.isTextGradientColorsEnable()) {
59+
textColorBuilder.clearTextGradientColor();
60+
} else {
61+
textColorBuilder.setTextGradientColors(new int[] {0xFF49DAFA, 0xFFED58FF})
62+
.intoTextColor();
63+
}
64+
});
65+
66+
ShapeTextView strokeTextView = findViewById(R.id.tv_main_stroke);
67+
strokeTextView.setOnClickListener(v -> {
68+
TextColorBuilder textColorBuilder = strokeTextView.getTextColorBuilder();
69+
if (textColorBuilder.isTextStrokeColorEnable()) {
70+
textColorBuilder.clearTextStrokeColor();
71+
} else {
72+
textColorBuilder.setTextStrokeColor(0xFF000000)
73+
.intoTextColor();
74+
}
75+
});
4276

43-
shapeButton.setText("颜色已经改变啦");
77+
ShapeTextView gradientAndStrokeTextView = findViewById(R.id.tv_main_gradient_and_stroke);
78+
gradientAndStrokeTextView.setOnClickListener(v -> {
79+
TextColorBuilder textColorBuilder = gradientAndStrokeTextView.getTextColorBuilder();
80+
if (textColorBuilder.isTextGradientColorsEnable() && textColorBuilder.isTextStrokeColorEnable()) {
81+
textColorBuilder.clearTextGradientColor();
82+
textColorBuilder.clearTextStrokeColor();
83+
} else {
84+
textColorBuilder.setTextGradientColors(new int[] {0xFF49DAFA, 0xFFED58FF})
85+
.setTextStrokeColor(0xFF000000)
86+
.intoTextColor();
4487
}
4588
});
4689
}

app/src/main/res/layout/activity_main.xml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,38 +367,53 @@
367367
android:textStyle="bold" />
368368

369369
<com.hjq.shape.view.ShapeTextView
370+
android:id="@+id/tv_main_gradient_horizontal"
370371
android:layout_width="wrap_content"
371372
android:layout_height="wrap_content"
372373
android:layout_margin="10dp"
373374
android:gravity="center"
374375
android:padding="10dp"
375-
android:text="文本水平渐变效果"
376+
android:text="文本水平渐变效果\n文本水平渐变效果\n单击可取消这种效果"
376377
android:textSize="18sp"
377378
app:shape_textEndColor="#ED58FF"
378379
app:shape_textGradientOrientation="horizontal"
379380
app:shape_textStartColor="#49DAFA" />
380381

381382
<com.hjq.shape.view.ShapeTextView
383+
android:id="@+id/tv_main_gradient_vertical"
382384
android:layout_width="wrap_content"
383385
android:layout_height="wrap_content"
384386
android:layout_margin="10dp"
385387
android:gravity="center"
386388
android:padding="10dp"
387-
android:text="文本垂直渐变效果ypgj"
389+
android:text="文本垂直渐变效果ypgj\n文本垂直渐变效果ypgj\n单击可取消这种效果"
388390
android:textSize="18sp"
389391
app:shape_textEndColor="#ED58FF"
390392
app:shape_textGradientOrientation="vertical"
391393
app:shape_textStartColor="#49DAFA" />
392394

393395
<com.hjq.shape.view.ShapeTextView
396+
android:id="@+id/tv_main_stroke"
394397
android:layout_width="wrap_content"
395398
android:layout_height="wrap_content"
396399
android:layout_margin="10dp"
397400
android:gravity="center"
398401
android:padding="10dp"
399-
android:text="文本边框颜色效果"
402+
android:text="文本边框颜色效果ypgj\n文本边框颜色效果ypgj\n单击可取消这种效果"
400403
android:textSize="18sp"
401404
app:shape_textColor="#5A8DDF"
405+
app:shape_textStrokeColor="#FF000000"
406+
app:shape_textStrokeSize="2sp" />
407+
408+
<com.hjq.shape.view.ShapeTextView
409+
android:id="@+id/tv_main_gradient_and_stroke"
410+
android:layout_width="wrap_content"
411+
android:layout_height="wrap_content"
412+
android:layout_margin="10dp"
413+
android:gravity="center"
414+
android:padding="10dp"
415+
android:text="文本边框色+渐变色效果ypgj\n文本边框色+渐变色效果ypgj\n单击可取消这种效果"
416+
android:textSize="18sp"
402417
app:shape_textEndColor="#f08833"
403418
app:shape_textGradientOrientation="horizontal"
404419
app:shape_textStartColor="#fefa54"

library/src/main/java/com/hjq/shape/builder/TextColorBuilder.java

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22

33
import android.content.res.ColorStateList;
44
import android.content.res.TypedArray;
5+
import android.graphics.Canvas;
56
import android.graphics.Color;
7+
import android.graphics.LinearGradient;
8+
import android.graphics.Paint;
9+
import android.graphics.Shader;
10+
import android.support.annotation.NonNull;
611
import android.support.annotation.Nullable;
712
import android.text.SpannableStringBuilder;
813
import android.text.Spanned;
14+
import android.widget.LinearLayout;
915
import android.widget.TextView;
16+
import android.widget.TextView.BufferType;
1017
import com.hjq.shape.config.ITextColorStyleable;
1118
import com.hjq.shape.config.ITextViewAttribute;
1219
import com.hjq.shape.other.TextViewAttribute;
1320
import com.hjq.shape.span.LinearGradientFontSpan;
14-
import com.hjq.shape.span.MultiFontSpan;
1521
import com.hjq.shape.span.StrokeFontSpan;
1622

1723
/**
@@ -22,6 +28,11 @@
2228
*/
2329
public final class TextColorBuilder {
2430

31+
/** 水平渐变方向 */
32+
public static final int GRADIENT_ORIENTATION_HORIZONTAL = LinearLayout.HORIZONTAL;
33+
/** 垂直渐变方向 */
34+
public static final int GRADIENT_ORIENTATION_VERTICAL = LinearLayout.VERTICAL;
35+
2536
private final TextView mTextView;
2637
private final ITextViewAttribute mTextViewAttribute;
2738

@@ -194,39 +205,37 @@ public boolean isTextStrokeColorEnable() {
194205
return mTextStrokeColor != Color.TRANSPARENT && mTextStrokeSize > 0;
195206
}
196207

197-
public void clearTextSpannable() {
198-
mTextStrokeColor = Color.TRANSPARENT;
199-
mTextStrokeSize = 0;
208+
/**
209+
* 清除文本渐变色
210+
*/
211+
public void clearTextGradientColor() {
200212
if (!isTextGradientColorsEnable()) {
201213
mTextView.setTextColor(mTextColor);
202214
}
203-
mTextView.setText(mTextView.getText().toString());
215+
mTextGradientColors = null;
216+
mTextView.postInvalidate();
217+
}
218+
219+
/**
220+
* 清除文本边框色
221+
*/
222+
public void clearTextStrokeColor() {
223+
mTextStrokeColor = Color.TRANSPARENT;
224+
mTextView.setText(mTextView.getText().toString(), BufferType.NORMAL);
204225
}
205226

206-
public SpannableStringBuilder buildTextSpannable(CharSequence text) {
227+
public SpannableStringBuilder buildStrokeFontSpannable(CharSequence text) {
207228
SpannableStringBuilder builder = new SpannableStringBuilder(text);
208229

209-
LinearGradientFontSpan linearGradientFontSpan = null;
210230
StrokeFontSpan strokeFontSpan = null;
211231

212-
if (isTextGradientColorsEnable()) {
213-
linearGradientFontSpan = new LinearGradientFontSpan(mTextViewAttribute)
214-
.setTextGradientColor(mTextGradientColors)
215-
.setTextGradientOrientation(mTextGradientOrientation)
216-
.setTextGradientPositions(null);
217-
}
218232
if (isTextStrokeColorEnable()) {
219233
strokeFontSpan = new StrokeFontSpan(mTextViewAttribute)
220234
.setTextStrokeColor(mTextStrokeColor)
221235
.setTextStrokeSize(mTextStrokeSize);
222236
}
223237

224-
if (linearGradientFontSpan != null && strokeFontSpan != null) {
225-
MultiFontSpan multiFontSpan = new MultiFontSpan(mTextViewAttribute, strokeFontSpan, linearGradientFontSpan);
226-
builder.setSpan(multiFontSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
227-
} else if (linearGradientFontSpan != null) {
228-
builder.setSpan(linearGradientFontSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
229-
} else if (strokeFontSpan != null) {
238+
if (strokeFontSpan != null) {
230239
strokeFontSpan.setTextSolidColor(mTextColor);
231240
builder.setSpan(strokeFontSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
232241
}
@@ -294,9 +303,41 @@ public ColorStateList buildColorState() {
294303
}
295304

296305
public void intoTextColor() {
306+
if (isTextGradientColorsEnable()) {
307+
// 如果 TextView 设置了不透明,那么就强制给它设置成不透明的
308+
mTextColor = mTextColor | 0xFF000000;
309+
}
310+
297311
mTextView.setTextColor(buildColorState());
298-
if (isTextGradientColorsEnable() || isTextStrokeColorEnable()) {
299-
mTextView.setText(buildTextSpannable(mTextView.getText()));
312+
313+
if (isTextStrokeColorEnable()) {
314+
mTextView.setText(buildStrokeFontSpannable(mTextView.getText().toString()), BufferType.SPANNABLE);
315+
}
316+
317+
mTextView.postInvalidate();
318+
}
319+
320+
public void onDraw(@NonNull Canvas canvas, Paint paint) {
321+
if (isTextGradientColorsEnable()) {
322+
LinearGradient linearGradient;
323+
if (mTextGradientOrientation == GRADIENT_ORIENTATION_VERTICAL) {
324+
linearGradient = new LinearGradient(
325+
mTextView.getPaddingLeft(), mTextView.getPaddingTop(), 0,
326+
(float) canvas.getHeight() - mTextView.getPaddingBottom(),
327+
mTextGradientColors, null, Shader.TileMode.CLAMP);
328+
} else {
329+
linearGradient = new LinearGradient(
330+
mTextView.getPaddingLeft(), mTextView.getPaddingTop(),
331+
(float) canvas.getWidth() - mTextView.getPaddingEnd(),
332+
(float) canvas.getHeight() - mTextView.getPaddingBottom(),
333+
mTextGradientColors, null, Shader.TileMode.CLAMP);
334+
}
335+
paint.setShader(linearGradient);
336+
} else {
337+
Shader shader = paint.getShader();
338+
if (shader instanceof LinearGradient) {
339+
paint.setShader(null);
340+
}
300341
}
301342
}
302343
}

library/src/main/java/com/hjq/shape/span/StrokeFontSpan.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public StrokeFontSpan(ITextViewAttribute textViewAttribute) {
5252
public void onDraw(@NonNull Canvas canvas, @NonNull Paint paint, CharSequence text, float textWidth,
5353
int start, int end, float x, int top, int y, int bottom) {
5454
mStrokePaint.set(paint);
55+
// 这里要把 Shader 清掉,避免把文本渐变色也带进来
56+
mStrokePaint.setShader(null);
5557
// 设置抗锯齿
5658
mStrokePaint.setAntiAlias(true);
5759
// 设置防抖动
@@ -66,7 +68,7 @@ public void onDraw(@NonNull Canvas canvas, @NonNull Paint paint, CharSequence te
6668
// 绘制文本描边
6769
canvas.drawText(text, start, end, x, y, mStrokePaint);
6870

69-
// 绘制文本内容
71+
// 绘制原文本内容
7072
if (mTextSolidColor != Color.TRANSPARENT) {
7173
paint.setColor(mTextSolidColor);
7274
canvas.drawText(text, start, end, x, y, paint);

library/src/main/java/com/hjq/shape/view/ShapeButton.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import android.content.Context;
44
import android.content.res.TypedArray;
5+
import android.graphics.Canvas;
56
import android.support.v7.widget.AppCompatButton;
67
import android.util.AttributeSet;
7-
88
import com.hjq.shape.R;
99
import com.hjq.shape.builder.ShapeDrawableBuilder;
1010
import com.hjq.shape.builder.TextColorBuilder;
@@ -43,12 +43,7 @@ public ShapeButton(Context context, AttributeSet attrs, int defStyleAttr) {
4343
typedArray.recycle();
4444

4545
mShapeDrawableBuilder.intoBackground();
46-
47-
if (mTextColorBuilder.isTextGradientColorsEnable() || mTextColorBuilder.isTextStrokeColorEnable()) {
48-
setText(getText());
49-
} else {
50-
mTextColorBuilder.intoTextColor();
51-
}
46+
mTextColorBuilder.intoTextColor();
5247
}
5348

5449
@Override
@@ -62,14 +57,21 @@ public void setTextColor(int color) {
6257

6358
@Override
6459
public void setText(CharSequence text, BufferType type) {
65-
if (mTextColorBuilder != null &&
66-
(mTextColorBuilder.isTextGradientColorsEnable() || mTextColorBuilder.isTextStrokeColorEnable())) {
67-
super.setText(mTextColorBuilder.buildTextSpannable(text), type);
60+
if (type != BufferType.SPANNABLE &&
61+
mTextColorBuilder != null &&
62+
mTextColorBuilder.isTextStrokeColorEnable()) {
63+
super.setText(mTextColorBuilder.buildStrokeFontSpannable(text), BufferType.SPANNABLE);
6864
} else {
6965
super.setText(text, type);
7066
}
7167
}
7268

69+
@Override
70+
protected void onDraw(Canvas canvas) {
71+
mTextColorBuilder.onDraw(canvas, getPaint());
72+
super.onDraw(canvas);
73+
}
74+
7375
@Override
7476
public ShapeDrawableBuilder getShapeDrawableBuilder() {
7577
return mShapeDrawableBuilder;

0 commit comments

Comments
 (0)