Android自定义控件实现手机摆放位置的校准

先上效果
当手机的摆放位置合适时
往左偏移
往上偏移

最近做的项目中的拍照模块要求拍照的时候手机是:
——竖直的
——面朝上的
——与地面的夹角为75°
基本上这个自定义控件就做了这样的一件事,如果手机的摆放位置符合上述条件,则会如图一所示,该控件中间的小圆显示在正中心的位置,整个控件是绿色的。
而如果摆放位置不符合条件,不是竖直的,夹角偏大偏小等,就会如图二图三所示,控件会变成红色而且中间的小圆也会做出对应的偏移提示用户当前应该往哪移动手机。

好,明白了需求就可以开始动工了,首先我们来温习一下自定义控件的基本知识。
自定义控件的基本步骤:
①新建一个类继承View。
②自定义属性,一个完美的自定义控件也可以添加xml来配置属性和风格。 要实现这一点,可按照下列步骤来做:
1) 添加自定义属性到xml文件中
2) 在xml的中,指定属性的值
3) 在view中获取xml中的值
4) 将获取的值应用到view中
③重写onMeasure(), onLayout(), onDraw(),方法(当然,简单一点的自定义控件只需要重写这几个就够了)。
④自定义监听器,选择合适的时机触发。

而手机的摆放位置信息我们可以使用手机的重力传感器来获得,图一中的X=。。。y=。。。z=。。。就是从手机的重力传感器获得的数据。

自定义控件GuideView所有代码:

package com.miser.sensordemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * 实现手机通过重力感应校准位置的自定义控件
 * Created by Administrator on 2016/4/7.
 */
public class GuideView extends View {
    private static final String TAG = "GuideView";
    private Sensor mSensor;
    private SensorManager mSensorManager;
    private int mViewWidth;
    private int mViewHeight;
    //外面圆的线条宽度(px)
    private float strokeWidth = 2;
    //小圆圆心坐标
    private float mChaildcy;
    private float mChaildcx;
    //里面圈圈的颜色,默认为红色
    private int mColor = Color.RED;


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

    public GuideView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        //得到SensorManager对象
        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        //获得重力感应传感器实例
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        //注册监听器
        mSensorManager.registerListener(mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_UI);
    }


    public GuideView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG, "onMeasure");
        mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
        mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(mViewWidth, mViewHeight);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG, "onLayout");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG, "onDraw");
        //画外面的大圆-----------------
        float cx = mViewWidth / 2;
        float cy = mViewHeight / 2;
        float radio = (mViewWidth > mViewHeight ? cx : cy) - strokeWidth;
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(mColor);
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(cx, cy, radio, paint);
        //----------------------------

        //画里面的小圆-----------------
        if ((mChaildcx > 0 && mChaildcx < mViewWidth)
                && (mChaildcy > 0 && mChaildcy < mViewHeight)) {
            canvas.drawCircle(mChaildcx, mChaildcy, radio / 3, paint);
        }
        //----------------------------
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.d(TAG, "onDetachedFromWindow");
        //取消重力感应的监听
        mSensorManager.unregisterListener(mSensorEventListener);
    }

    /**
     * 重力感应的监听器,可用来实时得到手机当前的位置信息
     */
    SensorEventListener mSensorEventListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
            float x = sensorEvent.values[SensorManager.DATA_X];
            float y = sensorEvent.values[SensorManager.DATA_Y];
            float z = sensorEvent.values[SensorManager.DATA_Z];
            mChaildcx = mViewWidth / 2 - x * mViewWidth / 20;
            if (z > 0) {
                mChaildcy = mViewHeight / 2 + ((y - 8.3333f) * mViewHeight / 20);
            } else {
                mChaildcy = mViewHeight / 2 - (z * mViewHeight / 20);
            }
            if ((x > -1 && x < 1)//手机竖屏度在合适范围内
                    && (y > 7.3F && y < 9.3)//倾斜15°范围内
                    && (z > 0)//手机是面朝上的
                    ) {
                mColor = Color.GREEN;
            } else {
                mColor = Color.RED;
            }
            postInvalidate();
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int i) {
        }
    };
}

有自定义控件的代码应该就可以了,这里就不上demo了,如有疑惑可私信或邮件 miqingtang@163.com

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

痕迹丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值