按道理跑马灯功能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;
}
}
关注我的个人公众号,提供更丰富的技术资讯和相关资源