自定义View在开发中是经常遇到的,例如一个×××灯的效果、或者自定义一个转盘来显示下载进度的百分百比。今天把实现方式写下来,下面是源码部分:

MainActivity:没变动

importandroid.app.Activity;importandroid.os.Bundle;publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}

主布局:只增加了一个自定义View

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><com.example.myview.MineViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"></com.example.myview.MineView></RelativeLayout>

自定义View:

importjava.util.Random;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Paint;importandroid.graphics.RectF;importandroid.os.SystemClock;importandroid.util.AttributeSet;importandroid.view.View;publicclassMineViewextendsView{/***字体移动的X坐标*/privateintrx=0;/***画笔工具*/privatePaintpaint;/***创建线程对象,用于循环延迟执行命令*/privateMyThreadt;/***0表示圆的left,60表示圆的top,100表示圆的right,160表示圆的bottom*/privateRectFrectF=newRectF(0,60,100,160);/***表示区间角度*/privatefloatsweepAngle;/***创建随机数对象*/privateRandomrandom;/***isdestroy表示该Activity是否已经结束*/privatebooleanisdestroy=false;publicMineView(Contextcontext,AttributeSetattrs){super(context,attrs);System.out.println("构造器");paint=newPaint();random=newRandom();//抗锯齿,否则图像会很难看paint.setAntiAlias(true);if(t==null){t=newMyThread();t.start();}}publicMineView(Contextcontext){super(context);System.out.println("构造器");paint=newPaint();paint.setAntiAlias(true);if(t==null){t=newMyThread();t.start();}}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);paint.setTextSize(30);//rx表示移动字体的x坐标canvas.drawText("移动字体",rx,30,paint);//rectF表示圆的对象,0表示起始角度,sweepAngle表示区间角度,true和false表示绘制过程的方式,paint表示画笔对象canvas.drawArc(rectF,0,sweepAngle,true,paint);}classMyThreadextendsThread{@Overridepublicvoidrun(){super.run();while(true){rx+=5;//如果字体移动出屏幕以外,就让字体从头开始if(rx>getWidth()){rx=(int)(0-paint.measureText("移动字体"));}sweepAngle+=5;//如果角度大于360就让圆从0度开始重新绘制if(sweepAngle>360){sweepAngle=0;}//让颜色从0-255随机选择intr=random.nextInt(256);intg=random.nextInt(256);intb=random.nextInt(256);//分别表示:透明度(0~255)、红、绿、蓝paint.setARGB(255,r,g,b);/***判断Activity是否已经退出,如果退出则isdestroy为true,那么立刻让线程对象与画笔对象为空,并且break,*否则会造成内存溢出,此办法必须在此处使用,否则会造成空指针的BUG。*/if(isdestroy){if(t!=null){t=null;}if(paint!=null){paint=null;}break;}//睡眠SystemClock.sleep(50);//可以让ondraw方法重新执行postInvalidate();//invalidate();分线程无效,要在主线程使用}}}/***当窗口销毁的时候会调用此方法,用于关闭资源*/@OverrideprotectedvoidonDetachedFromWindow(){super.onDetachedFromWindow();isdestroy=true;System.out.println("onDetachedFromWindow");}}

运行效果:运行起来是动态的,我不会上传动态效果,想看效果的自己跑起来就可以了。

注意:这里的×××灯效果只是一种非常笨的方式,有更简单的办法,我以后会介绍!