Android自定义可控制速度的跑马灯

Android自定义可控制速度的跑马灯_第1张图片

背景

原生的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
    }
}
  • 自定义属性
    
        
            
            
            
        
    

你可能感兴趣的:(Android自定义)