不少童鞋说个人代码运行后,点击home或者back后会程序异常,若是你也这样遇到过,那么你确定没有仔细读完Himi的博文,第十九篇Himi专门写了关于这些错误的缘由和解决方法,这里我在博客都补充说明下,省的童鞋们总疑惑这一块;请点击下面联系进入阅读:css
【Android游戏开发十九】(必看篇)SurfaceView运行机制详解—剖析Back与Home按键及切入后台等异常处理!html
各位童鞋请大家注意:surfaceview中确实有 onDraw这个方法,可是surfaceview不会本身去调用!!!java
而我代码中的ondraw 也好 draw 也好,都是我本身定义的一个方法。。。放在线程中不断调用的,必定要注意!!android
昨天圣诞节,没有出去,而是一天时间所有纠结在如何在SurfaceView中添加组件,例如添加经常使用的Button,TextView等等、一开始也想着从网上找些资料看看有没有可参考的,可是发现搜到的结果还是些童鞋对此很疑惑而且也在找寻答案,那么,这里就把圣诞节一天的成果来和各位童鞋分享;app
1.由于咱们的SurfaceView是个View对于添加的组件其实也是View,若是咱们只是一味的想在SurfaceView中添加View组件实际上是错误的思想,固然我一开始也是想着直接在SurfaceView中定义或者去使用组件,可是结果确定是不成功的,由于View不能添加View!ide
2.既然第一条确定是错误的,那么咱们就应该想到把咱们的SurfaceView和组件都放在一个Layout里面,毕竟咱们的的SurfaceView也是一个view和其余组件一同放在咱们的layout里,那么这样一来确定就能完成在SurfaceView中添加组件的目的啦。下面先上截图、函数
你们看到中间白色区域就是咱们的SurfaceView啦,最上方是组件TextView ,最下方是Button 、对的,要的就是这个效果!而不是像前面文章中多个Activity切换,这样都在一个界面中啦。哇哈哈啊。好、下面来看代码吧:布局
先放上Xml 代码:this
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"> <TextView android:id="@+id/textview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="This is Himi" android:textSize="32sp" android:textColor="#00FF00" android:gravity="center_horizontal"/> </LinearLayout> <FrameLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" > <com.himi.MySurfaceView android:id="@+id/view3d" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </FrameLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Himi Button_1" android:id="@+id/button1"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Himi Button_2" android:id="@+id/button2"/> </LinearLayout> </LinearLayout>
以上代码很简单,都是一些布局方式和各个组件一些属性及显示方式的设定,固然主要看如何对咱们的SurfaceView如何注册在xml中的,那么每一个组件都有id这样为了对后面其交互数据用到,由于咱们要对每一个组件操做,因此这里都索引了id方面从R文件中取出其对象。spa
那么,xml咱们定义好了,看看代码中如何实现的,这里先说下Activity类中代码:
package com.himi; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { /** Called when the activity is first created. */ private Button button1, button2; private TextView tv ; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE);//隐去标题(应用的名字) //此设定必需要写在setContentView以前,不然会有异常) this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); //要先显示,而后再对其组件取出、处理操做 tv=(TextView)findViewById(R.id.textview); button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(this);//这里是监听按键,由于本类使用了OnClickListener接口 button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(this); /* 其实你们也能够不用本类使用接口,能够内部类来完成。 * 如下是不使用OnClickListener接口的绑定监听方式; button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //这里处理按键操做 } }); */ } @Override public void onClick(View v) { if (v == button1) { MySurfaceView.button_str = "button 1被触发"; tv.setText("button 1被触发"); } else if (v == button2) { MySurfaceView.button_str = "button 2被触发"; tv.setText("button 2被触发"); } } }
该有的备注在代码后面都备注了,MySurfaceView.button_str,这个是本身的SurfaceView中定义的一个static 的变量用来交互数据用到;在那么下面就要看咱们的SurfaceView,当在Xml注册须要注意什么了,我半天的时候都花在了这里!!!必定要引发注意,这也是在SurfaceView中并显示组件完成最重要的一步。
先分析:
1.SurfaceView类的建立和实现等等和以前都是同样的,该怎么去写还怎么去写,可是!构造函数必定要注意!
/* * public MySurfaceView(Context context) { super(context); }//备注1(这里必定要引发注意,仔细看下文对备注1的解释 ) */ public MySurfaceView(Context context, AttributeSet attrs) {//备注1}
这里解释下备注1: 这里有两个构造函数,固然咱们用哪一个都是能够的,可是在此时咱们须要明确咱们到底要使用哪一个。
一个参数的构造函数:若是是new出来的此类实例确定是没有问题,可是咱们为了能在显示SurfaceView同时显示别的组件,因此把自定义的SurfaceView也看成组件注册在了main——xml中,因此这里须要注意,当在xml中注册的就必须在SurfaceView中使用这种含有两个参数的构造函数的方法, xml初始化的时候会调用两个参数的这个构造方法, (当时这个问题困扰了半天的研究时间,最后在一个群友的帮助下才发现是这里出了问题) 那么含有两个构造参数的方法里第二个参数指的自定义的组件的一些属性,就像长宽同样,你能够给组件属性,就是经过这个来传递的!
那么在SurfaceView 中并一同显示组件也就到底完结了,回顾下,一共分为3步,1.将咱们的SurfaceView 做为一个组件view 和其余组件一同放置到布局中,固然布局的方式和显示的方式你们本身随本身喜欢定义! 2.在咱们的SurfaceView中必定要使用两个构造函数的构造函数,必定!必定! 就这里有区别,别的仍是该怎么处理就怎么处理,就是构造函数换了 3.交互数据,对其按键的绑定在 activity中完成,别把view绑定在我们的SurfaceView中啊,不然报错- -、
这里说下为何要在activity中去绑定按键处理 而不是在咱们的surfaceview中去绑定:
其实根据xml中定义button时的id 咱们能够经过R.id 索引取到button,无论在activity中仍是咱们的surfaceview中均可以取到,可是!绑定button这一步若是在 surfaceview中去写就必定报错,缘由我解释下;
咱们在xml中定义咱们的surfaceview 和 组件button、textview等等的时候 他们是同一级别的!!而不是把button包含在 surfaceview
里,因此虽然在surfaceview中能够根据id索引到button但绑定的时候是没法找到button的,只有咱们的activitysetContentView(R.layout.main); 显示的button,因此只能在显示它的activity中去绑定,这里须要注意下;
下面分享出源码:
源码下载地址: http://www.himigame.com/android-game/306.html
(推荐你们订阅本博客,由于咱的更新速度但是很快的~娃哈哈)