首页 > 代码库 > Expert的View——SurfaceView

Expert的View——SurfaceView

SurfaceView 用于要求界面更新迅速的UI,能够更自主的定义界面!通常作为2D游戏开发的首选。它与View有相似地方,但也有区别!


SurfaceView的基本用法:

 1。为了实现代码的方便管理且不混乱,最好继承SurfaceView并且实现SurfaceHolder.Callback接口,如下

public class MySurfView extends SurfaceView implements SurfaceHolder.Callback {

    public MySurfView(Context context) {
        super(context);
        init(context);

    }

    public MySurfView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);

    }

    public MySurfView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public MySurfView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }
    private SurfaceHolder surfaceHolder;
    private Paint paint;
    private Context context;
    private void init(Context context){
      surfaceHolder=this.getHolder();
        surfaceHolder.addCallback(this);
       paint=new Paint();
        this.context=context;
        paint.setColor(Color.BLUE);
    }

   //<span style="font-family: Arial, Helvetica, sans-serif;">实现SurfaceView界面的绘制</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-family: Arial, Helvetica, sans-serif;">  private void drawCanvas(){</span>
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    drawCanvas();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }<span style="font-family: Arial, Helvetica, sans-serif;">   </span>
<span style="font-family: Arial, Helvetica, sans-serif;">//通过MotionEvent获取x,y的坐标,实现SurfaceView界面的区域点击事件</span>
   
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">@Override public boolean onTouchEvent(MotionEvent event) { return true; }}</span>
2.还可以通过实例化一个SurfaceView,并且获取该SurfaceView的SurfaceHolder对象,之后给该SurfaceView赋值SurfaceHolder.CallBack,如下:
   private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MySurfView(this));
        surfaceView= (SurfaceView) findViewById(R.id.surfaceView);
        surfaceHolder=surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });

    }

SurfaceView如何绘制:

前面提到过SurfaceView的界面绘制是从surfaceCreated(SurfaceHolder holder)方法开始进行的,通过SurfaceHolder获取Canvas对象,绘制完成后释放并提交该对象,如下代码:

 private void oneTest(){
        Canvas canvas=surfaceHolder.lockCanvas();//获取SurfaceView的画布
        // 这部分代码为   画布的绘制部分
     surfaceHolder.unlockCanvasAndPost(canvas);//绘制完成后,释放画布Canvas</span>
    }

SurfaceView的事件监听:

SurfaceView类是继承MockView的子类,MockView继承了TextView,因此SurfaceView也拥有View的事件,但SurfaceView也会有它自己的事件特性,如果想监听SurfaceView的某一块区域点击事件,首先需要判断该触摸点是否在该区域中,如果在则触发该区域的事件!如下所示:

    private         Region region=new Region();
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /**
         * 点击事件
         */
        if (region.contains( (int)event.getX(), (int)event.getY())){

            Toast.makeText(context,"区域部分",Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(context,"not  区域部分",Toast.LENGTH_SHORT).show();

        }
        return true;
    }
上面示例的Region在绘制SurfaceView时必须设定其区域范围,区域范围的定制问题立马探讨!

SurfaceView的区域定制:

 1.使用Region来确定区域:下述代码是绘制一个矩形,设定Region的范围

      region.op(new Rect(0,0,300,100), Re     gion.Op.XOR);
        canvas.clipRegion(region);

2,使用坐标来进行计算,设备的左上角为(0,0)起点,向右为x轴正方向,向下为Y轴正方向,横竖屏切换时亦是如此!通过划定区域的坐标界限来确定触摸点是否在划定区域内!


Expert的View——SurfaceView