1.效果展示和思路分析
画笔Paint的使用
- TextView可行?系统提供的只能够显示一种颜色,需要自定View
- 自定义View继承自谁
extends View:onMeasure() onDraw() extends TextView :onMeasure()不需要实现textColor颜色 textSize字体大小 会少很多逻辑
- 一个文字两种颜色 两个画笔画
- 能够从左到右,从右到左
- 整合到ViewPager
- 自定义属性:不变化的颜色 originColor 变化的颜色 changeColor
2.一个文字两种颜色
两个画笔画,用的是裁剪canvas.#clipRect()
3.实现不同朝向
左边是不变色右边是变色的,左边是不变色的右边是变色
4.自定义属性
<declare-styleable name="ColorTextTrackView">
<attr name="originColor" format="reference|color" />
<attr name="changeColor" format="reference|color" />
</declare-styleable>
5.自定义TextView
class ColorTextTrackView @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatTextView(context, attributeSet, defStyleAttr) {
private val originColor: Int
private val changeColor: Int
private val originPaint: Paint
private val changePaint: Paint
private var direction: Direction = Direction.LEFT_TO_RIGHT
/**
* 根据进度把中间值算出来
* */
private var currentProgress = 0.0F
/**
* 实现不同功效
* */
enum class Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
init {
context.obtainStyledAttributes(attributeSet, R.styleable.ColorTextTrackView).apply {
originColor = getColor(R.styleable.ColorTextTrackView_originColor, Color.BLACK)
changeColor = getColor(R.styleable.ColorTextTrackView_changeColor, Color.RED)
recycle()
}
originPaint = getPaintColor(originColor)
changePaint = getPaintColor(changeColor)
}
private fun getPaintColor(color: Int) = Paint().apply {
setColor(color)
//设置抗锯齿
isAntiAlias = true
//防抖动
isDither = true
this.textSize = this@ColorTextTrackView.textSize
}
private val zero = 0F
override fun onDraw(canvas: Canvas) {
val middle = currentProgress * width
if (direction == Direction.LEFT_TO_RIGHT) {
//绘制不变色:left到middle
canvas.drawText(originPaint, middle, width.toFloat())
//绘制变色:middle到getWidth()
canvas.drawText(changePaint, zero, middle)
} else {
//右边是红色,左边是黑色
canvas.drawText(originPaint, zero, width - middle)
canvas.drawText(changePaint, width - middle, width.toFloat())
}
}
private fun Canvas.drawText(paint: Paint, start: Float, end: Float) {
val content = text.toString().trim()
paint.getTextBounds(content, zero.toInt(), content.length, textRect)
val x = (width / 2 - textRect.width() / 2).toFloat()
val dy = with(paint.fontMetricsInt) {
(bottom - top) / 2 - bottom
}
val baseLine = (height / 2).toFloat() + dy
save()
clipRect(start, zero, end, height.toFloat())
drawText(content, x, baseLine, paint)
restore()
}
private val textRect by lazy { Rect() }
fun refreshDirection(direction: Direction) {
this.direction = direction
}
fun refreshCurrentProgress(progress: Float) {
this.currentProgress = progress
invalidate()
}
fun refreshOriginColor(originColor: Int) {
originPaint.color = originColor
}
fun refreshChangeColor(changeColor: Int) {
changePaint.color = changeColor
}
}
6.UI
class ViewPagerActivity : AppCompatActivity() {
private val itemArray by lazy { mutableListOf("直播", "推荐", "视频", "图片", "段子", "精华") }
private val fragmentArray by lazy {
with(mutableListOf<Fragment>()) {
itemArray.forEach {
add(ItemFragment.newInstance(it))
}
this
}
}
private val indicatorList = mutableListOf<ColorTextTrackView>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_pager)
val trackGroup = findViewById<LinearLayout>(R.id.track_group).apply {
//代码动态添加ColorTextTrackView
itemArray.forEach {
val view = ColorTextTrackView(this@ViewPagerActivity).let { v ->
val wrap = LayoutParams.WRAP_CONTENT
v.text = it
v.textSize = 20F
v.refreshChangeColor(Color.RED)
v.layoutParams = LayoutParams(wrap, wrap, 1F)
v
}
indicatorList.add(view)
addView(view)
}
}
val trackPager = findViewById<ViewPager2>(R.id.track_pager)
trackPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
/**
* positionOffset
* 从右往左滑,变大
* 从左往右滑,变小
* */
//1.左边,位置 position
val left = indicatorList[position].apply {
refreshDirection(ColorTextTrackView.Direction.RIGHT_TO_LEFT)
refreshCurrentProgress(1 - positionOffset)
}
if ((position) < indicatorList.size - 1) {
val right = indicatorList[position + 1].apply {
refreshDirection(ColorTextTrackView.Direction.LEFT_TO_RIGHT)
refreshCurrentProgress(positionOffset)
}
}
}
})
trackPager.adapter = object : FragmentStateAdapter(this) {
override fun getItemCount(): Int = fragmentArray.size
override fun createFragment(position: Int): Fragment = fragmentArray[position]
}
}
}