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 代码:
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:id="@+id/mainView"
android:layout_width="fill_parent"
android:layout_height = "fill_parent"/>< ! -- 自定义
View-->
编写完布局文件main.xml 后, 还需要开发字符串资源文件strings.xml.打开res/values 下的strings.xml 文件, 编写如下的代码:
水平仪
在该文件中只是对字符串app_name 进行了定义, 在开发Android 应用程序时, 将字符串资源统一定义到一个xml 文件中是一个很好的编程习惯。
编写完上述的xml 资源文件后, 为了调试还需要为此应用程序添加网络权限, 打开项目根目录下的AndroidManifest.xml文件, 在"" 标签之前加入下列代码:
上述代码的功能为此应用程序添加了访问网络的权限。
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){}
public boolean isContain(int x, int y){//判断点是否在圆内
int tempx =(int) (x + mv.zhongBitmap2.getWidth()/2.0);
int tempy =(int) (y + mv.zhongBitmap2.getWidth()/2.0);
int ox = (int) (mv.zhong1_X+ mv.zhongBitmap1.getWidth()/2.0);
int oy = (int) (mv.zhong1_X+ mv.zhongBitmap1.getWidth()/2.0);
if(Math.sqrt((tempx-ox)*(tempx-ox)+(tempy-oy)*(tempy-oy))>(mv.zhongBitmap1.getWidth()/2.0-mv.zhongBitmap2.getWidth()/2.0)){//不在圆内return false;
}else{ //在圆内时
return true;
}
}
};
在传感器监听类中, onSensorChanged 方法用于监听传感器采样值的变化, 例如手机姿态的改变等。上述代码中的is-Contain 方法用于判断界面中间的气泡是否出界, 若出界则返回false.
完成了代码框架的开发后, 便可以对传感器的监听方法onSensorChanged 进行开发了, 其详细代码如下:
public void onSensorChanged(int sensor, float[] values){
if(sensor == SensorManager.SENSOR_ORIENTATION){
double pitch = values[SensorManager.DATA_Y];
double roll = values[SensorManager.DATA_Z];
int x=0; int y=0;//临时变量,算中间水泡坐标时用
int tempX=0; int tempY=0;//下面气泡的临时变量
//开始调整x 的值
if(Math.abs(roll)<=k){
mv.shang2_X = mv.shang1_X //上面的
+ (int)(((mv.shangBitmap1.getWidth()
-mv.shangBitmap2.getWidth())/2.0)
-(((mv.shangBitmap1.getWidth()
-mv.shangBitmap2.getWidth())/2.0)*roll)/k);
x = mv.zhong1_X //中间的
+ (int)(((mv.zhongBitmap1.getWidth()
-mv.zhongBitmap2.getWidth())/2.0)
-(((mv.zhongBitmap1.getWidth()
-mv.zhongBitmap2.getWidth())/2.0)*roll)/k);
}else if(roll>k){
mv.shang2_X=mv.shang1_X; x = mv.zhong1_X;
}else{
mv.shang2_X=mv.shang1_X+
mv.shangBitmap1.getWidth()
- mv.shangBitmap2.getWidth();
x = mv.zhong1_X+ mv.zhongBitmap1.getWidth()
- mv.zhongBitmap2.getWidth();
}
评论
查看更多