Android 文字跑马灯控件,支持设置滚动速度,文字颜色,大小等,可设置任意长度文本及任意控件宽度

275 篇文章 4 订阅
33 篇文章 1 订阅

因项目需求,需实现文字跑马灯效果,且能动态设置文本的滚动速度、字体颜色、字体大小等,Android自带的TextView也能实现跑马灯效果,但有个问题,文字内容长度必须大于控件宽度才会滚动,且滚动速度不可动态设置;

So,就参考了相关文档,自己实现了以上需求,使用方法与TextView差不多,在此以作记录,方便日后复习、优化。上代码:

package com.xxx.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by xRoon on 2016/2/27.
 */
public class MarqueeTextView extends View {
    private final float DEF_TEXT_SIZE = 25.0F;//The default text size
    private float mSpeed = 3.0F; //The default text scroll speed
    private boolean isScroll = true; //The default set as auto scroll
    private Context mContext;
    private Paint mPaint;
    private String mText;//This is to display the content
    private float mTextSize;//This is text size
    private int mTextColor; //This is text color

    private float mCoordinateX;//Draw the starting point of the X coordinate
    private float mCoordinateY;//Draw the starting point of the Y coordinate
    private float mTextWidth; //This is text width
    private int mViewWidth; //This is View width

    public MarqueeTextView(Context context) {
        super(context);
        init(context);

    }

    public MarqueeTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);

    }

    public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);

    }

    /**
     * Initializes the related parameters
     *
     * @param context
     */
    private void init(Context context) {
        this.mContext = context;

        if (TextUtils.isEmpty(mText)) {
            mText = "";
        }
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(DEF_TEXT_SIZE);
    }


    public void setText(String text) {
        mText = text;
        if (TextUtils.isEmpty(mText)) {
            mText = "";
        }
        requestLayout();
        invalidate();
    }

    /**
     * Set the text size, if this value is < 0, set to the default size
     *
     * @param textSize
     */
    public void setTextSize(float textSize) {
        this.mTextSize = textSize;
        mPaint.setTextSize(mTextSize <= 0 ? DEF_TEXT_SIZE : mTextSize);
        requestLayout();
        invalidate();
    }

    public void setTextColor(int textColor) {
        this.mTextColor = textColor;
        mPaint.setColor(mTextColor);
        invalidate();
    }

    /**
     * Set the text scrolling speed, if the value < 0, set to the default is 0
     *
     * @param speed If this value is 0, then stop scrolling
     */
    public void setTextSpeed(float speed) {
        this.mSpeed = speed < 0 ? 0 : speed;
        invalidate();
    }

    public float getTextSpeed() {
        return mSpeed;
    }

    public void setScroll(boolean isScroll) {
        this.isScroll = isScroll;
        invalidate();
    }

    public boolean isScroll() {
        return isScroll;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mTextWidth = mPaint.measureText(mText);
        mCoordinateX = getPaddingLeft();
        mCoordinateY = getPaddingTop() + Math.abs(mPaint.ascent());
        mViewWidth = measureWidth(widthMeasureSpec);
        int mViewHeight = measureHeight(heightMeasureSpec);

        //If you do not call this method, will be thrown "IllegalStateException"
        setMeasuredDimension(mViewWidth, mViewHeight);
    }


    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = (int) mPaint.measureText(mText) + getPaddingLeft()
                    + getPaddingRight();
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }

        return result;
    }

    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = (int) mPaint.getTextSize() + getPaddingTop()
                    + getPaddingBottom();
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawText(mText, mCoordinateX, mCoordinateY, mPaint);

        if (!isScroll) {
            return;
        }

        mCoordinateX -= mSpeed;

        if (Math.abs(mCoordinateX) > mTextWidth && mCoordinateX < 0) {
            mCoordinateX = mViewWidth;
        }

        invalidate();

    }

}
 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值