Android重力感应飘树叶,晃动掉元宝

郑宜民
2023-12-01

图呢,,,,,自己想想吧、、、、、、、画面很美。

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();
	}

}

源码下载



 类似资料: