zoukankan      html  css  js  c++  java
  • View类和surfaceView详细介绍

    View类和surfaceView详细介绍:

      view类:

        view类是Android的一个超类,这个类几乎包含了所有的屏幕类型,每一个view都有一个用于绘画 的画布,这个画布可以进行任意的扩展。布局视图可以通过Android的XML来进行。在游戏开发中当然也可以自定义视图(view),让这个画布的功能更能满足我们在游戏开发是的需要,在Android中,任何一个view类只需要重写onDraw方法来实现界面显示,自定义视图可以是复杂的3D实现,也可以是简单地文本形式等。

        游戏中最重要的就是与玩家交互,比如键盘输入、触笔点击等事件,而我们该如何处理这些事件呢?OnKeyUp(按键弹起)、OnKeyDown(按键按下)、OoKeyMultiple(多个事件连续发生时调用)、OnTouchEvent(触摸事件)等方法,可以轻松的处理游戏内的事件消息。所以当你在继承view是,需要重载这几个方法,当有按键弹起或按下时,按键代码会自动传输给相应的方法来处理。

        游戏的核心是不断地绘图和刷新界面,图我们已经知道,需要使用onDraw方法绘制。下面我们来分析一下如何刷新界面。Android中提供了invalidate方法来实现界面的刷新,注意,invalidate方法不能直接在线程中调用,因为它违背了单线程模型,Android UI 操作并不是线程安全的,并且这些操作必须在UI线程中执行,因此Android中最常用的方法是利用Handler来实现UI 线程的更新。

        下面通过一个在屏幕上不停变换颜色的矩形来分析Android中界面的更新。

    //新建一个类,扩展至View类

    public class GameView extends View{

    public int count =0 ; //用于控制颜色的转换
    public static int y=100; //矩形的y轴坐标
    public static int x=100; //矩形的x轴坐标

    public GameView(Context context){
    super(context);
    }

    //重写onDraw方法,用于绘制界面
    public void onDraw(Canvas canvas){
    if(count<100){
    count++;
    }else{
    count=0;
    }
    Paint paint = new Paint();
    switch(count%4){
    case 0:
    //设置画笔颜色
    paint.setColor(Color.RED);
    break;
    case 1:
    paint.setColor(Color.BLUE);
    break;
    case 2:
    paint.setColor(Color.YELLOW);
    break;
    case 3:
    paint.setColor(Color.GREEN);
    break;
    }
    //绘制一个矩形
    canvas.drawRect(x,y,300+x,y+300, paint);
    }
    }

    上面的类主要用于绘制界面,下面我们还需要一个用来控制整个应用的操作,比如:事件处理、更新频率的类,这就需要实现一个Activity类。

    public class MainActivity extends Activity {

    //一个十六进制的整形数,用于判断接受到的信息是否是我们想要的信息
    private static final int REFRESH = 0X00000001;
    //声明GameView类对象
    private GameView gameView = null;;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //设置无标题模式
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //实例化GameView对象
    gameView = new GameView(this);
    setContentView(gameView);

    //启动一个线程
    new Thread(new MyThread()).start();
    }

    //声明并创建一个Handler对象用于接受消息
    Handler handler = new Handler(){

    //接受到消息后的处理
    public void handleMessage(Message msg) {
    switch(msg.what){
    case MainActivity.REFRESH:
    gameView.invalidate();
    }
    super.handleMessage(msg);
    }
    };

    /*class MyThread implements Runnable{
    public void run(){
    while(!Thread.currentThread().isInterrupted()){
    Message message = new Message();
    message.what = MainActivity.REFRESH;
    //发送消息
    handler.sendMessage(message);
    }
    try{
    Thread.sleep(1000);
    }catch(InterruptedException e){
    Thread.currentThread().interrupt();
    }
    }
    }*/

    //安卓中还提供了postInvalidate()方法来更新界面,该方法使用简单,可以直接在线程中更新,同樣可以更新界面,並且不需要Handle接受消息
    class MyThread implements Runnable{
    public void run(){
    while(!Thread.currentThread().isInterrupted()){
    try{
    Thread.sleep(1000);
    }catch(InterruptedException e){
    Thread.currentThread().interrupt();
    }
    gameView.postInvalidate();
    }
    }
    }

    public boolean onKeyDown(int keyCode,KeyEvent event){
    switch(keyCode){
    case KeyEvent.KEYCODE_DPAD_DOWN:
    GameView.y += 10;
    break;
    case KeyEvent.KEYCODE_DPAD_LEFT:
    GameView.x -= 10;
    break;
    case KeyEvent.KEYCODE_DPAD_RIGHT:
    GameView.x += 10;
    break;
    case KeyEvent.KEYCODE_DPAD_UP:
    GameView.y -= 10;
    break;
    }

    return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction()!=MotionEvent.ACTION_DOWN){
    return false;
    }
    GameView.x=(int) event.getX();
    GameView.y=(int) event.getY();
    return super.onTouchEvent(event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }

    }

      surfaceView类介绍:

        view类只适合开发一些需要被动更新界面的游戏,如棋牌类游戏,但是当需要开发复杂的游戏,而且对游戏的执行效率要求更高时,view类就不能满足需求了,这时就需要surfaceView类进行开发。例如对速度要求很高的游戏,可以使用双缓冲显示,游戏中的背景、人物、动画都需要绘制在一个画布(canvas)上,而surfaceView可以直接访问一个画布,surfaceview类是提供给需要直接画像素而不是使用窗口部件的应用使用的。安卓图形系统中一个重要的概念是surface,view,及其子类如(TextView,Button)要画在surface上,每个surface创建一个canvas对象(但属性时常改变),用来管理view在surface上的操作。

        在使用surfaceView开发游戏时需要注意的是,使用它绘制时,一般的出现在最顶层,使用时还需对其进行创建、销毁,情况改变时进行监视,这就需要实现surfaceHolder.callback接口,如果要对被绘制的画布进行裁剪,控制其大小时都需要surfaceHolder来完成处理。在程序中,surfaceholder对象需要通过getHolder方法来获取,同时还需要addCallback方法添加“回调函数”。

        surfaceChanged:在surface的大小发生改变时激发

        surfaceCreated:在创建surface的时候激发

        surfaceDestroyed:在销毁surface的时候激发】

        addCallback:给surfaceView添加一个回调函数

        lockCanvas:锁定画布,绘图之前,必须锁定画布才能得到当前画布对象

        unlockCanvasAndPost:解锁画布,绘图完成后,需要解锁画布才能显示出来

        removeCallback:从surfaceView中移除回调函数

      surfaceview和view的明显不同之处在于,surfaceview不需要通过线程来更新视图,但在绘图之前必须通过lockCanvas放法锁定画布,得到画布对象,然后在画布上进行绘制,当绘制完成后,需要通过unlockCanvasAndPost方法解锁画布,于是才能显示在屏幕上,surfaceView和view的事件处理一样,这里不多做介绍  。

      下面的程序实现了一个不断变化颜色的圆,用来分析通过surfaceView类开发游戏。

    public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{

    public static float x = 200;
    public static float y = 200;
    private SurfaceHolder surfaceHolder= null;
    private boolean mLoop = false;
    private int count = 0;

    public MySurfaceView(Context context) {
    super(context);
    surfaceHolder = this.getHolder();
    surfaceHolder.addCallback(this);
    mLoop = true;


    }

    @Override
    public void run() {
    while(mLoop){
    try{
    Thread.sleep(10);
    }catch(Exception e){
    e.printStackTrace();
    }
    synchronized(surfaceHolder){
    draw();
    }
    }
    }

    public void draw(){
    Canvas canvas = surfaceHolder.lockCanvas();
    if(canvas == null || surfaceHolder == null){
    return;
    }
    if(count <100 ){
    count ++;
    }else{
    count = 0;
    }

    Paint paint = new Paint();
    paint.setColor(Color.BLACK);
    canvas.drawRect(0,0,this.getWidth(),getHeight(),paint);
    switch(count%4){
    case 0:
    paint.setColor(Color.RED);
    break;
    case 1:
    paint.setColor(Color.BLUE);
    break;
    case 2:
    paint.setColor(Color.YELLOW);
    break;
    case 3:
    paint.setColor(Color.GREEN);
    break;
    }
    canvas.drawCircle(x, y, 30, paint);
    surfaceHolder.unlockCanvasAndPost(canvas);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    new Thread(this).start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
    // TODO Auto-generated method stub

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
    mLoop = false;
    }

    }

    Activity类:

    public class MainActivity extends Activity {

    private MySurfaceView mySurfaceView= null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mySurfaceView = new MySurfaceView(this);
    setContentView(mySurfaceView);
    }

    public boolean onKeyUp(int keyCode,KeyEvent event){
    if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
    MySurfaceView.y += 20;
    }else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
    MySurfaceView.y -= 20;
    }else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
    MySurfaceView.x -= 20;
    }else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
    MySurfaceView.x += 20;
    }
    return super.onKeyUp(keyCode, event);
    }

    public boolean onTouchEvent(MotionEvent event){
    MySurfaceView.x = event.getX();
    MySurfaceView.y = event.getY();

    return super.onTouchEvent(event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }

    }

    奋斗和第三方
  • 相关阅读:
    ethtool 命令输出的注意点--网卡参数
    centos7.2+zabbix3.2+sedmail邮件告警
    vscode monokai
    SQL SERVER 常用命令
    数据库问题6-將系統資料表對應至系統檢視
    数据库问题5-SYS.SYSPROCESSES使用和查找死锁
    select * from sys.sysprocesses
    【SQL Server学习笔记】事务、锁定、阻塞、死锁 sys.sysprocesses
    使用DMV调优性能 --Burgess_Liu
    sql server线程等待信息
  • 原文地址:https://www.cnblogs.com/Smart-Du/p/4299389.html
Copyright © 2011-2022 走看看