Android摇一摇功能实现(摇一摇监听)
16lz
2021-01-23
近期项目中要求增加摇一摇功能,搜了相关帖子,自己整理一套代码,发个博客保留一份。
解析: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); }
更多相关文章
- android xml之动画篇 alpha、scale、translate、rotate、set的属
- Android三种动画的实现
- android Animation动画的xml使用
- Android 动画之Tween动画详细讲解及java源码实现
- Android属性动画—实现第三方登录的上拉展开,下拉隐藏
- android 动画系列 - 目录