Android 摇一摇之双甩功能
Android 摇一摇之双甩功能
最近做一个摇一摇的功能 网上相关代码很多 但是这次的需求有点奇葩 要求是摇两次才生效
看起来好像很简单 但真正要做遇到的问题还是很多 时间限制 机型灵敏性 摇动的方式 弄了一周多 做出的效果算一般吧
原理介绍
其实就是加速度传感器的使用 开发传感器应用的步骤如下
1 调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取 SensorManager对象
SensorManager代表系统的传感器管理服务2 调用SensorManager的getDefaultSensor(int type)获取指定类型的传感器
3 在Activity的onResume()方法中调用SensorManager的registerListener()为指定传感器注册监听
程序通过实现监听器可获取传感器传回来的数据
registerListener(SensorEventListener listener, Sensor sensor, int rateUs)
listener 监听传感器事件的监听器 该监听需要实现SensorEventListener接口
sensor 传感器对象
rateUs 获取传感器数据的频率 支持4个频率值
SENSOR_DELAY_FASTEST 最快 延迟小 耗电
SENSOR_DELAY_GAME 适合游戏
SENSOR_DELAY_UI 正常频率
SENSOR_DELAY_NORMAL 省电 延迟大
上代码
public class AccelerometerTest extends Activity
implements SensorEventListener
{
// 定义系统的Sensor管理器
SensorManager sensorManager;
EditText etTxt1; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面上的文本框组件
etTxt1 = (EditText) findViewById(R.id.txt1);
// 获取系统的传感器管理服务
sensorManager = (SensorManager) getSystemService(
Context.SENSOR_SERVICE); //①
} @Override
protected void onResume()
{
super.onResume();
// 为系统的加速度传感器注册监听器
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME); //②
} @Override
protected void onStop()
{
// 取消注册
sensorManager.unregisterListener(this);
super.onStop();
} // 以下是实现SensorEventListener接口必须实现的方法
// 当传感器的值发生改变时回调该方法
@Override
public void onSensorChanged(SensorEvent event)
{
float[] values = event.values;
StringBuilder sb = new StringBuilder();
sb.append("X方向上的加速度:");
sb.append(values[0]);
sb.append("\nY方向上的加速度:");
sb.append(values[1]);
sb.append("\nZ方向上的加速度:");
sb.append(values[2]);
etTxt1.setText(sb.toString());
} // 当传感器精度改变时回调该方法。
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
}
<?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">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/tip" />
<EditText
android:id="@+id/txt1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:cursorVisible="false" />
</LinearLayout>
返回的三个值分别代表在X Y Z三个方向上的加速度
X轴沿屏幕向左
Y轴沿屏幕向上
Z轴垂直于屏幕向里
下面给出双甩功能的代码 主要原理是判断速度阀值 并加入时间限制
MainActivity
public class MainActivity extends Activity{
EditText etTxt1;
private ShakeListener mShakeListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etTxt1 = (EditText) findViewById(R.id.txt1);
}
@Override
protected void onResume() {
super.onResume();
//注册
mShakeListener = new ShakeListener(this);
mShakeListener.setOnShakeListener(new ShakeListener.OnShakeListener() {
@Override
public void onShake() {
Log.i("TAG", "震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动");
Vibrator vVi = (Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
vVi.vibrate(400);
StringBuilder sb = new StringBuilder();
sb.append(mShakeListener.getSpeed());
etTxt1.setText(sb.toString());
}
});
}
@Override
protected void onStop() {
super.onStop();
// 取消注册
mShakeListener.stop();
}
}
ShakeListener
public class ShakeListener implements SensorEventListener {
private Context mContext;
private Sensor sensor; // 传感器
private SensorManager sensorManager; // 传感器管理器
private OnShakeListener onShakeListener;
// 手机上一个位置时重力感应坐标
private float lastX;
private float lastY;
private float lastZ;
private double speed;
private long lastUpdateTime;
int UPTATE_INTERVAL_TIME = 70;// 两次检测的时间间隔
int SPEED_SHRESHOLD = 3000;// 速度阈值
// 双甩
int count = 0;
int timeSlice = 0; // 时间片
final int GET_SUCC = 0;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case GET_SUCC:
count = 0;
timeSlice = 0;
break;
}
}
};
public ShakeListener(Context mContext) {
super();
this.mContext = mContext;
start();
}
//开始
public void start() {
// 获得传感器管理器
sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
// 获得重力传感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
// 注册
if (sensor != null) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
//停止
public void stop() {
sensorManager.unregisterListener(this);
}
// 设置重力感应监听器
public void setOnShakeListener(OnShakeListener listener) {
onShakeListener = listener;
}
@Override
public void onSensorChanged(SensorEvent event) {
long currentUpdateTime = System.currentTimeMillis(); // 现在检测时间
long timeInterval = currentUpdateTime - lastUpdateTime; // 两次检测的时间间隔
if (timeInterval < UPTATE_INTERVAL_TIME) // 判断是否达到了检测时间间隔
return;
lastUpdateTime = currentUpdateTime; // 现在的时间变成last时间
float[] values = event.values;
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 获得x,y,z的变化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ;
// 将现在的坐标变成last坐标
lastX = x;
lastY = y;
lastZ = z;
speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * 10000 / timeInterval;
Log.i("TAG", "speed" + speed);
Log.i("TAG", "count---" + count);
Log.i("TAG", "timeSlice---" + timeSlice);
//限制两次摇动在1S的时间内
if (count == 1) {
timeSlice++;
if (timeSlice * UPTATE_INTERVAL_TIME > 1000) {
count = 0;
timeSlice = 0;
}
}
if (speed > SPEED_SHRESHOLD) {
Log.i("TAG", " 摇一摇---------------------------------------------------------------------------------------------------摇一摇");
count++;
if (count == 2) {
count = 0;
//如果两次触发在300毫秒之内 只能算一次
if (timeSlice * UPTATE_INTERVAL_TIME < 300) {
count = 1;
} else {
onShakeListener.onShake();
handler.removeMessages(GET_SUCC);
handler.sendEmptyMessageDelayed(GET_SUCC, 300);
}
timeSlice = 0;
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public interface OnShakeListener {
public void onShake();
}
public double getSpeed() {
return speed;
}
}
activity_main
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.accelerometertest.MainActivity" > <EditText
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> </RelativeLayout>
加速度传感器Demo https://github.com/huanyi0723/Accelerometer/
双甩功能Demo https://github.com/huanyi0723/AccelerometerTest/
Android 摇一摇之双甩功能的更多相关文章
- Android仿iPhone晃动撤销输入功能(微信摇一摇功能)
重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内 ...
- android 实现摇一摇功能
实现“摇一摇”功能,其实很简单,就是检测手机的重力感应,具体实现代码如下: 一.在 AndroidManifest.xml 中添加操作权限 二.实现代码 package com.xs.test; im ...
- android 摇一摇功能的实现
将这个功能封装成了一个类,这样今后方便调用 package com.bobo.myyaoyiyaotest; import android.R.bool; import android.content ...
- Android 摇一摇功能的注意事项
/**开始重力传感器的检测*/ public void start() { // 获得传感器管理器 sensorManager = (SensorManager) mContext.getSystem ...
- Android 使用加速度传感器实现摇一摇功能及优化
如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 目前很多应用已经实现了摇一摇功能,这里通过讲解该功能的原理及实现回顾一下加速度传感器的使用: 1.首先获得 ...
- 【WP开发】实现“摇一摇”功能
尽管我的微信是每八个月登录一次,但我相信各位玩得比我多.微信有一个“摇一摇”功能,这个功能其实是利用了加速度传感器来实现的,这个传感器,我估计再低端的手机都会有的,这是严重基本的传感器. 重力加速度既 ...
- 利用HTML5的一个重要特性 —— DeviceOrientation来实现手机网站上的摇一摇功能
介绍之前做两个声明: 以下代码可以直接运行,当然你别忘了引用jQuery才行. <script> // DeviceOrientation将底层的方向传感器和运动传感器进行了高级封装, ...
- html5实现微信摇一摇功能
在HTML5中,DeviceOrientation特性所提供的DeviceMotion事件封装了设备的运动传感器时间,通过改时间可以获取设备的运动状态.加速度等数据(另还有deviceOrientat ...
- 用HTML5实现手机摇一摇的功能(转)
在百度开发者大会上我介绍过HTML5另外一个重要特性就是DeviceOrientation,它将底层的方向传感器和运动传感器进行了高级封装,提供了DOM事件的支持.这个特性包括两种事件: 1.devi ...
随机推荐
- 关于iframe嵌套、动态获取iframe内的url、父页面重定向
1 $(function () { 2 //选择器是选择了easyui中的点击链接,出现新的iframe 3 $("a[target='mainFrame']").click(fu ...
- handler以及AnyscTask处理机制
1.Handler 主文件:MainActivity.java package com.example.asynctaskdownload; import java.io.IOException; i ...
- 第十二届浙江省大学生程序设计大赛-May Day Holiday 分类: 比赛 2015-06-26 14:33 10人阅读 评论(0) 收藏
May Day Holiday Time Limit: 2 Seconds Memory Limit: 65536 KB As a university advocating self-learnin ...
- python Flask restful框架
框架地址:https://github.com/flask-restful/flask-restful 文档:http://flask-restful.readthedocs.io/en/0.3.5/ ...
- JavaScript获取元素尺寸和大小操作总结
一.获取元素的行内样式 复制代码 代码如下: var obj = document.getElementById("test"); alert(obj.height + " ...
- #ifdef DEBUG的理解
今天看到一段代码,对ifdef的概念比较模糊,于是去学习了一下,找到一个很好的解释,如下: 在工程设置里有一些设置会对该工程自动产生一系列的宏,用以控制程序的编译和运行.就好象楼上说的一样,如果你把代 ...
- 2016年11月20日 星期日 --出埃及记 Exodus 20:11
2016年11月20日 星期日 --出埃及记 Exodus 20:11 For in six days the LORD made the heavens and the earth, the sea ...
- Bootstrap_基本HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- C# Eval()和Bind()
Eval( " ")和Bind( " ") 这两种一个单向绑定,一个双向绑定,bind是双向绑定,但需数据源支持ASP.NET 2.0改善了模板中的数据绑定 ...
- C#其他
1.switch - if ...else if...switch(表达式) { case 值: ..... break; case 值: ..... break; default: ..... br ...