Android自定义跑马灯实现(SurfaceView)

     按道理跑马灯功能Android已经实现了,但自定义的跑马灯功能是通过SurfaceView来实现,使用子线程来更新视图,性能更好,跑马灯的启动和停止都是由自己控制,更加灵活。

public class MarqueeTextSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

	private SurfaceHolder mHolder;
	private MyThread myThread;
	private String mText = "";
	private boolean isSurfaceValid = false;
	private float textLength = 0f;// 文本长度
	private float viewWidth = 880.0f;// 控件的宽度
	private float step = 0f;// 文字的横坐标
	private float y = 0f;// 文字的纵坐标
	private float temp_view_plus_text_length = 0.0f;// 用于计算的临时变量
	private float temp_view_plus_two_text_length = 0.0f;// 用于计算的临时变量
	private int speed = 10;
	private Paint paint = null;// 绘图样式

	public MarqueeTextSurfaceView(Context context) {
		super(context);
	}

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

	public MarqueeTextSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		holder.setFixedSize(width, height);
	}

	public void setText(String str) {// 设置跑马灯的内容
		mText = str;
		textLength = paint.measureText(mText);
		temp_view_plus_two_text_length = viewWidth + textLength * 2f;
		// viewWidth = mHolder.getSurfaceFrame().width();
		step = textLength;
		temp_view_plus_text_length = viewWidth + textLength;
	}

	public void setSpeed(int speed) {// 设置跑马灯的速度
		this.speed = speed;
	}

	public void canScroll() {
		isSurfaceValid = true;
	}

	public void suspend() {// 选中获焦跑马灯暂停
		step = temp_view_plus_text_length - 20;
	}

	public void init() {// 初始化
		setZOrderOnTop(true);
		mHolder = getHolder();
		mHolder.addCallback(this);
		myThread = new MyThread(mHolder);
		mHolder.setFormat(PixelFormat.TRANSPARENT);
		paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 创建画笔
		paint.setTextSize(spToPixel(getContext(), 20f));
		paint.setColor(getResources().getColor(R.color.marquee));
		y = getFontHeight(paint);
		canScroll();
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		isSurfaceValid = true;
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		isSurfaceValid = false;
	}

	class MyThread extends Thread {
		private SurfaceHolder holder;
		public boolean canRun;

		public MyThread(SurfaceHolder holder) {
			this.canRun = true;
			this.holder = holder;
		}

		@Override
		public void run() {
			Canvas c = null;
			while (canRun && isSurfaceValid) {
				try {
					// Thread.sleep(50);
					c = holder.lockCanvas();// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
					handlerDrawInternal(c);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (c != null) {
						holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
					}
				}
				try {
					Thread.sleep(30);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}// 睡眠时间为1秒

			}

			// reset
			try {
				c = holder.lockCanvas();
				handlerDrawInternal(c);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (c != null) {
					holder.unlockCanvasAndPost(c);
				}
			}
		}
	}

	public void startScroll() {// 跑马灯启动
		if (!isSurfaceValid) {
			return;
		}
		// myThread.canRun = true;
		if (!myThread.isAlive()) {
			myThread = new MyThread(mHolder);
			myThread.start();
		}
	}

	public void stopScroll() {// 跑马灯停止
		myThread.canRun = false;
		isSurfaceValid = false;
		// myThread.interrupt();
	}

	private void handlerDrawInternal(Canvas canvas) {
		if (canvas == null) {
			return;
		}
		step += speed;
		if (step >= temp_view_plus_two_text_length)// 达到一定限值,跑马灯重新进行
			step = textLength;
		canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
		canvas.drawText(mText, 0, mText.length(), temp_view_plus_text_length - step, y, paint);
	}

	private static float getFontHeight(Paint paint) {// 获得字体高度
		Rect bounds = new Rect();
		paint.getTextBounds("这", 0, 1, bounds);
		return bounds.height();
	}

	// private static float pixelsToSp(Context context, Float px) {
	// float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
	// return px / scaledDensity;
	// }

	private static float spToPixel(Context context, Float sp) {
		float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
		return sp * scaledDensity;
	}

}

 

关注我的个人公众号,提供更丰富的技术资讯和相关资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值