近期项目中要求增加摇一摇功能,搜了相关帖子,自己整理一套代码,发个博客保留一份。
解析:Android中摇一摇主要通过[SensorManager]实现,想了解可以查一下。
上期的不够完善 更新了一下,添加了防暴力摇动控制
public class ShakeService implements SensorEventListener {
private Context mContext;
private final MyHandler mHandler;
private static final int START_SHAKE = 0x1;
private static final int END_SHAKE = 0x2;
//传感器管理器
private SensorManager mSensorManager;
//检测的时间间隔
private static final int UPDATE_INTERVAL = 130;
//上一次检测的时间
private long mLastUpdateTime;
//上一次检测时,加速度在x、y、z方向上的分量,用于和当前加速度比较求差。
private float mLastX, mLastY, mLastZ;
//摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感。
private static final int shakeThreshold = 3800;
//记录摇动状态
private boolean isShake = false;
//动画
private Animation rotateAnimation, alphaAnimation, translateAnimation;
private static final int DURATION = 1000;
private static final int DURATION_STAR = 800;
public ShakeService(Context mContext) {
this.mContext = mContext;
mHandler = new MyHandler();
}
@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 =
(float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / diffTime * 10000);
// 当加速度的差值大于指定的阈值,认为这是一个摇晃
if (delta > shakeThreshold && !isShake) {
isShake = true;
Thread thread = new Thread() {
@Override
public void run() {
super.run();
try {
if (isValid()) {
mHandler.obtainMessage(START_SHAKE).sendToTarget();
}
//开始 展示动画效果
//Thread.sleep(100);
//再来一次提示
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
} else {
mHandler.obtainMessage(END_SHAKE).sendToTarget();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void start() {
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
//传感器
Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (mSensor != null) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);
}
}
}
public void Stop() {
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
//清空消息队列
mHandler.removeCallbacks(null);
//置位可摇一摇
isShake = false;
//关闭动画
}
if (rotateAnimation != null) {
rotateAnimation.cancel();
}
if (alphaAnimation != null) {
alphaAnimation.cancel();
}
if (translateAnimation != null) {
translateAnimation.cancel();
}
}
private static final long intervalAtMillis = 1000L;
private static long sLastTime;
public static boolean isValid() {
//防止暴力摇动
long currentTime = System.currentTimeMillis();
if (currentTime - sLastTime < intervalAtMillis) {
return false;
}
sLastTime = currentTime;
return true;
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case START_SHAKE:
//发出动画触发,执行动画
break;
case END_SHAKE:
isShake = false;
break;
}
}
}
//接口回调,摇一摇开始通知外部
public interface onStartListener {
void onStart();
}
public onStartListener startListener;
public void setStartListener(onStartListener startListener) {
this.startListener = startListener;
}
}
动画部分 根据需求编写哦
private void devilDialog() {
final CustomDialog dialog = new CustomDialog(mContext);
View view = LayoutInflater.from(mContext).inflate(R.layout.view_jackpot_shake, null);
dialog.setCanceledOnTouchOutside(false);
dialog.setContentView(view);
dialog.show();
ImageView devilFish = view.findViewById(R.id.iv_devilFish);
ImageView background = view.findViewById(R.id.iv_background);
ImageView soccer = view.findViewById(R.id.iv_soccer);
ImageView star1 = view.findViewById(R.id.iv_star1);
ImageView star2 = view.findViewById(R.id.iv_star2);
ImageView star3 = view.findViewById(R.id.iv_star3);
rotateAnimation =
new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotateAnimation.setDuration(3000);
//rotateAnimation.setRepeatCount(Animation.INFINITE);
background.startAnimation(rotateAnimation);
rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束 关闭动画效果 通知外部摇一摇结束
if (startListener != null) {
startListener.onStart();
}
rotateAnimation.cancel();
alphaAnimation.cancel();
translateAnimation.cancel();
dialog.dismiss();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
//star闪烁
alphaAnimation = new AlphaAnimation(0.1f, 1.0f);
alphaAnimation.setDuration(DURATION_STAR);
alphaAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatMode(Animation.REVERSE);
star1.setAnimation(alphaAnimation);
star2.setAnimation(alphaAnimation);
star3.setAnimation(alphaAnimation);
//soccer弹跳
translateAnimation = new TranslateAnimation(0, 0, 0, 25);
translateAnimation.setDuration(DURATION);
translateAnimation.setInterpolator(new CycleInterpolator(Animation.INFINITE));
translateAnimation.setRepeatCount(Animation.INFINITE);
soccer.setAnimation(translateAnimation);
}