在本文中,我们想探索另一种刷新应用程序UI的方法,称为Shake to Refresh 。 我们都知道在几个应用程序中实现的“从上到下”模式。 在这种模式下,我们沿着屏幕下拉手指,并刷新了UI:
即使此模式非常有用,我们也可以基于智能手机传感器使用另一种模式来刷新我们的UI,我们可以称其为Shake刷新 。 我们不用动动手指,而是摇动智能手机来刷新UI:
实作
为了使我们的应用程序支持摇动刷新功能,我们必须使用智能手机传感器,特别是运动传感器 :加速度计。 如果您想了解更多有关如何使用传感器的信息,可以在这里看看。
如前所述,我们希望用户摇动智能手机进行刷新,同时我们不希望刷新过程意外启动或用户只是移动智能手机而启动。 因此,我们必须实施一些控件以确保用户故意晃动智能手机。 另一方面,我们不想在处理UI的类中实现此逻辑,因为不建议将UI逻辑与其他事物混合使用,而使用另一个类,我们可以在其他上下文中重用此“模式” 。
然后,我们将创建另一个名为ShakeEventManager
类。 此类必须侦听传感器事件:
public class ShakeEventManager implements SensorEventListener {
..
}
这样它将实现SensorEventListener 。 然后,我们必须寻找加速度传感器,并将我们的课程注册为事件监听器:
public void init(Context ctx) {
sManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
s = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
register();
}
然后:
public void register() {
sManager.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
}
要在UI上触发刷新事件,必须验证一些条件,这些条件可确保用户故意晃动他的智能手机。 条件是:
- 加速度必须大于阈值水平
- 必须发生固定数量的加速事件
- 这些事件之间的时间必须在固定的时间窗口内
我们将在每次有新值可用时调用onSensorChanged
方法中实现此逻辑。 第一步是计算加速度,我们想知道三个轴上的最大加速度值,并希望从重力中清除传感器值。 因此,如Android官方文档中所述,我们首先应用低通滤波器来隔离重力,然后再应用高通滤波器:
private float calcMaxAcceleration(SensorEvent event) {
gravity[0] = calcGravityForce(event.values[0], 0);
gravity[1] = calcGravityForce(event.values[1], 1);
gravity[2] = calcGravityForce(event.values[2], 2);
float accX = event.values[0] - gravity[0];
float accY = event.values[1] - gravity[1];
float accZ = event.values[2] - gravity[2];
float max1 = Math.max(accX, accY);
return Math.max(max1, accZ);
}
哪里
// Low pass filter
private float calcGravityForce(float currentVal, int index) {
return ALPHA * gravity[index] + (1 - ALPHA) * currentVal;
}
一旦知道最大加速度,便实现我们的逻辑:
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
float maxAcc = calcMaxAcceleration(sensorEvent);
Log.d("SwA", "Max Acc ["+maxAcc+"]");
if (maxAcc >= MOV_THRESHOLD) {
if (counter == 0) {
counter++;
firstMovTime = System.currentTimeMillis();
Log.d("SwA", "First mov..");
} else {
long now = System.currentTimeMillis();
if ((now - firstMovTime) < SHAKE_WINDOW_TIME_INTERVAL)
counter++;
else {
resetAllData();
counter++;
return;
}
Log.d("SwA", "Mov counter ["+counter+"]");
if (counter >= MOV_COUNTS)
if (listener != null)
listener.onShake();
}
}
}
分析第3行的代码,我们简单地计算出加速度,然后检查加速度是否大于阈值(条件1)(第5行)。 如果是第一个动作(第7-8行),我们将保存时间戳以检查是否在指定的时间范围内发生了其他事件。 如果满足所有条件,则在回调接口中调用一个回调方法定义:
public static interface ShakeListener {
public void onShake();
}
测试应用
现在,我们已经实现了震动事件管理器,我们准备创建一个使用它的简单应用程序。 我们可以使用ListView创建一个简单的活动,当震动事件发生时会刷新该活动:
public class MainActivity extends ActionBarActivity implements ShakeEventManager.ShakeListener {
....
@Override
public void onShake() {
// We update the ListView
}
}
在第5行的位置,我们更新了UI,因为仅当用户摇动智能手机时才调用此方法。
最后一些注意事项:暂停应用程序时,我们必须注销传感器侦听器,以使其不再侦听事件,并以此节省电池。 另一方面,当应用恢复时,我们将再次注册侦听器:
Override
protected void onResume() {
super.onResume();
sd.register();
}
@Override
protected void onPause() {
super.onPause();
sd.deregister();
}
翻译自: https://www.javacodegeeks.com/2014/04/android-shake-to-refresh-tutorial.html