Skip to content

Commit

Permalink
1,新增支持渐变色字体
Browse files Browse the repository at this point in the history
  • Loading branch information
FlyJingFish committed May 11, 2023
1 parent 5e668e4 commit 9ea08ff
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class FormatText : BaseFormat() {
@JvmField
var ignorePaintShader = true

@JvmField
var gradient: Gradient? = null


fun setTextColor(@ColorRes color: Int): FormatText {
this.textColor = color
Expand Down Expand Up @@ -128,4 +131,9 @@ class FormatText : BaseFormat() {
return this
}

fun setIgnorePaintShader(gradient: Gradient): FormatText {
this.gradient = gradient
return this
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.flyjingfish.formattextview

import android.content.Context
import android.graphics.*
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.Shader
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import android.graphics.drawable.LevelListDrawable
Expand All @@ -16,7 +23,7 @@ import android.util.LayoutDirection
import android.view.View
import androidx.annotation.StringRes
import androidx.core.text.TextUtilsCompat
import java.util.*
import java.util.Locale


class FormatTextView : BaseTextView {
Expand All @@ -25,8 +32,13 @@ class FormatTextView : BaseTextView {
private var onInflateImageListener: OnInflateImageListener? = null
private var isClickSpanItem = false
var isSetOnClick = false
private var isDrawGradient = false
private val underLineTexts: ArrayList<LineText> = ArrayList()
private val deleteLineTexts: ArrayList<LineText> = ArrayList()
private val gradientTexts: ArrayList<LineText> = ArrayList()
private val gradientDrawTexts: ArrayList<GradientText> = ArrayList()
private var formatArgs: Array<out BaseFormat?>? = null
private var richText: String ?= null

constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
Expand All @@ -45,6 +57,7 @@ class FormatTextView : BaseTextView {
textValue = textValue.replace("\\n".toRegex(), "<br>")
textValue = textValue.replace("\\r".toRegex(), "<br>")
val strings = arrayOfNulls<String>(args.size)
var isContainGradient = false
for (i in args.indices) { //%1$s
val start = "<a href=\"$i\">"
val end = "</a>"
Expand All @@ -64,17 +77,29 @@ class FormatTextView : BaseTextView {
value1 = value1?.replace("\\n".toRegex(), "<br>")
value1 = value1?.replace("\\r".toRegex(), "<br>")
strings[i] = start + value1 + end
if (formatText.gradient != null){
isContainGradient = true
}
}


}
val richText = String.format(textValue, *strings)

formatArgs = args
this.richText = richText
isDrawGradient = !isContainGradient
underLineTexts.clear()
deleteLineTexts.clear()
gradientTexts.clear()
gradientDrawTexts.clear()
text = getCustomStyleHtml(richText, *args)
highlightColor = Color.TRANSPARENT
autoLinkMask = Linkify.WEB_URLS
}

private fun resetText(){
text = richText?.let { formatArgs?.let { it1 -> getCustomStyleHtml(it, *it1) } }
}

fun setFormatText(@StringRes formatTextRes: Int, vararg args: Int) {
setFormatText(resources.getString(formatTextRes), *args)
Expand Down Expand Up @@ -299,11 +324,83 @@ class FormatTextView : BaseTextView {
userDefaultDelete = false

}
//gradient
if (!isDrawGradient && formatText.gradient != null) {
val textPaint = TextPaint()
textPaint.textSize = if (textSize > 0) sp2px(context, textSize) else getTextSize()
val fm = textPaint.fontMetrics

val gradientText = LineText(
start,
end,
0,
(fm.descent - fm.ascent) / 2 - fm.descent,
0f
)
gradientTexts.add(gradientText)

}

if (isDrawGradient && gradientDrawTexts.size > 0){
for (gradientDrawText in gradientDrawTexts) {
if (gradientDrawText.start>=start && gradientDrawText.end <= end){

val clickableSpan: GradientSpan = object : GradientSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
var left=0f
var top=0f
var right=0f
var bottom=0f
var orientation = formatText.gradient?.orientation
if (orientation == null){
orientation = Gradient.Orientation.LEFT_TO_RIGHT
}
when (orientation) {
Gradient.Orientation.LEFT_TO_RIGHT -> {
left = gradientDrawText.rectF.left
top = gradientDrawText.rectF.top
right = gradientDrawText.rectF.right
bottom = gradientDrawText.rectF.top
}
Gradient.Orientation.TOP_TO_BOTTOM -> {
left = gradientDrawText.rectF.left
top = gradientDrawText.rectF.top
right = gradientDrawText.rectF.left
bottom = gradientDrawText.rectF.bottom
}
Gradient.Orientation.LEFT_TOP_TO_RIGHT_BOTTOM -> {
left = gradientDrawText.rectF.left
top = gradientDrawText.rectF.top
right = gradientDrawText.rectF.right
bottom = gradientDrawText.rectF.bottom
}
Gradient.Orientation.LEFT_BOTTOM_TO_RIGHT_TOP -> {
left = gradientDrawText.rectF.left
top = gradientDrawText.rectF.bottom
right = gradientDrawText.rectF.right
bottom = gradientDrawText.rectF.top
}
}
val mLinearGradient = formatText.gradient?.gradientColors?.let {
LinearGradient(
left, top, right, bottom,
it, formatText.gradient?.gradientPositions,
Shader.TileMode.CLAMP
)
}
ds.shader = mLinearGradient
}
}
htmlBuilder.setSpan(clickableSpan, gradientDrawText.start, gradientDrawText.end, flags)
}
}
}

val clickableSpan: ClickableSpan = object : FormatClickableSpan(urlSpan) {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
if(formatText.ignorePaintShader){
if(formatText.ignorePaintShader && formatText.gradient == null){
ds.shader = null
}
//设置颜色
Expand Down Expand Up @@ -361,6 +458,13 @@ class FormatTextView : BaseTextView {
}
}

abstract class GradientSpan : CharacterStyle(), UpdateAppearance {
override fun updateDrawState(ds: TextPaint) {
ds.color = ds.linkColor
ds.isUnderlineText = false
}
}

override fun setOnClickListener(l: OnClickListener?) {
// 为了处理ClickableSpan和View.OnClickListener点击事件冲突
super.setOnClickListener {
Expand All @@ -382,8 +486,46 @@ class FormatTextView : BaseTextView {
super.onDraw(canvas)
drawUnderline(canvas)
drawDeleteLine(canvas)
getGradient()
}
private fun getGradient() {
if (gradientTexts.size == 0 || isDrawGradient) {
return
}
//绘制下划线
for (lineText in gradientTexts) {
val map = HashMap<Int,GradientText>()
for (i in lineText.start until lineText.end) {
val line = layout.getLineForOffset(i)
val bound = getUnderLineBound(i)
val left = bound.left.toFloat()
val top = bound.bottom.toFloat() - lineText.lineTop*2
val right = bound.right.toFloat()
val bottom = bound.bottom.toFloat()
val rect = RectF(left,top,right, bottom)
if (!map.containsKey(line)){
val gradientText = GradientText(rect,i,i+1)
map[line] = gradientText
}else{
val gradientText = map[line]
val oldRect = gradientText!!.rectF
if (oldRect.left < rect.left){
oldRect.right = right
}else{
oldRect.left = left
}
gradientText.end = i+1
}
}

for ((_,value) in map){
gradientDrawTexts.add(value)
}

}
isDrawGradient = true
resetText()
}
private fun drawUnderline(canvas: Canvas?) {
if (underLineTexts.size == 0) {
return
Expand Down Expand Up @@ -476,6 +618,12 @@ class FormatTextView : BaseTextView {
var lineWidth: Float
)

private class GradientText(
var rectF: RectF,
var start: Int,
var end: Int,
)

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (underLineTexts.size > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.flyjingfish.formattextview

class Gradient(
var gradientColors: IntArray,
var gradientPositions: FloatArray?,
var orientation: Orientation?
) {
enum class Orientation{
LEFT_TO_RIGHT,
TOP_TO_BOTTOM,
LEFT_TOP_TO_RIGHT_BOTTOM,
LEFT_BOTTOM_TO_RIGHT_TOP
}
}
36 changes: 19 additions & 17 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

```gradle
dependencies {
implementation 'com.github.FlyJingFish:FormatTextViewLib:2.2.3'
implementation 'com.github.FlyJingFish:FormatTextViewLib:2.2.4'
}
```
## 第三步,使用说明
Expand Down Expand Up @@ -204,22 +204,24 @@ textView.setFormatTextBean("%1$s欢迎欢迎欢迎欢迎欢迎欢迎欢迎%3$s
ALIGN_CENTER 为当前库新增对齐方式旨解决在小图标和文本中心对齐问题,在图片设置超过行高时将会出现裁剪问题,如果您图片很大还是建议使用ALIGN_BASELINE

## FormatText 参数一览
| 属性 | 参数类型 | 描述 |
|--------------------|:--------------:|:-------------:|
| textColor | @ColorRes int | 文字资源颜色Id |
| bold | boolean | 文字是否加粗 |
| italic | boolean | 文字是否斜体 |
| strValue | String | 文字String类型值 |
| resValue | @StringRes int | 文字文本资源Id |
| textSize | float | 文字字体大小(单位:SP) |
| underline | boolean | 文字是否下划线 |
| underlineColor | @ColorRes int | 文字下划线颜色 |
| underlineWidth | float | 文字下划线线宽 |
| underlineMarginTop | float | 文字下划线向下偏移的距离 |
| deleteLine | boolean | 文字是否删除线 |
| deleteLineColor | @ColorRes int | 文字删除线颜色 |
| deleteLineWidth | float | 文字删除线线宽 |
| backgroundColor | @ColorRes int | 文字区域背景色 |
| 属性 | 参数类型 | 描述 |
|--------------------|:--------------:|:---------------------:|
| textColor | @ColorRes int | 文字资源颜色Id |
| bold | boolean | 文字是否加粗 |
| italic | boolean | 文字是否斜体 |
| strValue | String | 文字String类型值 |
| resValue | @StringRes int | 文字文本资源Id |
| textSize | float | 文字字体大小(单位:SP) |
| underline | boolean | 文字是否下划线 |
| underlineColor | @ColorRes int | 文字下划线颜色 |
| underlineWidth | float | 文字下划线线宽 |
| underlineMarginTop | float | 文字下划线向下偏移的距离 |
| deleteLine | boolean | 文字是否删除线 |
| deleteLineColor | @ColorRes int | 文字删除线颜色 |
| deleteLineWidth | float | 文字删除线线宽 |
| backgroundColor | @ColorRes int | 文字区域背景色 |
| ignorePaintShader | boolean | 文字是否忽略TextView的Shader |
| gradient | Gradient | 文字渐变色配置 |

## FormatImage 参数一览
| 属性 | 参数类型 | 描述 |
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

```gradle
dependencies {
implementation 'com.github.FlyJingFish:FormatTextViewLib:2.2.3'
implementation 'com.github.FlyJingFish:FormatTextViewLib:2.2.4'
}
````
## The third step, instructions for use
Expand Down Expand Up @@ -222,6 +222,8 @@ ALIGN_CENTER adds an alignment method to the current library to solve the alignm
| deleteLineColor | @ColorRes int | Text strikethrough color |
| deleteLineWidth | float | Text strikethrough line width |
| backgroundColor | @ColorRes int | Text area background color |
| ignorePaintShader | boolean | Whether the text ignores the Shader of the TextView |
| gradient | Gradient | Text Gradient Color Configuration |

## FormatImage parameter list
| property | parameter type | description |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flyjingfish.formattextviewdemo

import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.drawable.Drawable
Expand Down Expand Up @@ -30,6 +31,7 @@ class DemoActivity : AppCompatActivity() {
underlineMarginTop = 6f
underlineWidth = 2f
resValue = R.string.User_Agreement
gradient = Gradient(intArrayOf(Color.GREEN,Color.RED),null,Gradient.Orientation.LEFT_TO_RIGHT)
},
FormatText().apply {
textSize = 22f
Expand All @@ -41,6 +43,7 @@ class DemoActivity : AppCompatActivity() {
underlineMarginTop = 6f
underlineWidth = 2f
resValue = R.string.Privacy_Policy
gradient = Gradient(intArrayOf(Color.BLUE,Color.RED),null,Gradient.Orientation.LEFT_BOTTOM_TO_RIGHT_TOP)
}
)
text1.setOnFormatClickListener(object :OnFormatClickListener{
Expand Down Expand Up @@ -104,6 +107,7 @@ class DemoActivity : AppCompatActivity() {
underlineMarginTop = 10f
underlineWidth = 3f
ignorePaintShader = false
gradient = Gradient(intArrayOf(Color.BLUE,Color.RED),null,Gradient.Orientation.LEFT_BOTTOM_TO_RIGHT_TOP)
},
FormatText().apply {
textSize = 30f
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
android:text="Hello World!" />


<com.flyjingfish.formattextview.FormatTextView
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
Expand Down

0 comments on commit 9ea08ff

Please sign in to comment.