現(xiàn)在有不少的應(yīng)用開始實(shí)現(xiàn)了搖一搖功能秦士,今天就把搖一搖的實(shí)現(xiàn)過程做一下記錄熟空。
用到知識(shí)點(diǎn)
1.加速度傳感器
2.補(bǔ)間動(dòng)畫
3.手機(jī)震動(dòng) (Vibrator)
4.較短 聲音/音效 的播放 (SoundPool)
首先布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/shake_bg"
android:gravity="center"
android:orientation="vertical" >
<!-- 手掌展開后里面的圖片 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="260dp"
android:background="@color/shake_flower_bg"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/shake_flower"
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="@drawable/shake_flower_img" />
</LinearLayout>
<LinearLayout
android:id="@+id/shake_loading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/shakeImgDown"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:layout_width="18dp"
android:layout_height="18dp"
android:indeterminateDuration="1100"
android:indeterminateDrawable="@drawable/progressbar_shake_loading"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在搜尋美好"
android:textSize="16dp"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginLeft="6dp"
android:textColor="@color/white" />
</LinearLayout>
<!-- 搖一搖的結(jié)果 -->
<RelativeLayout
android:id="@+id/shake_result_layout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_below="@+id/shakeImgDown"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="10dp"
android:background="@drawable/shake_result_bg"
android:gravity="center_vertical"
android:visibility="visible"
android:padding="@dimen/listitem_top" >
<ImageView
android:id="@+id/shake_result_img"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerVertical="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/layout_padding"
android:layout_toRightOf="@id/shake_result_img"
android:gravity="center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/shake_result_txt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:gravity="center_vertical"
android:textSize="16dp"
android:textColor="@color/shake_reslut_txt_color" />
<TextView
android:id="@+id/shake_result_txt_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:gravity="center_vertical"
android:textColor="@color/shake_reslut_txt_color"
android:textSize="16dp" />
</LinearLayout>
</RelativeLayout>
<!-- 手掌頁面 -->
<RelativeLayout
android:id="@+id/shakeImgUp"
android:layout_width="match_parent"
android:layout_height="130dp"
android:background="@color/shake_bg" >
<ImageView
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/shake_logo_up" />
<LinearLayout
android:id="@+id/shakeImgUp_line"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_alignParentBottom="true"
android:background="@color/black"
android:visibility="gone" >
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_gravity="bottom"
android:background="@color/shake_line_bg" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/shakeImgDown"
android:layout_width="match_parent"
android:layout_height="130dp"
android:layout_below="@id/shakeImgUp"
android:background="@color/shake_bg" >
<ImageView
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="@drawable/shake_logo_down" />
<LinearLayout
android:id="@+id/shakeImgDown_line"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_alignParentTop="true"
android:background="@color/black"
android:visibility="gone" >
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_gravity="top"
android:background="@color/shake_line_bg" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
布局寫了好了就開始實(shí)現(xiàn)搖一搖功能了胧奔。
首先實(shí)現(xiàn)搖一搖的操作
public class ShakeListener implements SensorEventListener {
// 速度閾值矛市,當(dāng)搖晃速度達(dá)到這值后產(chǎn)生作用
private static final int SPEED_SHRESHOLD = 3000;
// 兩次檢測的時(shí)間間隔
private static final int UPTATE_INTERVAL_TIME = 70;
// 傳感器管理器
private SensorManager sensorManager;
// 傳感器
private Sensor sensor;
// 重力感應(yīng)監(jiān)聽器
private OnShakeListenerCallBack onShakeListener;
// 上下文
private Context mContext;
// 手機(jī)上一個(gè)位置時(shí)重力感應(yīng)坐標(biāo)
private float lastX;
private float lastY;
private float lastZ;
// 上次檢測時(shí)間
private long lastUpdateTime;
// 構(gòu)造器
public ShakeListener(Context context) {
// 獲得監(jiān)聽對(duì)象
mContext = context;
start();
}
/**開始重力傳感器的檢測*/
public void start() {
// 獲得傳感器管理器
sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
// 獲得重力傳感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
// 注冊
if (sensor != null) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
}
/**停止檢測*/
public void stop() {
sensorManager.unregisterListener(this);
}
/**重力感應(yīng)器感應(yīng)獲得變化數(shù)據(jù)*/
@Override
public void onSensorChanged(SensorEvent event) {
// 現(xiàn)在檢測時(shí)間
long currentUpdateTime = System.currentTimeMillis();
// 兩次檢測的時(shí)間間隔
long timeInterval = currentUpdateTime - lastUpdateTime;
// 判斷是否達(dá)到了檢測時(shí)間間隔
if (timeInterval < UPTATE_INTERVAL_TIME)
return;
// 現(xiàn)在的時(shí)間變成last時(shí)間
lastUpdateTime = currentUpdateTime;
// 獲得x,y,z坐標(biāo)
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 獲得x,y,z的變化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ;
// 將現(xiàn)在的坐標(biāo)變成last坐標(biāo)
lastX = x;
lastY = y;
lastZ = z;
double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeInterval * 10000;
// 達(dá)到速度閥值焦影,發(fā)出提示
if (speed >= SPEED_SHRESHOLD) {
onShakeListener.onShake();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**搖晃監(jiān)聽接口*/
public interface OnShakeListenerCallBack {
public void onShake();
}
/**設(shè)置重力感應(yīng)監(jiān)聽器*/
public void setOnShakeListener(OnShakeListenerCallBack listener) {
onShakeListener = listener;
}
}
首先獲取SensorManager宣增,進(jìn)而獲取到加速度傳感器玫膀,再設(shè)置監(jiān)聽器。然后在監(jiān)聽中根據(jù)傳感器數(shù)值的變化爹脾,根據(jù)需要做響應(yīng)的處理帖旨。當(dāng)達(dá)到要求時(shí)進(jìn)行回調(diào)箕昭,進(jìn)而實(shí)現(xiàn)搖一搖后響應(yīng)的邏輯(音效、動(dòng)畫等)解阅。
搖一搖完成后動(dòng)畫
/** 搖一搖手掌上部分動(dòng)畫 */
public AnimationSet getUpAnim(){
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation0 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-0.8f);
translateAnimation0.setDuration(OPEN_TIME);
translateAnimation0.setAnimationListener(openAnimationListner);//圖片上移動(dòng)畫監(jiān)聽
TranslateAnimation translateAnimation1 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0.8f);
translateAnimation1.setDuration(CLOSE_TIME);
translateAnimation1.setAnimationListener(closeAnimationListener);//圖片下移動(dòng)畫監(jiān)聽
translateAnimation1.setStartOffset(OFFSET_TIME);
translateAnimation1.setInterpolator(new AccelerateInterpolator(1));
animationSet.addAnimation(translateAnimation0);
animationSet.addAnimation(translateAnimation1);
return animationSet;
}
/** 搖一搖手掌下部分動(dòng)畫 */
public AnimationSet getDownAnim(){
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation0 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0.8f);
translateAnimation0.setDuration(OPEN_TIME);
translateAnimation0.setAnimationListener(openAnimationListner);//圖片上移動(dòng)畫監(jiān)聽
TranslateAnimation translateAnimation1 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-0.8f);
translateAnimation1.setDuration(CLOSE_TIME);
translateAnimation1.setAnimationListener(closeAnimationListener);//圖片下移動(dòng)畫監(jiān)聽
translateAnimation1.setStartOffset(OFFSET_TIME);
translateAnimation1.setInterpolator(new AccelerateInterpolator(1));
animationSet.addAnimation(translateAnimation0);
animationSet.addAnimation(translateAnimation1);
return animationSet;
}
/** 顯示搖出結(jié)果動(dòng)畫 */
public Animation getReusltAnim(){
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-1,Animation.RELATIVE_TO_SELF,0);
translateAnimation.setDuration(OPEN_TIME);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(SHAKE_RESULT_VISIBLE_CODE );
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return translateAnimation;
}
/** 隱藏?fù)u出結(jié)果動(dòng)畫 */
public Animation getReusltGoneAnim(){
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,3);
translateAnimation.setDuration(OPEN_TIME);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(SHAKE_RESULT_GONE_CODE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return translateAnimation;
}
/**手掌圖開啟動(dòng)畫監(jiān)聽*/
public Animation.AnimationListener openAnimationListner = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//動(dòng)畫開始執(zhí)行時(shí)回調(diào)
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimStart(OPEN_ANIM_CODE);
}
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
/**手掌圖合上動(dòng)畫監(jiān)聽*/
public Animation.AnimationListener closeAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//動(dòng)畫結(jié)束時(shí)回調(diào)
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(COLSE_ANIM_CODE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
public interface DoAnimationListener{
void onAnimStart(int code);
void onAnimEnd(int code);
}
震動(dòng)
震動(dòng)首先要加權(quán)限
<uses-permission android:name="android.permission.VIBRATE"/>
震動(dòng)代碼
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(500);
接下來就是播放音效了
public class Sound {
private static Sound mInstance;
private SoundPool mSoundPool;//音效池
private HashMap<Integer,Integer> mSoundPoolMap;//定義一個(gè)HashMap用于存放音頻流的ID
public static Sound getInstance() {
if (mInstance == null) {
mInstance = new Sound();
}
return mInstance;
}
/**初始化音效池---向音效池添加音效*/
public void initPool(final Context context){
mSoundPoolMap = new HashMap<>();
mSoundPool = new SoundPool(3, AudioManager.STREAM_ALARM,1);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes audioAttributes = null;
audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
mSoundPool = new SoundPool.Builder()
.setMaxStreams(3)
.setAudioAttributes(audioAttributes)
.build();
} else { // 5.0 以前
mSoundPool = new SoundPool(3, AudioManager.STREAM_ALARM, 0); // 創(chuàng)建SoundPool
}
new Thread(new Runnable() {
@Override
public void run() {
mSoundPoolMap.put(0,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_sound_male),1));
mSoundPoolMap.put(1,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_match),1));
mSoundPoolMap.put(2,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_nomatch),1));
}
}).start();
}
/** 播放搖一搖開始聲音 */
public void playStartSound(){
try {
mSoundPool.play(mSoundPoolMap.get(0),1,1,0,0,1.3f);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 播放搖一搖結(jié)束聲音 */
public void playEndSound(){
try {
mSoundPool.play(mSoundPoolMap.get(1),1,1,0,0,1.0f);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 什么都沒搖到 */
public void playNotingSound(){
try {
mSoundPool.play(mSoundPoolMap.get(2),1,1,0,0,1.0f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
首先定義一個(gè)音效池落竹,一個(gè)HashMap存放音效id,然后向音效池中添加音效货抄,在合適的時(shí)機(jī)播放對(duì)應(yīng)的音效述召。
以上幾個(gè)步驟實(shí)現(xiàn)整個(gè)搖一搖效果
最終代碼
動(dòng)畫部分
public class ShakeAnimation{
/**展開動(dòng)畫*/
public static final long OPEN_TIME = 500;
/**關(guān)合動(dòng)畫*/
public static final long CLOSE_TIME = 280;
/**開合動(dòng)畫間隔*/
public static final long OFFSET_TIME = 800;
/**模擬延遲*/
public static final long SIMULLATE_DELAY = 400;
public static final int OPEN_ANIM_CODE = 1;
public static final int COLSE_ANIM_CODE = 2;
public static final int SHAKE_RESULT_GONE_CODE = 3;
public static final int SHAKE_RESULT_VISIBLE_CODE = 4;
private static DoAnimationListener mDoAnimationListener;
private static ShakeAnimation needForAnim;
public static ShakeAnimation getInstance(DoAnimationListener doAnimationListener) {
mDoAnimationListener = doAnimationListener;
if (needForAnim == null) {
needForAnim = new ShakeAnimation();
}
return needForAnim;
}
/** 搖一搖手掌上部分動(dòng)畫 */
public AnimationSet getUpAnim(){
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation0 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-0.8f);
translateAnimation0.setDuration(OPEN_TIME);
translateAnimation0.setAnimationListener(openAnimationListner);//圖片上移動(dòng)畫監(jiān)聽
TranslateAnimation translateAnimation1 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0.8f);
translateAnimation1.setDuration(CLOSE_TIME);
translateAnimation1.setAnimationListener(closeAnimationListener);//圖片下移動(dòng)畫監(jiān)聽
translateAnimation1.setStartOffset(OFFSET_TIME);
translateAnimation1.setInterpolator(new AccelerateInterpolator(1));
animationSet.addAnimation(translateAnimation0);
animationSet.addAnimation(translateAnimation1);
return animationSet;
}
/** 搖一搖手掌下部分動(dòng)畫 */
public AnimationSet getDownAnim(){
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation0 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0.8f);
translateAnimation0.setDuration(OPEN_TIME);
translateAnimation0.setAnimationListener(openAnimationListner);//圖片上移動(dòng)畫監(jiān)聽
TranslateAnimation translateAnimation1 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-0.8f);
translateAnimation1.setDuration(CLOSE_TIME);
translateAnimation1.setAnimationListener(closeAnimationListener);//圖片下移動(dòng)畫監(jiān)聽
translateAnimation1.setStartOffset(OFFSET_TIME);
translateAnimation1.setInterpolator(new AccelerateInterpolator(1));
animationSet.addAnimation(translateAnimation0);
animationSet.addAnimation(translateAnimation1);
return animationSet;
}
/** 顯示搖出結(jié)果動(dòng)畫 */
public Animation getReusltAnim(){
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-1,Animation.RELATIVE_TO_SELF,0);
translateAnimation.setDuration(OPEN_TIME);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(SHAKE_RESULT_VISIBLE_CODE );
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return translateAnimation;
}
/** 隱藏?fù)u出結(jié)果動(dòng)畫 */
public Animation getReusltGoneAnim(){
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,3);
translateAnimation.setDuration(OPEN_TIME);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(SHAKE_RESULT_GONE_CODE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return translateAnimation;
}
/**手掌圖開啟動(dòng)畫監(jiān)聽*/
public Animation.AnimationListener openAnimationListner = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//動(dòng)畫開始執(zhí)行時(shí)回調(diào)
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimStart(OPEN_ANIM_CODE);
}
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
/**手掌圖合上動(dòng)畫監(jiān)聽*/
public Animation.AnimationListener closeAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//動(dòng)畫結(jié)束時(shí)回調(diào)
if (mDoAnimationListener != null) {
mDoAnimationListener.onAnimEnd(COLSE_ANIM_CODE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
public interface DoAnimationListener{
void onAnimStart(int code);
void onAnimEnd(int code);
}
}
音效部分
public class Sound {
private static Sound mInstance;
private SoundPool mSoundPool;//音效池
private HashMap<Integer,Integer> mSoundPoolMap;//定義一個(gè)HashMap用于存放音頻流的ID
public static Sound getInstance() {
if (mInstance == null) {
mInstance = new Sound();
}
return mInstance;
}
/**初始化音效池---向音效池添加音效*/
public void initPool(final Context context){
mSoundPoolMap = new HashMap<>();
mSoundPool = new SoundPool(3, AudioManager.STREAM_ALARM,1);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes audioAttributes = null;
audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
mSoundPool = new SoundPool.Builder()
.setMaxStreams(3)
.setAudioAttributes(audioAttributes)
.build();
} else { // 5.0 以前
mSoundPool = new SoundPool(3, AudioManager.STREAM_ALARM, 0); // 創(chuàng)建SoundPool
}
new Thread(new Runnable() {
@Override
public void run() {
mSoundPoolMap.put(0,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_sound_male),1));
mSoundPoolMap.put(1,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_match),1));
mSoundPoolMap.put(2,mSoundPool.load(context.getResources().openRawResourceFd(R.raw.shake_nomatch),1));
}
}).start();
}
/** 播放搖一搖開始聲音 */
public void playStartSound(){
try {
mSoundPool.play(mSoundPoolMap.get(0),1,1,0,0,1.3f);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 播放搖一搖結(jié)束聲音 */
public void playEndSound(){
try {
mSoundPool.play(mSoundPoolMap.get(1),1,1,0,0,1.0f);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 什么都沒搖到 */
public void playNotingSound(){
try {
mSoundPool.play(mSoundPoolMap.get(2),1,1,0,0,1.0f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
重力傳感器部分
public class ShakeListener implements SensorEventListener {
// 速度閾值,當(dāng)搖晃速度達(dá)到這值后產(chǎn)生作用
private static final int SPEED_SHRESHOLD = 3000;
// 兩次檢測的時(shí)間間隔
private static final int UPTATE_INTERVAL_TIME = 70;
// 傳感器管理器
private SensorManager sensorManager;
// 傳感器
private Sensor sensor;
// 重力感應(yīng)監(jiān)聽器
private OnShakeListenerCallBack onShakeListener;
// 上下文
private Context mContext;
// 手機(jī)上一個(gè)位置時(shí)重力感應(yīng)坐標(biāo)
private float lastX;
private float lastY;
private float lastZ;
// 上次檢測時(shí)間
private long lastUpdateTime;
// 構(gòu)造器
public ShakeListener(Context context) {
// 獲得監(jiān)聽對(duì)象
mContext = context;
start();
}
/**開始重力傳感器的檢測*/
public void start() {
// 獲得傳感器管理器
sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
// 獲得重力傳感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
// 注冊
if (sensor != null) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
}
/**停止檢測*/
public void stop() {
sensorManager.unregisterListener(this);
}
/**重力感應(yīng)器感應(yīng)獲得變化數(shù)據(jù)*/
@Override
public void onSensorChanged(SensorEvent event) {
// 現(xiàn)在檢測時(shí)間
long currentUpdateTime = System.currentTimeMillis();
// 兩次檢測的時(shí)間間隔
long timeInterval = currentUpdateTime - lastUpdateTime;
// 判斷是否達(dá)到了檢測時(shí)間間隔
if (timeInterval < UPTATE_INTERVAL_TIME)
return;
// 現(xiàn)在的時(shí)間變成last時(shí)間
lastUpdateTime = currentUpdateTime;
// 獲得x,y,z坐標(biāo)
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 獲得x,y,z的變化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ;
// 將現(xiàn)在的坐標(biāo)變成last坐標(biāo)
lastX = x;
lastY = y;
lastZ = z;
double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeInterval * 10000;
// 達(dá)到速度閥值蟹地,發(fā)出提示
if (speed >= SPEED_SHRESHOLD) {
// ToastUtils.showToast(mContext,"速度"+speed);
onShakeListener.onShake();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**搖晃監(jiān)聽接口*/
public interface OnShakeListenerCallBack {
public void onShake();
}
/**設(shè)置重力感應(yīng)監(jiān)聽器*/
public void setOnShakeListener(OnShakeListenerCallBack listener) {
onShakeListener = listener;
}
}
Activity部分
public class BActivity extends AppCompatActivity implements ShakeAnimation.DoAnimationListener {
@BindView(R.id.shake_flower)
ImageView mShakeFlower;
@BindView(R.id.shake_loading)
LinearLayout mShakeLoading;
@BindView(R.id.shake_result_img)
ImageView mShakeResultImg;
@BindView(R.id.shake_result_txt_name)
TextView mShakeResultTxtName;
@BindView(R.id.shake_result_txt_value)
TextView mShakeResultTxtValue;
@BindView(R.id.shake_result_layout)
RelativeLayout mShakeResultLayout;
@BindView(R.id.shakeImgUp_line)
LinearLayout mShakeImgUpLine;
@BindView(R.id.shakeImgUp)
RelativeLayout mShakeImgUp;
@BindView(R.id.shakeImgDown_line)
LinearLayout mShakeImgDownLine;
@BindView(R.id.shakeImgDown)
RelativeLayout mShakeImgDown;
private ShakeListener mShakeListener;
private ShakeAnimation mShakeAnimation;
private boolean hasReslut = false;
private int shakeNum = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shake_root);
ButterKnife.bind(this);
setResultVisible(false);//初始時(shí)不顯示結(jié)果
showShakeLoading(false);//初始時(shí)不顯示加載
initShake();
}
private void initShake() {
Sound.getInstance().initPool(this);
mShakeListener = new ShakeListener(this);
mShakeListener.setOnShakeListener(new ShakeListener.OnShakeListenerCallBack() {
@Override
public void onShake() {
startShake();//開始執(zhí)行動(dòng)畫
mShakeListener.stop();//取消搖動(dòng)監(jiān)聽,動(dòng)畫結(jié)束之前不再監(jiān)聽
vibrate(500);
Sound.getInstance().playStartSound();
}
});
}
/**
* 執(zhí)行動(dòng)畫
*/
private void startShake() {
mShakeAnimation = ShakeAnimation.getInstance(this);
mShakeImgDown.startAnimation(mShakeAnimation.getDownAnim());
mShakeImgUp.startAnimation(mShakeAnimation.getUpAnim());
if (mShakeResultLayout != null && mShakeResultLayout.getVisibility() == View.VISIBLE) {
showResultGoneAnim();
}
}
/**
* 搖出的結(jié)果顯示控制
*/
private void setResultVisible(boolean isVisible) {
if (mShakeResultLayout == null) {
return;
}
if (isVisible) {
mShakeResultLayout.setVisibility(View.VISIBLE);
} else {
mShakeResultLayout.setVisibility(View.INVISIBLE);
}
}
/**
* 正在加載
*/
private void showShakeLoading(boolean isShow) {
if (mShakeLoading == null) {
return;
}
if (isShow) {
mShakeLoading.setVisibility(View.VISIBLE);
} else {
mShakeLoading.setVisibility(View.GONE);
}
}
private void setResultView(){
showResultAnim();
if(!hasReslut){
mShakeResultImg.setImageResource(R.drawable.icon_sad_black);
mShakeResultTxtName.setText("什么都沒搖到");
mShakeResultTxtValue.setVisibility(View.GONE);
}else {
mShakeResultImg.setImageResource(R.drawable.a);
mShakeResultTxtName.setText("渾水摸魚");
mShakeResultTxtValue.setVisibility(View.VISIBLE);
mShakeResultTxtValue.setText("距離10公里");
}
playResultSound();
}
private void playResultSound(){
if(hasReslut){
Sound.getInstance().playEndSound();
}else {
Sound.getInstance().playNotingSound();
}
shakeNum++;
if(shakeNum%6==0){
hasReslut = !hasReslut;
}
}
/**
* 動(dòng)畫開啟
*/
@Override
public void onAnimStart(int code) {
switch (code) {
case ShakeAnimation.OPEN_ANIM_CODE:
setHandLineVisible(true);
break;
}
}
/**
* 動(dòng)畫結(jié)束
*/
@Override
public void onAnimEnd(int code) {
switch (code) {
case ShakeAnimation.COLSE_ANIM_CODE:
setHandLineVisible(false);//
setResultView();
//showResultAnim();//顯示結(jié)果
setResultVisible(true);
break;
case ShakeAnimation.SHAKE_RESULT_GONE_CODE:
setResultVisible(false);
break;
case ShakeAnimation.SHAKE_RESULT_VISIBLE_CODE:
mShakeListener.start();//動(dòng)畫結(jié)束了桨武,重新開始監(jiān)聽搖動(dòng)
break;
}
}
/**
* 手掌邊線顯示控制
*/
private void setHandLineVisible(boolean isVisible) {
if (mShakeImgUpLine != null) {
if (isVisible) {
mShakeImgUpLine.setVisibility(View.VISIBLE);
} else {
mShakeImgUpLine.setVisibility(View.GONE);
}
}
if (mShakeImgDownLine != null) {
if (isVisible) {
mShakeImgDownLine.setVisibility(View.VISIBLE);
} else {
mShakeImgDownLine.setVisibility(View.GONE);
}
}
}
/**顯示結(jié)果動(dòng)畫*/
private void showResultAnim() {
if (mShakeAnimation != null) {
mShakeResultLayout.setAnimation(mShakeAnimation.getReusltAnim());
}
}
/**顯示結(jié)果隱藏的動(dòng)畫*/
private void showResultGoneAnim(){
if (mShakeAnimation != null) {
mShakeResultLayout.setAnimation(mShakeAnimation.getReusltGoneAnim());
}
}
/**震動(dòng)*/
private void vibrate(long milliseconds){
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(500);
}
@Override
public void onResume() {
super.onResume();
mShakeListener.start();
}
@Override
public void onPause() {
mShakeListener.stop();
super.onPause();
}
@Override
public void onStop() {
mShakeListener.stop();
super.onStop();
}
}
代碼就寫到這塊了,基本實(shí)現(xiàn)了仿微信搖一搖功能锈津。
參考:https://www.cnblogs.com/wangyuehome/p/4608128.html