一般在绘制图形界面时,我们用到的是配置文件中的视图,那么我们能不能定义自己需要的视图呢?答案当然是可以的,我们可以利用画笔在画布上自己绘制自己需要的视图,在界面中引用过即可。然而,象画图这样的操作,我们不建议放在主UI线程中使用,我们可以利用继承自SurfaceView或者继承自View的方式去实现,我们具体来看一下吧。

   一:继承自View完成自定义视图

   自定义视图无疑就是绘制自己想要的视图样式,引用到工程中的过程。先来看看,如何自定义视图?

   1:自定义继承自View的类,用来完成绘制。

   (1)添加构造方法,在构造方法中实例化画笔,为画笔设置颜色

   (2)重写onDraw方法:参数为画布,可以设置画布的背景色,完成图形的绘制等

//自定义视图继承自View
public class MyView extends View{
    private Paint paint;//声明画笔
    public MyView(Context context) {
        super(context);
        paint = new Paint();//实例化画笔
        paint.setColor(Color.GREEN);//设置画笔的颜色
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);//设置画布的背景色
        //绘制矩形,参数(起始点x坐标,起始点y坐标,宽度,高度,画笔对象)
        canvas.drawRect(10, 10, 100, 100, paint);
    }
}

   2:在主界面的onCreate方法中引入自定义的视图对象

setContentView(new MyView(this));

   3:结果:在主界面上绘制出了自定义的视图样式,如下

   二:应用继承自View实现矩形块的”一定一动“

   1:添加构造方法,完成画笔的初始化与属性的设置

public MyRect(Context context) {
        super(context);
        paint.setColor(Color.GREEN);
    }

   2:继承自View的类中的onDraw方法中,实现矩形的绘制

private float x = 0;// 起始x,y坐标
    private float y = 0;
    private float speedx = 50;// 矩形的宽与高
    private float speedy = 50;
    private float addy = 2;// 每次移动时,x,y的增量值
    private float addx = 2;
    // 设置画布的背景色
        canvas.drawColor(Color.WHITE);
        // 矩形的绘制
        canvas.drawRect(x, y, x + speedx, y + speedy, paint);
        y += addy;// y坐标值得变化
        if (y < 0) {// 若y的上边界超出了正值的范围,跑到了手机屏幕的上方
            addy = Math.abs(addy);// 则让他的增量值为+,向下跑
        }
        if (y > getHeight() - speedy) {// 如果y的下边界超出了屏幕范围
            addy = -Math.abs(addy);// 则让他的增量值为负,向上跑
        }
        x += addx;// x坐标值得变化
        if (x < 0) {// 若x的左边界超出了正值的范围,跑到了手机屏幕的左方
            addx = Math.abs(addx);
        }
        if (x > getWidth() - speedx) {// 如果x的右边界超出了屏幕范围
            addx = -Math.abs(addx);// 则让他的增量值为负,向左跑
        }

3:创建Handler对象,实现Handler对象,在其中的handleMessage方法中实现重绘

private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            invalidate();// 重画
        };
    };

   4:添加计时器的启动与终止方法,在启动计时器中添加handler发送消息的方法

// 计时器的启动
    public void startTimer() {
        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                // 发送消息
                handler.sendEmptyMessage(0);
            }
        };
        // 启动计时器
        timer.schedule(task, 100, 10);
    }
    // 终止计时器
    public void stopTimer() {
        timer.cancel();
    }

   5:主界面中,对自定义视图添加OnTouchListener监听,根据触发的动作,实现”一定一动“的效果

public class MainActivity extends Activity implements OnTouchListener {
    private MyRect myRect;// 声明自定义视图
    private int flag = 0;// 标志
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myRect = new MyRect(this);// 实例化自定义视图
        setContentView(myRect);// 添加视图
        myRect.setOnTouchListener(this);// 加载监听
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:// 是不是按下操作
            if (flag == 0) {// 若是第一次单击
                myRect.startTimer();// 启动,让他走
                flag = 1;// 更改标志
            }else if(flag==1){//若再次单击
                myRect.stopTimer();//则停止,不让他动
                flag=0;//修改标志
            }
            break;
        }
        return true;//注意,只有true的时候才会触发
    }
}

   6:结果:通过这种方法,实现矩形“一定一动”效果。可以自行试试。

   三:继承自SurfaceView实现的自定义视图

   普通的绘制静态图形的操作还好,但是如果绘制动态或者更耗时的操作时,我们并不建议将他们直接放置在主UI线程中,我们继承自SurfaceView就是自己创建了一个线程,在这个线程中去完成操作,显得更好一些。

   应用:我们利用这种方法实现矩形的自由移动。

   1:继承自SurfaceView,并实现SurfaceHolder.Callback接口,重写其中的三个方法

public class MySurface extends SurfaceView implements SurfaceHolder.Callback

   (1)surfaceCreated方法:当SurfaceView第一次创建时触发的方法,主要完成初始化的工作,一搬不要在这里完成绘制的操作

   (2)surfaceChanged方法:当Surface的状态发生变化时,触发的方法

   (3)surfaceDestoryed方法:当Surface销毁前触发的状态,用于清理资源。

   2:添加构造方法,实现画笔的初始化及属性设置,并添加回调

public MySurface(Context context) {
        super(context);
        paint.setColor(Color.GREEN);//画笔的颜色设置
        getHolder().addCallback(this);//添加回调
    }

   3:自定义绘图方法,完成矩形的绘制

private float x=0;//起始x,y坐标
    private float y=0;
    private float speedx=50;//矩形的宽与高
    private float speedy=50;
    private float addy = 2;//每次移动时,x,y的增量值
    private float addx=2;
    public void draw(){
        //锁定画布,所有的绘图操作,都要在锁定于解锁之间完成,否则出错
        Canvas canvas=  getHolder().lockCanvas();
        //设置画布的背景色
        canvas.drawColor(Color.WHITE);
        //矩形的绘制
        canvas.drawRect(x, y, x+speedx, y+speedy,paint);
        y +=addy;//y坐标值得变化
        if(y<0){//若y的上边界超出了正值的范围,跑到了手机屏幕的上方
            addy = Math.abs(addy);//则让他的增量值为+,向下跑
        }
        if(y>getHeight()-speedy){//如果y的下边界超出了屏幕范围
            addy = -Math.abs(addy);//则让他的增量值为负,向上跑
        }
        x +=addx;//x坐标值得变化
        if(x<0){//若x的左边界超出了正值的范围,跑到了手机屏幕的左方
            addx = Math.abs(addx);
        }
        if(x>getWidth()-speedx){//如果x的右边界超出了屏幕范围
            addx = -Math.abs(addx);//则让他的增量值为负,向左跑
        }
        //解锁画布
        getHolder().unlockCanvasAndPost(canvas);
    }

   4:自定义定时器的启动与暂停,并在计时器中调用绘图方法

//计时器的启动
    public void startTImer(){
        timer = new Timer();//实例化计时器
        task = new TimerTask() {
                                                                                                                                                                                                                                                
            @Override
            public void run() {
                draw();//调用绘图方法
            }
        };
        //启动计时器
        timer.schedule(task, 100,10);
    }
    //停止计时器
    public void stopTimer(){
        timer.cancel();
    }

   5:将启动计时器,关闭计时器的方法的引用添加到接口中重写的三个方法中(注意引用的位置)

// 调用启动计时器的方法
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        startTImer();
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }
    // 调用终止计时器的方法
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopTimer();
    }

   6:结果:实现了绿色矩形块在屏幕范围内的自由移动。

   自定义视图很有用处,我们得熟记于心哦。。。