preface

Android: Ellipsize =”marquee” has a text scroll effect, but pit, such as the focus changes will not move, and can not control the speed of the scroll, in the RecyclerView performance is a disaster level. To solve this problem, here’s MarqueeTextView: a custom View for text scrolling implemented by Kotlin. MarqueeTextView: Kotlin to achieve horizontal text scrolling, running through the lights effect. (gitee.com)

Relevant properties

XML attributes

attribute instructions
android:textSize Text size
android:textColor Text color
android:text The text content
marqueeRepeat Cycle mode:singe– Single execution;singleLoop– Monomial cycle;fillLoop– Fill cycle
marqueeItemDistance The distance between each item,marqueeRepeat=fillLoopeffective
marqueeStartLocationDistance The start position of the start is 0 to 1 percent from the left of the control
marqueeSpeed Text scroll speed
marqueeResetLocation When changing content again, whether to initialize the position, which defaults to true, changed

The main method

  • start: Start scrolling
  • stop: Stop rolling
  • toggle: Toggles the start/stop of scrolling

use

<com.xin.marquee.text.view.MarqueeTextView
    android:id="@+id/tv1"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    android:layout_marginBottom="16dp"
    android:text="Kotlin allows text to scroll horizontally and run around."
    android:textSize="14dp"
    app:marqueeRepeat="fillLoop"
    app:marqueeSpeed="5" />
Copy the code

The start method is called in the code

The specific implementation

Let the text scroll up is actually timed in a short period of time to the text, so that there will be a continuous scrolling feeling. The following only explains the core method to achieve the effect, source code from: MarqueeTextView: Kotlin to achieve text horizontal scrolling, running horselight effect. (gitee.com)

  1. Core classes:android.text.TextPaintandroid.os.handler
  2. Gets the width of the drawn text
private fun getTextWidth(text: String?).: Float {
    if (text.isNullOrEmpty()) {
        return 0f
    }
    return textPaint.measureText(text)
}
Copy the code
  1. Fill the text concatenation in circular mode
if (repeat == REPEAT_FILL_LOOP) {
    mFinalDrawText = ""
    // Calculate the width of the text
    mSingleContentWidth = getTextWidth(targetContent)
    if (mSingleContentWidth > 0) {
        // Maximum number of visible content items
        val maxVisibleCount = ceil(width / mSingleContentWidth.toDouble()).toInt() + 1
        repeat(maxVisibleCount) {
            mFinalDrawText += targetContent
        }
    }
    contentWidth = getTextWidth(mFinalDrawText)
} 
Copy the code
  1. Draw text content
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    // Ignore part of the code...
    // Draw the text
    if (mFinalDrawText.isNotBlank()) {
        canvas.drawText(mFinalDrawText, xLocation, height / 2 + textHeight / 2, textPaint)
    }
}
Copy the code
  1. Draw content regularly – roll
override fun handleMessage(msg: Message) {
    super.handleMessage(msg)
    if (msg.what == WHAT_RUN) {
        mRef.get()? .apply {if (speed > 0) {
                xLocation -= speed
                invalidate()
                // Draw once for 50 milliseconds
                sendEmptyMessageDelayed(WHAT_RUN, 50)}}}}Copy the code

conclusion

The whole implementation down on the whole is relatively simple, can meet the usual text scrolling (running horselight) effect needs. Code volume is very small, but also relatively clear, everyone should look at the source code is clear. There are unclear welcoming exchanges.