图呢,,,,,自己想想吧、、、、、、、画面很美。
package com.example.propertyanimsecdemo;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.sax.StartElementListener;
import android.util.Log;
import android.widget.TextView;
public class SensorManagerHelper implements SensorEventListener {
/**
* 上下文
*/
private Context mContext;
/**
* 传感器管理器
*/
private SensorManager mSensorManager;
/**
* 传感器
*/
private Sensor mSensor;
/**
* 手机上一个位置时重力感应坐标
*/
private float LX, LY, LZ;
/**
* 晃动监听
*/
private OnShakeListener mShakeListener;
/**
* 速度阈值,当摇晃速度达到这值后产生作用
*/
private static final int SPEED_SHRESHOLD = 5000;
/**
* 两次检测的时间间隔
*/
private static final int UPTATE_INTERVAL_TIME = 50;
/**
* 某轴上的速度s/t
*/
private static final int SPEED_XYZ = 500;
/**
* 上次晃动检测时间
*/
private long lastShakeTime;
public SensorManagerHelper(Context mContext) {
super();
this.mContext = mContext;
start();
}
public void start() {
// 获取传感器管理器
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
// 获取重力传感器
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
if (mSensor != null) {
// 注册listener,第三个参数是检测的精确度
// SENSOR_DELAY_FASTEST 最灵敏 因为太快了没必要使用
// SENSOR_DELAY_GAME 游戏开发中使用
// SENSOR_DELAY_NORMAL 正常速度
// SENSOR_DELAY_UI 最慢的速度
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI);
}
}
public void stop() {
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
long curShakeTime = System.currentTimeMillis();// 当前时间
long deltaT = curShakeTime - lastShakeTime;// 两次时间差
if (deltaT < UPTATE_INTERVAL_TIME) {
return;
}
lastShakeTime = curShakeTime;
// 获取当前x,y,z坐标
float CX = event.values[0];
float CY = event.values[1];
float CZ = event.values[2];
// 坐标差
float deltaX = CX - LX;
float deltaY = CY - LY;
float deltaZ = CZ - LZ;
LX = CX;
LY = CY;
LZ = CZ;
double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / deltaT * 10000;
// 达到速度阀值,发出提示
if (speed >= SPEED_SHRESHOLD)
mShakeListener.onShake();
if ((7<Math.abs(CX)&&Math.abs(CX)<10&&Math.abs(deltaX/deltaT*10000)>SPEED_XYZ)||(7<Math.abs(CY)&&Math.abs(CY)<10&&Math.abs(deltaY/deltaT*10000)>SPEED_XYZ)||(7<Math.abs(CZ)&&Math.abs(CZ)<10&&Math.abs(deltaZ/deltaT*10000)>SPEED_XYZ)) {
mShakeListener.onSensor();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
// 摇晃监听接口
public interface OnShakeListener {
/**
* 晃动监听回调
*/
public void onShake();
/**
* 重力监听回调
*/
public void onSensor();
}
/**
* 设置晃动监听
*
* @param mShakeListener
*/
public void setmShakeListener(OnShakeListener mShakeListener) {
this.mShakeListener = mShakeListener;
}
}
1、取得重力感应器Sensor对象
mSensorManager= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
2、创建监听器
mListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}public void onSensorChanged(SensorEvent event) {
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
doSomething(x, y, z);
}
};
3、注册监听器
mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
这里 SENSOR_DELAY_GAME 还可以是以下常量:
SENSOR_DELAY_FASTEST
SENSOR_DELAY_UI
SENSOR_DELAY_NORMAL
4、取消监听器
mSensorManager.unregisterListener(mListener);
5、添加当重力变化时的处理函数
当 手机倾斜方向改变时,监听器会调用该方法。
Android重力感应系统的坐标系
以屏幕的左下方为原点(2d编程的时候,是以屏幕左上方为原点的,这个值得注意一下),箭头指向的方向为正。从-10到10,以浮点数为等级单位,想象一下以下情形:
手机屏幕向上(z轴朝天)水平放置的时侯,(x,y,z)的值分别为(0,0,10);
手机屏幕向下(z轴朝地)水平放置的时侯,(x,y,z)的值分别为(0,0,-10);
手机屏幕向左侧放(x轴朝天)的时候,(x,y,z)的值分别为(10,0,0);
手机竖直(y轴朝天)向上的时候,(x,y,z)的值分别为(0,10,0);
其他的如此类推,规律就是:朝天的就是正数,朝地的就是负数。利用x,y,z三个值求三角函数,就可以精确检测手机 的运动状态了
我们要做的,就是填充该方法,用于在重力发生变化时进行我们自己的处理。
当 x=y=0 时, 手机处于水平放置状态。
当 x=0 并且 y>0 时, 手机顶部的水平位置要大于底部,也就是一般接听电话时手机所处的状态。
当 x=0 并且 y<0 时, 手机顶部的水平位置要小于底部。手机一般很少处于这种状态。
当 y=0 并且 x>0 时, 手机右侧的水平位置要大于左侧,也就是右侧被抬起。
当 y=0 并且 x<0 时, 手机右侧的水平位置要小于左侧,也就是左侧被抬起。
当 z=0 时, 手机平面与水平面垂直。
当 z>0 时, 手机屏幕朝上。
当 z<0 时, 手机屏幕朝下
package com.example.propertyanimsecdemo; import java.util.Random; import com.example.propertyanimsecdemo.SensorManagerHelper.OnShakeListener; import android.app.Activity; import android.graphics.Point; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.FrameLayout; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private FrameLayout mFrameLayout; private LayoutParams mParams; /** * 贝尔曲线数 */ private static final int BEZIER_COUNT = 20; /** * 4点决定三次贝尔曲线 */ private static final int POINT_COUNT = 4; /** * 添加树叶 */ private static final int LEAF = 1; /** * 添加元宝 */ private static final int YUANBAO = -1; /** * 树叶数 */ private static final int LEAF_COUNT = 6; /** * 移动物体元宝 */ private Button[] mViews = new Button[BEZIER_COUNT]; /** * 移动物体树叶 */ private Button[] mLeafs= new Button[LEAF_COUNT]; /** * 三次贝塞尔曲线起始点,2控制点,终点 */ private Point[] mPoints = new Point[POINT_COUNT]; /** * 屏幕宽 */ private int w_screen; /** * 屏幕高 */ private int h_screen; private SensorManagerHelper mHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFrameLayout = (FrameLayout) findViewById(R.id.frameLayout); DisplayMetrics dm = getResources().getDisplayMetrics(); w_screen = dm.widthPixels; h_screen = dm.heightPixels; int[] leafs = { R.drawable.fengye1,R.drawable.fengye2, R.drawable.fengye3, R.drawable.fengye4, R.drawable.fengye3, R.drawable.fengye4}; for (int i = 0; i < BEZIER_COUNT; i++) { addPointAndView(i, R.drawable.yuanbao,YUANBAO); } for (int i = 0; i < LEAF_COUNT; i++) { addPointAndView(i, leafs[i],LEAF); } mHelper = new SensorManagerHelper(MainActivity.this); mHelper.setmShakeListener(new OnShakeListener() { @Override public void onShake() { for (int count = 0; count < BEZIER_COUNT; count++) { getFPoints(); mViews[count].setX(mPoints[0].x); mViews[count].setY(mPoints[0].y); MyAnimator animator = new MyAnimator(mPoints, MainActivity.this, mViews[count],YUANBAO); animator.startAnimator(); } } @Override public void onSensor() { for (int count = 0; count < LEAF_COUNT; count++) { getFPoints(); mLeafs[count].setX(mPoints[0].x); mLeafs[count].setY(mPoints[0].y); MyAnimator animator = new MyAnimator(mPoints, MainActivity.this, mLeafs[count],LEAF); animator.startAnimator(); } } }); } /** * 随机产生四点 */ private void getFPoints() { for (int i = 0; i < POINT_COUNT; i++) { Point point = new Point(); point.x = new Random().nextInt( w_screen - 20); if (i == 0) { point.y = 0 - Utils.dip2px(this, 60);// 控制起点在屏幕最上方 } else if (i == 3) { point.y = h_screen;// 控制终点在屏幕最下方 } else { point.y = new Random().nextInt( h_screen); } mPoints[i] = point; Log.d("ee", i + ":(" + point.x + "." + point.y); } } /** * 往布局上添加物体 * * @param count * @param resource * @param type */ private void addPointAndView(int count, int resource, int type) { getFPoints(); if (type==YUANBAO) { Button mView = new Button(MainActivity.this); mView.setBackgroundResource(resource); mParams = new LayoutParams(Utils.dip2px(this, 30), Utils.dip2px(this, 30)); mFrameLayout.addView(mView, mParams); mView.setX(mPoints[0].x); mView.setY(mPoints[0].y); mViews[count] = mView; }else { Button mView = new Button(MainActivity.this); mView.setBackgroundResource(resource); mParams = new LayoutParams(Utils.dip2px(this, 60), Utils.dip2px(this, 60)); mFrameLayout.addView(mView, mParams); mView.setX(mPoints[0].x); mView.setY(mPoints[0].y); mLeafs[count]=mView; } } @Override protected void onDestroy() { super.onDestroy(); mHelper.stop(); } }
源码下载