以前自学,都是用帧动画来实现跑马灯,这几天常失眠,晚上学东西也学不进,所以用Canvas写个小Demo,这么无聊的应该只有我一个了吧,废话不多说,下面上内容。
老规矩,最后有源码
效果图如下:

上代码前先介绍下手机坐标系,如下图

然后是绘制草图,如下:

大概思路为,开一个耗时线程使彩色背景旋转,来达到跑马灯的效果。
核心:
1.计算出View宽高,矩形宽高,从而算出矩形的坐标点。
1 int canvasWidth = canvas.getWidth(); //画布宽度 2 int canvasHeight = canvas.getHeight(); //画布高度 3 int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2,2)+Math.pow(canvasHeight/2,2))+1; //正方形宽高的一半
2.绘制背景,跑马灯,幕布
1 //开始绘制底层背景 2 p.setColor(Color.WHITE); 3 RectF oval2 = new RectF(0, 0, canvasWidth, canvasHeight);// 设置个新的长方形,扫描测量 4 canvas.drawRect(oval2,p); 5 //开始绘制跑马灯 6 Paint p1=new Paint(p); 7 Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax, 8 new int[] { 9 10 11 Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT); 12 p1.setShader(mShader); 13 RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// 设置个新的长方形 14 canvas.drawRect(oval,p1); 15 //绘制幕布 16 Paint p2=new Paint(); 17 p2.setColor(Color.BLACK); 18 RectF oval3 = new RectF(30, 30, canvasWidth-30, canvasHeight-30);// 设置个新的长方形,扫描测量 19 canvas.drawRect(oval3,p2);
3.找到旋转的依靠,并开启一个耗时任务。
1 private Calendar mCalendar; // 时间对象 2 public static final int START_CLOCK = 1000;// 开启时钟的标识 3 Handler mHandler = new Handler() { 4 5 6 7 public void handleMessage(android.os.Message msg) { 8 9 10 11 switch (msg.what) { 12 13 14 15 case DrawView.START_CLOCK: 16 mCalendar = mCalendar.getInstance(); 17 invalidate(); 18 sendEmptyMessageDelayed(DrawView.START_CLOCK, 10); 19 break; 20 case DrawView.STOP_CLOCK: 21 break; 22 default: 23 break; 24 } 25 } 26 };
4.设置彩色正方形旋转
canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2);
5.将幕布按照彩色正方形反向旋转(不设置则跟着正方形一起旋转);
canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2);
源码如下:
1.完整java文件
1public class MarqueeView extends View { 2 3 4 5 private Calendar mCalendar; // 时间对象 6 public static final int START_CLOCK = 1000;// 开启时钟的标识 7 Handler mHandler = new Handler() { 8 9 10 11 public void handleMessage(android.os.Message msg) { 12 13 14 15 switch (msg.what) { 16 17 18 19 case DrawView.START_CLOCK: 20 mCalendar = mCalendar.getInstance(); 21 invalidate(); 22 sendEmptyMessageDelayed(DrawView.START_CLOCK, 10); 23 break; 24 case DrawView.STOP_CLOCK: 25 break; 26 default: 27 break; 28 } 29 } 30 }; 31 32 public MarqueeView(Context context) { 33 34 35 36 super(context); 37 } 38 39 public MarqueeView(Context context, @Nullable AttributeSet attrs) { 40 41 42 43 super(context, attrs); 44 mCalendar = mCalendar.getInstance(); 45 if (mCalendar == null) { 46 47 48 49 mCalendar = mCalendar.getInstance(); 50 } 51 mHandler.sendEmptyMessage(START_CLOCK); 52 } 53 54 @Override 55 protected void onDraw(Canvas canvas) { 56 57 58 59 super.onDraw(canvas); 60 drawAxis(canvas); 61 } 62 63 //绘制 64 private void drawAxis(Canvas canvas){ 65 66 67 68 Paint p=new Paint(); 69 int canvasWidth = canvas.getWidth(); //画布宽度 70 int canvasHeight = canvas.getHeight(); //画布高度 71 int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2,2)+Math.pow(canvasHeight/2,2))+1; //正方形宽高的一半 72 int sec = mCalendar.get(Calendar.SECOND);//得到当前秒数 73 //开始绘制底层背景 74 p.setColor(Color.WHITE); 75 RectF oval2 = new RectF(0, 0, canvasWidth, canvasHeight);// 设置个新的长方形,扫描测量 76 canvas.drawRect(oval2,p); 77 canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2); 78 //开始绘制跑马灯 79 Paint p1=new Paint(p); 80 Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax, 81 new int[] { 82 83 84 Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT); 85 p1.setShader(mShader); 86 RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// 设置个新的长方形,扫描测量 87 canvas.drawRect(oval,p1); 88 //绘制幕布 89 Paint p2=new Paint(); 90 canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2); 91 p2.setColor(Color.BLACK); 92 RectF oval3 = new RectF(30, 30, canvasWidth-30, canvasHeight-30);// 设置个新的长方形,扫描测量 93 canvas.drawRect(oval3,p2); 94 95 96 } 97} 98
2.xml中调用
1<com................MarqueeView 2 android:layout_width="match_parent" 3 android:layout_height="match_parent"/>

本文同步分享在 博客“计蒙不吃鱼”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。