Android 微信摇一摇功能实现详细介绍

Android 微信摇一摇功能实现,最近学习传感器,就想实现摇一摇的功能,上网查了些资料,就整理下。如有错误,还请指正。

开发环境

  1. Android Studio 2.2.1
  2. JDK1.7
  3. API 24
  4. Gradle 2.2.1

相关知识点

  1. 加速度传感器
  2. 补间动画
  3. 手机震动 (Vibrator)
  4. 较短 声音/音效 的播放 (SoundPool)

案例:

我们接下来分析一下这个案例, 当用户晃动手机时, 会触发加速传感器, 此时加速传感器会调用相应接口供我们使用, 此时我们可以做一些相应的动画效果, 震动效果和声音效果. 大致思路就是这样. 具体功能点:

用户晃动后两张图片分开, 显示后面图片
晃动后伴随震动效果, 声音效果

根据以上的简单分析, 我们就知道该怎么做了, Just now

先搭建布局

布局没啥可说的, 大家直接看代码吧

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/activity_main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ff222222"
  android:orientation="vertical"
  tools:context="com.lulu.weichatshake.MainActivity">
  <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--摇一摇中心图片-->
    <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:src="@mipmap/weichat_icon"/>
    <LinearLayout
      android:gravity="center"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_alignParentTop="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true">
      <!--顶部的横线和图片-->
      <LinearLayout
        android:gravity="center_horizontal|bottom"
        android:id="@+id/main_linear_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
          android:src="@mipmap/shake_top"
          android:id="@+id/main_shake_top"
          android:layout_width="wrap_content"
          android:layout_height="100dp"/>
        <ImageView
          android:background="@mipmap/shake_top_line"
          android:id="@+id/main_shake_top_line"
          android:layout_width="match_parent"
          android:layout_height="5dp"/>
      </LinearLayout>
      <!--底部的横线和图片-->
      <LinearLayout
        android:gravity="center_horizontal|bottom"
        android:id="@+id/main_linear_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
          android:background="@mipmap/shake_bottom_line"
          android:id="@+id/main_shake_bottom_line"
          android:layout_width="match_parent"
          android:layout_height="5dp"/>
        <ImageView
          android:src="@mipmap/shake_bottom"
          android:id="@+id/main_shake_bottom"
          android:layout_width="wrap_content"
          android:layout_height="100dp"/>
      </LinearLayout>
    </LinearLayout>
  </RelativeLayout>
</LinearLayout>

得到加速度传感器的回调接口

step1: 在onStart() 方法中获取传感器的SensorManager

@Override
protected void onStart() {
  super.onStart();
  //获取 SensorManager 负责管理传感器
  mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
  if (mSensorManager != null) {
    //获取加速度传感器
    mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    if (mAccelerometerSensor != null) {
      mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_UI);
    }
  }
}

step2: 紧接着我们就要在Pause中注销传感器

@Override
protected void onPause() {
  // 务必要在pause中注销 mSensorManager
  // 否则会造成界面退出后摇一摇依旧生效的bug
  if (mSensorManager != null) {
    mSensorManager.unregisterListener(this);
  }
  super.onPause();
}

Note: 至于为什么我们要在onStart和onPause中就行SensorManager的注册和注销, 就是因为, 防止在界面退出(包括按Home键)时, 摇一摇依旧生效(代码中有注释)

step3: 在step1中的注册监听事件方法中, 我们传入了当前Activity对象, 故让其实现回调接口, 得到以下方法

