`
jingbin4679
  • 浏览: 2173 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类

Android自定义TextView实现跑马灯效果

阅读更多
1、机顶盒应用中经常用到跑马灯效果,而自己绘制跑马灯效果的关键在于步长和刷新频率的控制,一般情况下,刷新频率不要大于16ms,因为16ms是保证不掉帧的关键时间点,所以就不会出现卡顿的现象,具体实现代码如下:

package com.example.marquee;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

public class CustomTextView extends View {
    /**
     * 界面刷新时间(ms)
     */
    public static final int INVALIDATE_TIME = 15;
    /**
     * 每次移动的像素点(px)
     */
    public static final int INVALIDATE_STEP = 4;
    /**
     * 一次移动完成后等待的时间(ms)
     */
    public static final int WAIT_TIME = 1500;
    /**
     * 滚动文字前后的间隔
     */
    private String space = "              ";
    private String drawingText = "";
    private TextPaint paint;
    public boolean exitFlag;
    private float textWidth;
    private String _mText;
    private int posX = 0;
    private float posY;
    private int width;
    private RectF rf;

    private Handler mHandler = new Handler();

    public CustomTextView(Context context) {
        this(context, null);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    private void initView() {
        paint = new TextPaint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        paint.setTextSize(30F);
        rf = new RectF(0, 0, 0, 0);
    }

    public void setText(String text) {
        this._mText = text;
        this.drawingText = _mText;
        layoutView();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
        layoutView();
    }

    private void layoutView() {
        width = getWidth();
        rf.right = width;
        rf.bottom = getHeight();
        textWidth = paint.measureText(_mText, 0, _mText.length());
        posY = getTextDrawingBaseline(paint, rf);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getVisibility() != View.VISIBLE || TextUtils.isEmpty(drawingText)) {
            return;
        }
        canvas.save();
        canvas.drawText(drawingText, 0, drawingText.length(), posX, posY, paint);
        canvas.restore();
    }

    private Runnable moveRun = new Runnable() {

        @Override
        public void run() {
            if(width >= textWidth){
                return;
            }
            drawingText = _mText + space + _mText;
            posX -= INVALIDATE_STEP;
            if(posX >= -1 * INVALIDATE_STEP / 2 && posX <= INVALIDATE_STEP / 2){
                mHandler.postDelayed(this, WAIT_TIME);
                invalidate();
                return;
            }
            if (posX < -1 * textWidth - paint.measureText(space, 0, space.length())) {
                posX = INVALIDATE_STEP;
            }
            invalidate();
            if(!exitFlag){
                mHandler.postDelayed(this, INVALIDATE_TIME);
                return;
            }
            posX = 0;
        }
    };

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopMove();
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        layoutView();
        startMove();
    }

    private void stopMove() {
        exitFlag = true;
        mHandler.removeCallbacksAndMessages(null);
    }

    public void startMove() {
        exitFlag = false;
        mHandler.post(moveRun);
    }


    /**
     * 获取绘制文字的baseline
     *
     * @param paint
     * @param targetRect
     * @return
     */
    public static float getTextDrawingBaseline(Paint paint, RectF targetRect) {
        if (paint == null || targetRect == null) {
            return 0;
        }
        Paint.FontMetrics fontMetric = paint.getFontMetrics();
        return targetRect.top + (targetRect.height() - fontMetric.bottom + fontMetric.top) / 2.0f - fontMetric.top;
    }
}


调用代码:
package com.example.marquee;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.RelativeLayout;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		RelativeLayout rl = new RelativeLayout(MainActivity.this);
		setContentView(rl);

		CustomTextView view = new CustomTextView(MainActivity.this);
		view.setBackgroundColor(Color.GRAY);
		view.setText("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
		rl.addView(view, 300, 100);
	}
}


大家可以根据自己的需要去调整步长,建议不要修改刷新间隔时间。

附件是Demo工程,可以在上面调整出需要的速度
分享到:
评论
1 楼 jingbin4679 2015-08-27  
    

相关推荐

Global site tag (gtag.js) - Google Analytics