上述代码为initBitmap 方法的全部代码, 其作用是对程序中所有的图片资源进行初始化, 在开发该方法之前, 应该确保所有的图片资源已经存放到了指定的目录下。
完成了图片资源初始化方法的开发后, 便可对气泡位置初始化方法initLOCation 进行开发了, 其代码如下:
private void initLocation(){ //初始化气泡位置的方法
shang2_X = shang1_X + shangBitmap1.getWidth()/2- shangBitmap2.getWidth()/2;
shang2_Y = shang1_Y + shangBitmap1.getHeight()/2- shangBitmap2.getHeight()/2;
zuo2_X = zuo1_X + zuoBitmap1.getWidth()/2- zuoBitmap2.getWidth()/2;
zuo2_Y = zuo1_Y + zuoBitmap1.getHeight()/2- zuoBitmap2.getHeight()/2;
zhong2_X = zhong1_X + zhongBitmap1.getWidth()/2- zhongBitmap2.getWidth()/2;
zhong2_Y = zhong1_Y + zhongBitmap1.getHeight()/2- zhongBitmap2.getHeight()/2;
xia2_X = xia1_X + xiaBitmap1.getWidth()/2- xiaBitmap2.getWidth()/2;
xia2_Y = xia1_Y + xiaBitmap1.getHeight()/2- xiaBitmap2.getHeight()/2;
}
在该方法中通过相应图片的宽度和高度动态计算气泡的初始坐标, 采用此方法动态计算气泡坐标的好处是当日后更改图片资源后, 不需要重写修改源代码即可正常运行, 大大提高了程序的可维护性。
在完成了各个初始化方法的开发后就可以对绘制方法onDraw 进行开发, 该方法主要负责界面的绘制工作, 其代码如下:
@Override
protected void onDraw(CANvas canvas){//界面绘制方法super.onDraw(canvas);
canvas.drawColor(Color.WHITE); //设置背景色为白色
paint.setColor(Color.BLUE); //设置画笔颜色
paint.setStyle(Style.STROKE); //设置画笔为不填充
canvas.drawRect(5, 5, 315, 315, paint);//绘制外边框矩形
//画背景矩形
canvas.drawBitmap(shangBitmap1, shang1_X,shang1_Y, paint); //上
canvas.drawBitmap(zuoBitmap1, zuo1_X,zuo1_Y, paint); //左
canvas.drawBitmap(zhongBitmap1, zhong1_X,zhong1_Y, paint); //中
canvas.drawBitmap(xiaBitmap1, xia1_X,xia1_Y, paint); //下
//开始绘制气泡
canvas.drawBitmap(shangBitmap2, shang2_X,shang2_Y, paint); //上
canvas.drawBitmap(zuoBitmap2, zuo2_X,zuo2_Y, paint); //左
canvas.drawBitmap(zhongBitmap2, zhong2_X,zhong2_Y, paint); //中
canvas.drawBitmap(xiaBitmap2, xia2_X, xia2_Y, paint);//下
paint.setColor(Color.GRAY);//设置画笔颜色用来绘制刻度
//绘制上面方框中的刻度
canvas.drawLine (shang1_X+shangBitmap1.getWidth()/2-7,shang1_Y, shang1_X+shangBitmap1.getWidth()/2-7,shang1_Y+shangBitmap1.getHeight()-2, paint);
canvas.drawLine (shang1_X+shangBitmap1.getWidth()/2+7,shang1_Y, shang1_X+shangBitmap1.getWidth()/2+7,shang1_Y+shangBitmap1.getHeight()-2, paint);
//绘制左面方框中的刻度
canvas.drawLine(zuo1_X,zuo1_Y+zuoBitmap1.getHeight()/2-7,zuo1_X+zuoBitmap1.getWidth()-2,zuo1_Y+zuoBitmap1.getHeight()/2-7, paint);canvas.drawLine(zuo1_X,zuo1_Y+zuoBitmap1.getHeight()/2+7,zuo1_X+zuoBitmap1.getWidth()-2,zuo1_Y+zuoBitmap1.getHeight()/2+7, paint);
//绘制下面方框中的刻度
canvas.drawLine(xia1_X+xiaBitmap1.getWidth()/2-10,xia1_Y+xiaBitmap1.getHeight()/2-20,xia1_X+xiaBitmap1.getWidth()/2+20,xia1_Y+xiaBitmap1.getHeight()/2+10, paint);
canvas.drawLine(xia1_X+xiaBitmap1.getWidth()/2-20,xia1_Y+xiaBitmap1.getHeight()/2-10,xia1_X+xiaBitmap1.getWidth()/2+10,xia1_Y+xiaBitmap1.getHeight()/2+20, paint);
//中间圆圈中的刻度(小圆)
RectF oval = new RectF(zhong1_X+zhongBitmap1.getWidth()/2-10,zhong1_Y+zhongBitmap1.getHeight()/2-10,zhong1_X+zhongBitmap1.getWidth()/2+10,zhong1_Y+zhongBitmap1.getHeight()/2+10);
canvas.drawOval(oval, paint);//绘制基准线(圆)
}
在该方法中, 根据相应图片的X、Y 坐标将图片绘制到屏幕中, 在图片的绘制过程中, 同样动态根据相应图片的宽和高计算需要绘制到的位置坐标, 以提高程序的可维护性与灵活性。
6 相关XML 文件的编写
完成了用于显示水平仪界面的自定义View 的Java 代码开发之后, 就应该对布局XML 资源文件进行编写, 以将之前开发的自定义View 添加到用户界面中。打开项目中res/layout 目录下的main.xml, 在其中编写如下的xml 代码:
<?xml version="1.0" encoding="utf-8"?> <!--编码格式-->
<LinearLayoutxmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation="vertICal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"> <! --线性布局-->
<wyf.ytl.MainView
android:id="@+id/mainView"
android:layout_width="fill_parent"
android:layout_height = "fill_parent"/>< ! -- 自定义
View-->
</LinearLayout>
www.55dianzi.com
编写完布局文件main.xml 后, 还需要开发字符串资源文件strings.xml.打开res/values 下的strings.xml 文件, 编写如下的代码:
<?xml version="1.0" encoding="utf-8"?> <!--编码方式-->
<resources>
<string name="app_name">水平仪</string>
</resources>
在该文件中只是对字符串app_name 进行了定义, 在开发Android 应用程序时, 将字符串资源统一定义到一个xml 文件中是一个很好的编程习惯。
编写完上述的xml 资源文件后, 为了调试还需要为此应用程序添加网络权限, 打开项目根目录下的AndroiDMAnifest.xml文件, 在"</manifest>" 标签之前加入下列代码:
<uses-permission android:name="android.permission.INTERNET"/>
上述代码的功能为此应用程序添加了访问网络的权限。
7 Activity 类的开发
完成了自定义View 以及XML 文件的开发后, 就可以对用户界面对应的Activity 类进行开发, 首先开发该类的代码框架,其代码如下:
PACkage wyf.ytl; //声明所在包
import android.app.Activity; //引入相关类
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
publIC class SPYActivity extends Activity { //继承Activity MainView mv; //主View
int k = 45; //灵敏度
//SensorManager mySensorManager;
//真机
SensorManagerSimulator mySensorManager; //测试时@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.main);//设置当前用户界面
mv = (MainView) findViewById(R.id.mainView);
mySensorManager =SensorManagerSimulator.getSystEMService(this,SENSOR_SERVICE); //测试时
mySensorManager.connectSimulator();//测试时
//mySensorManager = (SensorManager)
// getSystemService(SENSOR_SERVICE);//真机
}
private final SensorListener mSensorLisener =new SensorListener(){ //传感器监听
//器类
…//该处省略了部分代码,将在后面进行介绍
};
@Override
protected void onResume(){ //添加监听
mySensorManager.registerListener(mSensorLisener,SensorManager.SENSOR_ORIENTATION);
super.onResume();
}
@Override
protected void onPause() { //取消监听
mySensorManager.unregisterListener (mSensorLisener);
super.onPause();
}
}
上述代码中除了重写了onCreate 方法外, 还重写了onRe-sume 以及onPause 方法为mySensorManager 添加或删除监听,并且定义了传感器监听器类mSensorLisener.
在完成了Activity 类代码框架的开发后就可以对其中传感器的监听类进行开发, 首先给出监听器类的代码框架:
private final SensorListener mSensorLisener =
new SensorListener(){//传感器监听器类
public void onSensorChanged(int sensor, float[] values){…//该处省略了部分代码,将在后面进行介绍
}
@Override
public void onACCuracyChanged(int sensor, int accuracy){}