`
不夜的星辰
  • 浏览: 86937 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android 实现甩屏

阅读更多

最近要实现一个手机摇晃的功能。

想到这个功能可能应用广泛,比如摇晃手机换图片、截图、洗牌、结束当前程序等,所以找了些资料,并加以改进,将此功能封装成类(ShakeDetector),方便今后使用。

摇晃检测基于加速传感器(Sensor.TYPE_ACCELEROMETER)。

由于重力的存在,当手机静止放于桌面时,加速传感器也是有加速度的。所以,仅通过是否有加速度来判断摇晃是不行的。

那么,判断加速度的变化吧。在一个较短的时间间隔求出加速度的差值,跟一个指定的阈值比较,如果差值大于阈值,则认为是摇晃发生了。ClingMarks的方法将x、y、z方向的加速度差值简单的加起来,我认为不是很准确。

加速度是向量,求差应该是各方向的差值平方后相加,再开方。(数学忘光了,应该没记错吧。)

所以就有了这行代码:

1
float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / diffTime * 10000;

功能封装成类ShakeDetector,实现了SensorEventListener接口,用于向系统注册传感器事件的Listener。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package zhengzhiren.android.hardware;
  
import java.util.ArrayList;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.FloatMath;
  
/**
 * 用于检测手机晃动
 
 * @author 郑智仁
 */
public class ShakeDetector implements SensorEventListener {
    /**
     * 检测的时间间隔
     */
    static final int UPDATE_INTERVAL = 100;
    /**
     * 上一次检测的时间
     */
    long mLastUpdateTime;
    /**
     * 上一次检测时,加速度在x、y、z方向上的分量,用于和当前加速度比较求差。
     */
    float mLastX, mLastY, mLastZ;
    Context mContext;
    SensorManager mSensorManager;
    ArrayList<OnShakeListener> mListeners;
    /**
     * 摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感。
     */
    public int shakeThreshold = 5000;
  
    public ShakeDetector(Context context) {
        mContext = context;
        mSensorManager = (SensorManager) context
                .getSystemService(Context.SENSOR_SERVICE);
        mListeners = new ArrayList<OnShakeListener>();
    }
  
    /**
     * 当摇晃事件发生时,接收通知
     */
    public interface OnShakeListener {
        /**
         * 当手机晃动时被调用
         */
        void onShake();
    }
  
    /**
     * 注册OnShakeListener,当摇晃时接收通知
     
     * @param listener
     */
    public void registerOnShakeListener(OnShakeListener listener) {
        if (mListeners.contains(listener))
            return;
        mListeners.add(listener);
    }
  
    /**
     * 移除已经注册的OnShakeListener
     
     * @param listener
     */
    public void unregisterOnShakeListener(OnShakeListener listener) {
        mListeners.remove(listener);
    }
  
    /**
     * 启动摇晃检测
     */
    public void start() {
        if (mSensorManager == null) {
            throw new UnsupportedOperationException();
        }
        Sensor sensor = mSensorManager
                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (sensor == null) {
            throw new UnsupportedOperationException();
        }
        boolean success = mSensorManager.registerListener(this, sensor,
                SensorManager.SENSOR_DELAY_GAME);
        if (!success) {
            throw new UnsupportedOperationException();
        }
    }
  
    /**
     * 停止摇晃检测
     */
    public void stop() {
        if (mSensorManager != null)
            mSensorManager.unregisterListener(this);
    }
  
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
    }
  
    @Override
    public void onSensorChanged(SensorEvent event) {
        long currentTime = System.currentTimeMillis();
        long diffTime = currentTime - mLastUpdateTime;
        if (diffTime < UPDATE_INTERVAL)
            return;
        mLastUpdateTime = currentTime;
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];
        float deltaX = x - mLastX;
        float deltaY = y - mLastY;
        float deltaZ = z - mLastZ;
        mLastX = x;
        mLastY = y;
        mLastZ = z;
        float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ
                * deltaZ)
                / diffTime * 10000;
        if (delta > shakeThreshold) { // 当加速度的差值大于指定的阈值,认为这是一个摇晃
            this.notifyListeners();
        }
    }
  
    /**
     * 当摇晃事件发生时,通知所有的listener
     */
    private void notifyListeners() {
        for (OnShakeListener listener : mListeners) {
            listener.onShake();
        }
    }
}

如何使用ShakeDetector

1、new一个ShakeDetector
2、调用mShakeDetector.registerOnShakeListener()注册一个OnShakeListener
3、在OnShakeListener的onShake函数中,处理摇晃事件
4、调用mShakeDetector.start()启动摇晃检测
5、mShakeDetector.stop()用于停止摇晃检测

参考资料:
http://www.clingmarks.com/?p=25
http://android.hlidskialf.com/blog/code/android-shake-detection-listener

 

注:此文转载

分享到:
评论

相关推荐

    Google Android SDK开发范例大全(PDF高清完整版1)(4-1)

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK开发范例大全(PDF完整版4)(4-4)

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK开发范例大全(PDF高清完整版3)(4-3)

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK开发范例大全的目录

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK开发范例大全(完整版附部分源码).pdf

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——...

    Google Android SDK 开发范例大全01

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK 开发范例大全02

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google+Android+SDK开发范例大全

    ——具选择功能的对话框 3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给...

    Google Android sdk 开发范例大全 部分章节代码

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

    Google Android SDK开发范例大全(完整版)

    3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast...

Global site tag (gtag.js) - Google Analytics