背景
原生的TextView是支持跑马灯效果的,但是在项目中实际用了之后,达不到需求,原因是内容滚动太慢,速度无法调节。因此,需要自定义一个可以调节速度的跑马灯。
思路
目前实现的思路是对文本内容不断地重绘,同时改变每次重绘的坐标,来在视觉上达到内容在滚动的效果。缺点是如果每次改变的坐标差值太大,会有明显的卡顿效果。经过调试,下面源码中的速度感觉还可以接受,如果有特殊需求,自行在调试一下。
源码(Kotlin)
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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。