Android 传感器实现水平仪效果

这两天公司项目需要效果是实现水平仪效果,从网上查了查,也找了一些储备,虽然达到了要求,但是有点不足,和我需求不符合,就是当小球转到边缘的时候,小球会在边缘不动,于是就改了改,完美达到了我的要求,不管你手机怎么转,小球始终在大圆里面,超过边缘的时候,也是在边缘滚动哦,特在此记录,有需要的可供参考,废话不多说,下面直接上代码了:

还是要声明下,这是本人第一篇博客,写的不好,勿怪

呃,自己要提前准备两张图片哦,一张是小球的,一张是小球的背景画布

实现的效果如下


1、首先定义传感器变量

  private Sensor gyroSensor = null;
2、在onCreat里面初始化传感器
//初始化方向传感器
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

3、在onResume里面注册传感器

  @Override
    protected void onResume() {
        super.onResume();
        if (null != sensorManager || null != gyroSensor) {
            sensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_GAME); //为传感器注册监听器
        }
    }
4、onPause里面要暂停传感器
@Override
    protected void onPause() {
        // 取消方向传感器的监听
        if (null != sensorManager) {
            sensorManager.unregisterListener(this);
        }
        super.onPause();
    }

5、编写PlaneView,这个就是水平仪的控件,这个是从网上摘抄的,不懂可以直接搜android 水平仪实现,一定有的

public class PlaneView extends View {
    // 定义水平仪仪表盘图片
    public Bitmap back;
    // 定义水平仪中的气泡图标
    public Bitmap bubble;
    // 定义水平仪中气泡 的X、Y座标
    public float bubbleX, bubbleY;

    public PlaneView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 加载水平仪图片和气泡图片
        back = BitmapFactory.decodeResource(getResources(), R.mipmap.plane);
        bubble = BitmapFactory.decodeResource(getResources(), R.mipmap.bubble);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制水平仪表盘图片
        canvas.drawBitmap(back, 0, 0, null);
        // 根据气泡座标绘制气泡
        canvas.drawBitmap(bubble, bubbleX, bubbleY, null);
    }
}

6、下面就是将控件放到你的Activity布局中去,我的是MainActivity,布局android_main.xml

        <!-宽高在这里设定,具体根据你个人项目需求->         
        <RelativeLayout
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="25dp">

            <cn.leadpcom.com.underparking.common.PlaneView
                android:id="@+id/pv_bubble"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </RelativeLayout>

7、下面就是具体在传感器接收到数据之后的操作了,里面的pv_bubble是我的控件名,大家应该懂得,转换成你个人设定的就行,呃,实在不懂,我也没有办法啊,就是这里面的逻辑和网上不同,希望大家注意哦,大家是不是在想MAX_ANGLE在哪里,是什么,哈哈,这个是定义的变量,就是角度,越小,小球就越灵敏

private int MAX_ANGLE = 10;//具体多大,自己尝试下就行了
 @Override
    public void onSensorChanged(SensorEvent event) {
        float[] values = event.values;
        // 获取触发event的传感器类型就
        int sensorType = event.sensor.getType();
        switch (sensorType) {
            case Sensor.TYPE_ORIENTATION:
                // 获取与Y轴的夹角
                float yAngle = values[1];
                // 获取与Z轴的夹角
                float zAngle = values[2];
                // 气泡位于中间时(水平仪完全水平),气泡的X、Y座标
                int x = (pv_bubble.back.getWidth() - pv_bubble.bubble.getWidth()) / 2;
                int y = (pv_bubble.back.getHeight() - pv_bubble.bubble.getHeight()) / 2;
                // 根据与Z轴的倾斜角度计算X座标的变化值(倾斜角度越大,X座标变化越大)
                int deltaX = (int) ((pv_bubble.back.getWidth() - pv_bubble.bubble.getWidth()) / 2 * zAngle / MAX_ANGLE);
                x += deltaX;
                // 根据与Y轴的倾斜角度计算Y座标的变化值(倾斜角度越大,Y座标变化越大)
                int deltaY = (int) ((pv_bubble.back.getHeight() - pv_bubble.bubble.getHeight()) / 2 * yAngle / MAX_ANGLE);
                y += deltaY;
                // 如果计算出来的X、Y座标还位于水平仪的仪表盘内,更新水平仪的气泡座标
                float aa = (float) Math.sqrt((x - (pv_bubble.back.getHeight() / 2 - pv_bubble.bubble.getHeight() / 2)) * (x - (pv_bubble.back.getHeight() / 2 - pv_bubble.bubble.getHeight() / 2)) + (y - (pv_bubble.back.getHeight() / 2 - pv_bubble.bubble.getHeight() / 2)) * (y - (pv_bubble.back.getHeight() / 2 - pv_bubble.bubble.getHeight() / 2)));
                if (aa < pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)) {
                    pv_bubble.bubbleX = x;
                    pv_bubble.bubbleY = y;
                } else {
                    float newx = (float) ((pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)) * (x - (pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)))) / aa + ((pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)));
                    float newy = (float) ((pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)) * (y - (pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)))) / aa + ((pv_bubble.back.getHeight() / 2 - (pv_bubble.bubble.getHeight() / 2)));
                    pv_bubble.bubbleX = newx;
                    pv_bubble.bubbleY = newy;
                }
                // 通知系统重回MyView组件
                pv_bubble.postInvalidate();
                break;
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }


8、好了,只要按照上面的说的,应该就能完美实现了,小球一直在画布里面的哦!~!~!~!~!有需要的,参考下,大神还请给出点评,我会继续更新改正,上面部分是摘抄,别的部分是原创,如有雷同,纯属巧合!~!~!~!~!~!








©️2020 CSDN 皮肤主题: 护眼 设计师:闪电赇 返回首页