///////////////////////////////////////////////////////////////////////////
// SensorEventListener回调方法
///////////////////////////////////////////////////////////////////////////
@Override
public void onSensorChanged(SensorEvent event) {
  int type = event.sensor.getType();

  if (type == Sensor.TYPE_ACCELEROMETER) {
    //获取三个方向值
    float[] values = event.values;
    float x = values[0];
    float y = values[1];
    float z = values[2];

    if ((Math.abs(x) > 17 || Math.abs(y) > 17 || Math
        .abs(z) > 17) && !isShake) {
      isShake = true;
      // TODO: 2016/10/19 实现摇动逻辑, 摇动后进行震动
      Thread thread = new Thread() {
        @Override
        public void run() {
          super.run();
          try {
            Log.d(TAG, "onSensorChanged: 摇动");

            //开始震动 发出提示音 展示动画效果
            mHandler.obtainMessage(START_SHAKE).sendToTarget();
            Thread.sleep(500);
            //再来一次震动提示
            mHandler.obtainMessage(AGAIN_SHAKE).sendToTarget();
            Thread.sleep(500);
            mHandler.obtainMessage(END_SHAKE).sendToTarget();

          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      };
      thread.start();
    }
  }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

Note: 当用户晃动手机会调用onSensorChanged方法, 可以做一些相应的操作

为解决动画和震动延迟, 我们开启了一个子线程来实现.

子线程中会通过发送Handler消息, 先开始动画效果, 并伴随震动和声音 ,先把Handler的实现放一放, 我们再来看一下震动和声音初始化动画, 震动和音效实现

step 1: 先获取到震动相关的服务,注意要加权限. 至于音效, 我们采用SoundPool来播放, 在这里非常感谢Vincent 的贴子, 好初始化SoundPool

震动权限

<uses-permission android:name="android.permission.VIBRATE"/>

//初始化SoundPool
mSoundPool = new SoundPool(1, AudioManager.STREAM_SYSTEM, 5);
mWeiChatAudio = mSoundPool.load(this, R.raw.weichat_audio, 1);

//获取Vibrator震动服务
mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);

Note: 大家可能发现SoundPool的构造方法已经过时, 不过不用担心这是Api21之后过时的, 所以也不算太”过时”吧  

step2: 接下来我们就要介绍Handler中的实现了, 为避免Activity内存泄漏, 采用了软引用方式

private static class MyHandler extends Handler {
  private WeakReference<MainActivity> mReference;
  private MainActivity mActivity;
  public MyHandler(MainActivity activity) {
    mReference = new WeakReference<MainActivity>(activity);
    if (mReference != null) {
      mActivity = mReference.get();
    }
  }
  @Override
  public void handleMessage(Message msg) {
    super.handleMessage(msg);
    switch (msg.what) {
      case START_SHAKE:
        //This method requires the caller to hold the permission VIBRATE.
        mActivity.mVibrator.vibrate(300);
        //发出提示音
        mActivity.mSoundPool.play(mActivity.mWeiChatAudio, 1, 1, 0, 0, 1);
        mActivity.mTopLine.setVisibility(View.VISIBLE);
        mActivity.mBottomLine.setVisibility(View.VISIBLE);
        mActivity.startAnimation(false);//参数含义: (不是回来) 也就是说两张图片分散开的动画
        break;
      case AGAIN_SHAKE:
        mActivity.mVibrator.vibrate(300);
        break;
      case END_SHAKE:
        //整体效果结束, 将震动设置为false
        mActivity.isShake = false;
        // 展示上下两种图片回来的效果
        mActivity.startAnimation(true);
        break;
    }
  }
}

Note: 内容不多说了, 代码注释中很详细, 还有一个startAnimation方法
我先来说一下它的参数, true表示布局中两张图片从打开到关闭的动画, 反之, false是从关闭到打开状态, 上代码

step3: startAnimaion方法上的实现

/**
 * 开启 摇一摇动画
 *
 * @param isBack 是否是返回初识状态
 */
private void startAnimation(boolean isBack) {
  //动画坐标移动的位置的类型是相对自己的
  int type = Animation.RELATIVE_TO_SELF;

  float topFromY;
  float topToY;
  float bottomFromY;
  float bottomToY;
  if (isBack) {
    topFromY = -0.5f;
    topToY = 0;
    bottomFromY = 0.5f;
    bottomToY = 0;
  } else {
    topFromY = 0;
    topToY = -0.5f;
    bottomFromY = 0;
    bottomToY = 0.5f;
  }

  //上面图片的动画效果
  TranslateAnimation topAnim = new TranslateAnimation(
      type, 0, type, 0, type, topFromY, type, topToY
  );
  topAnim.setDuration(200);
  //动画终止时停留在最后一帧~不然会回到没有执行之前的状态
  topAnim.setFillAfter(true);

  //底部的动画效果
  TranslateAnimation bottomAnim = new TranslateAnimation(
      type, 0, type, 0, type, bottomFromY, type, bottomToY
  );
  bottomAnim.setDuration(200);
  bottomAnim.setFillAfter(true);

  //大家一定不要忘记, 当要回来时, 我们中间的两根线需要GONE掉
  if (isBack) {
    bottomAnim.setAnimationListener(new Animation.AnimationListener() {
      @Override
      public void onAnimationStart(Animation animation) {}
      @Override
      public void onAnimationRepeat(Animation animation) {}
      @Override
      public void onAnimationEnd(Animation animation) {
        //当动画结束后 , 将中间两条线GONE掉, 不让其占位
        mTopLine.setVisibility(View.GONE);
        mBottomLine.setVisibility(View.GONE);
      }
    });
  }
  //设置动画
  mTopLayout.startAnimation(topAnim);
  mBottomLayout.startAnimation(bottomAnim);

}

至此 核心代码已经介绍完毕 , 但是还有部分小细节不得不提一下

细枝末节

大家要在初始化View之前将上下两条横线GONE掉, 用GONE是不占位的

mTopLine.setVisibility(View.GONE);
mBottomLine.setVisibility(View.GONE);

2.咱们的摇一摇最好是只竖屏 (毕竟我也没见过横屏的摇一摇), 加上下面代码

//设置只竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

完整代码

源码我已经发在了github上, 希望大家多多支持!

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 微信小程序 摇一摇抽奖简单实例实现代码

    微信小程序 摇一摇抽奖 微信小程序目录 为了更好的理解小程序和小程序开发,我们首先来看一下项目的目录. 首先看下根目录下的app.json的文件,可以看到在"pages"的数组里,里面配置了每个界面,且包含了每个界面文件的目录 我们接下来看一下page文件夹,可以看到每个页面需要包含两个文件,一个是js文件,是每个界面的入口,wxml的文件是每个界面的布局文件,wxss是样式文件. 接下来看一下logs文件夹,在logs文件夹中比index文件夹中多出了一个logs.json的文件,l

  • Android利用传感器仿微信摇一摇功能

    传感器 简单的介绍一下传感器: 就是设备用来感知周边环境变化的硬件. Android中的传感器包含在传感器框架中,属于android.hardware.*(硬件部分) 传感器框架主要包含四个部分: ① SensorManager:用来获取传感器的入口,它是一个系统的服务,还可以为传感器注册与取消注册监听 ② Sensor: 具体的传感器,包含了传感器的名字,类型,采样率 ③ SensorEvent:传感器事件,包含了传感器采集回来的数据,传感器的精度 ④ SensorEventListener:

  • 微信公众号 摇一摇周边功能开发

    ①申请开通摇一摇功能 申请开通摇一摇周边功能.成功提交申请请求后,工作人员会在三个工作日内完成审核.若审核不通过,可以重新提交申请请求.若是审核中,请耐心等待工作人员审核,在审核中状态不能再提交申请请求. 接口代码如下: http请求方式: POST(请使用https协议)https://api.weixin.qq.com/shakearound/account/register?access_token=ACCESS_TOKENPOST数据格式:json POST数据例子: { "name&q

  • Android利用传感器实现微信摇一摇功能

    本文实例为大家分享了Android微信摇一摇功能的实现方法,供大家参考,具体内容如下 import java.util.ArrayList; import java.util.List; import java.util.Random; import android.app.Activity; import android.app.Service; import android.content.res.Resources; import android.hardware.Sensor; impo

  • android 类似微信的摇一摇功能实现思路及代码

    复制代码 代码如下: package com.eboy.testyaoyiyao; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import

  • Android 微信小视频录制功能实现详细介绍

    Android 微信小视频录制功能 开发之前 这几天接触了一下和视频相关的控件, 所以, 继之前的微信摇一摇, 我想到了来实现一下微信小视频录制的功能, 它的功能点比较多, 我每天都抽出点时间来写写, 说实话, 有些东西还是比较费劲, 希望大家认真看看, 说得不对的地方还请大家在评论中指正. 废话不多说, 进入正题. 开发环境 最近刚更新的, 没更新的小伙伴们抓紧了 Android Studio 2.2.2 JDK1.7 API 24 Gradle 2.2.2 相关知识点 视频录制界面 Surf

  • Android微信右滑退出功能的实现代码

    先给大家展示下效果图,如果大家感觉效果不错,请参考实例代码, act2是Main2Activity,act3是Main3Activity 原理 滚动 首先我们知道每个Activity展示的内容一般都是DecorView去承载的,不知道的看下图,其中状态栏背景也包括在内: DecorView 所以我们第一步,只需要滚动DecorView内容或者平移DecorView就行了. 使上一个Activity可见 上面的Activity不可见其实是因为被当前Activity给挡住了.那问题来了. Q:为什么

  • 微信小程序父子组件通信详细介绍

    组件间的基本通信方式有以下几种: WXML 数据绑定:用于父组件向子组件的指定属性设置数据. 事件:用于子组件向父组件传递数据,可以传递任意数据. 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent() 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法. 父组件通过 properties 属性给子组件传递数据: // 父组件 home.wxml <search-input placeholderText="搜明星.达人">

  • Android 微信摇一摇功能实现详细介绍

    Android 微信摇一摇功能实现,最近学习传感器,就想实现摇一摇的功能,上网查了些资料,就整理下.如有错误,还请指正. 开发环境 Android Studio 2.2.1 JDK1.7 API 24 Gradle 2.2.1 相关知识点 加速度传感器 补间动画 手机震动 (Vibrator) 较短 声音/音效 的播放 (SoundPool) 案例: 我们接下来分析一下这个案例, 当用户晃动手机时, 会触发加速传感器, 此时加速传感器会调用相应接口供我们使用, 此时我们可以做一些相应的动画效果,

  • Java实现企业微信消息推送功能的详细步骤

    第一步:申请企业微信注册企业(链接:https://work.weixin.qq.com/nl/sem/registe?s=c&from=1011017189&bd_vid=11628667012427618020) 第二步:登录自己的企业微信找到应用管理———>添加应用 第三步:获取到应用的AgentId.Secret.企业id 第四步,准备代码编写: model层代码: package com.toone.itop.formula.function.inte.model; /**

  • 微信 小程序开发环境搭建详细介绍

    微信小程序可谓是今天最火的一个名词了,一经出现真是轰炸了整个开发人员,当然很多App开发人员有了一个担心,微信小程序的到来会不会给移动端App带来一个寒冬,身为一个Android开发者我是不相信的,即使有,那也是很遥远的未来. 不管微信小程序是否能颠覆当今的开发格局,我们都要以好奇的心态去接收,去学习.不排斥新技术,所以,心动不如行动,赶紧先搭建一个微信小程序开发工具.那么接下来就让我们一起来开始吧. 先放一张Github上demo的动态图 开发工具下载是看到GitHub上的分享.那么你可以直接

  • Android 通过Intent使用Bundle传递对象详细介绍

    Android 通过Intent使用Bundle传递对象 Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法. 被传递的对象需要先实现序列化,而序列化对象有两种方式:java.io.Serializable和android.os.Parcelable Java中使用的是Serializable,而谷歌在Android使用了自定义的Parcelable. 两种序列化方式的区别: 1.在使用内存的时候,Parcelable比Serializa

  • 微信小程序 触控事件详细介绍

    微信小程序 触控事件: 微信小程序的"事件"挺有意思.看了说明文档后发现它的功能很全,事件可以向父节点传递,而且打印这个事件的信息很透明,调试起来应该非常方便. 接下来把文档copy过来 原文地址:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html >>>什么是事件 事件是视图层到逻辑层的通讯方式. 事件可以将用户的行为反馈到逻辑层进行处理. 事件可以绑定在组件上,当达到触发

  • Android中的广播(BroadCast)详细介绍

    什么是广播 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.我们拿广播电台来做个比方.我们平常使用收音机收音是这样的:许许多多不同的广播电台通过特定的频率来发送他们的内容,而我们用户只需要将频率调成和广播电台的一样就可以收听他们的内容了.Android中的广播机制就和这个差不多的道理. 电台发送的内容是语音,而在Android中我们要发送的广播内容是一个Intent.这个Intent中可以携带我们要传送的数据. 电台通过大功率的发射器发送内容,而在Androi

  • Android 常见的图片加载框架详细介绍

    Android 常见的图片加载框架 图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行图片加载. 开源框架的源码还是挺复杂的,但使用较为简单.大部分框架其实都差不多,配置稍微麻烦点,但是使用时一般只需要一行,显示方法一般会提供多个重载方法,支持不同需要.这样会减少很不必要的麻烦.同时,第三方框架的使用较为方便,这大大的减少了工作量.提高了开发效率.

随机推荐