NightRain.png
背景
原生的TextView是支持跑馬燈效果的局劲,但是在項(xiàng)目中實(shí)際用了之后飘痛,達(dá)不到需求,原因是內(nèi)容滾動(dòng)太慢容握,速度無法調(diào)節(jié)宣脉。因此,需要自定義一個(gè)可以調(diào)節(jié)速度的跑馬燈剔氏。
思路
目前實(shí)現(xiàn)的思路是對(duì)文本內(nèi)容不斷地重繪塑猖,同時(shí)改變每次重繪的坐標(biāo),來在視覺上達(dá)到內(nèi)容在滾動(dòng)的效果谈跛。缺點(diǎn)是如果每次改變的坐標(biāo)差值太大羊苟,會(huì)有明顯的卡頓效果。經(jīng)過調(diào)試感憾,下面源碼中的速度感覺還可以接受蜡励,如果有特殊需求,自行在調(diào)試一下阻桅。
源碼
class CustomMarqueeView : AppCompatTextView {
companion object {
val SPEED_FAST = 9
val SPEED_MEDIUM = 6
val SPEED_SLOW = 3
}
//View寬度
private var mViewWidth = 0
private var mViewHeight = 0
private var mScrollX = 0F
private var mMarqueeMode = 3
private val rect = Rect()
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
includeFontPadding = false
initAttrs(context, attrs)
}
fun setScrollSpeed(speed: Int) {
if (speed == SPEED_FAST || speed == SPEED_MEDIUM || speed == SPEED_SLOW) {
mMarqueeMode = speed
}
}
override fun onDraw(canvas: Canvas?) {
val textContentText = text.toString().trim()
if (TextUtils.isEmpty(textContentText)) {
return
}
val x = mViewWidth - mScrollX
val y = mViewHeight / 2F + getTextContentHeight() / 2
canvas?.drawText(textContentText, x, y, paint)
mScrollX += mMarqueeMode
if (mScrollX >= (mViewWidth + getTextContentWdith())) {
mScrollX = 0F
}
invalidate()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
mViewWidth = MeasureSpec.getSize(widthMeasureSpec)
mViewHeight = MeasureSpec.getSize(heightMeasureSpec)
}
override fun setTextColor(color: Int) {
super.setTextColor(color)
paint.setColor(color)
}
private fun initAttrs(context: Context, attrs: AttributeSet?) {
val typeArray = context.obtainStyledAttributes(attrs, R.styleable.CustomMarqueeView)
mMarqueeMode =
typeArray.getInt(R.styleable.CustomMarqueeView_customScrollSpeed, mMarqueeMode)
typeArray.recycle()
}
/**
* 測量文字寬度
* @return 文字寬度
*/
private fun getTextContentWdith(): Int {
val textContent = text.toString().trim()
if (!TextUtils.isEmpty(textContent)) {
paint.getTextBounds(textContent, 0, textContent.length, rect)
return rect.width()
}
return 0
}
/**
* 測量文字高度
* @return 文字高度
*/
private fun getTextContentHeight(): Int {
val textContent = text.toString().trim()
if (!TextUtils.isEmpty(textContent)) {
paint.getTextBounds(textContent, 0, textContent.length, rect)
return rect.height()
}
return 0
}
}
- 自定義屬性
<declare-styleable name="CustomMarqueeView">
<attr name="customScrollSpeed">
<enum name="fast" value="9" />
<enum name="medium" value="6" />
<enum name="slow" value="3" />
</attr>
</declare-styleable>