软件截图
![](https://img.haomeiwen.com/i13512800/8ff3a2dd0ff23299.png)
最近看到一段视频,利用重力传感器制作了一个很炫的壁纸查看视频
废话不多说直接上源码
点我下载
视频中的那个手,就是靠重力传感器实现的
重力传感器
重力传感器,其实他很早就进入生活中了,市场上很多游戏都用到了重力传感器,但是用到软件上当背景的确少之又少
点我查看实现后的效果
点我下载软件
今天要实现的效果很简单
SensorEventListener主要是对这个类的学习
//得到重力传感器实例
//TYPE_ACCELEROMETER 加速度传感器(重力传感器)类型。
//TYPE_ALL 描述所有类型的传感器。
//TYPE_GYROSCOPE 陀螺仪传感器类型
//TYPE_LIGHT 光传感器类型
//TYPE_MAGNETIC_FIELD 恒定磁场传感器类型。
//TYPE_ORIENTATION 方向传感器类型。
//TYPE_PRESSURE 描述一个恒定的压力传感器类型
//TYPE_PROXIMITY 常量描述型接近传感器
//TYPE_TEMPERATURE 温度传感器类型描述
final Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
SensorEventListener lsn = new SensorEventListener() {
@SuppressWarnings("deprecation")
//传感器获取值改变时响应此函数
public void onSensorChanged(SensorEvent e) {
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
z = e.values[SensorManager.DATA_Z];
重力传感器可以返回3个值,xyz
左右x值,左正右负,前后位y值,前负后正
z值没有什么用处,可以不用考虑
注册listener,第三个参数是检测的精确度
sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);
再继承ViewGroup实现3D控件
主要用到了Camera和 Matrix
还需要隐藏状态栏和标题栏,实现完全沉浸
public void hide(){
if (getActionBar() != null){
getActionBar().hide();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
View v = this.getWindow().getDecorView();
v.setSystemUiVisibility(View.GONE);
} else if (Build.VERSION.SDK_INT >= 19) {
//for new api versions.
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
}
}
布局页面就是那个3d的ViewGroup包裹一个ImageView
在写一个动画,使它一直旋转
Animation animation = AnimationUtils.loadAnimation(this, R.drawable.an);
LinearInterpolator lin = new LinearInterpolator();//设置动画匀速运动
animation.setInterpolator(lin);
imageView.startAnimation(animation);
an.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<rotate
android:duration="5000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:repeatMode="restart"
android:toDegrees="360" />
</set>
xml没什么解释的,应该都能看懂的
下面放出代码
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="#000000">
<com.mycompany.myapp.ThreeDLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mainThreeDLayout1"
android:background="#00000000">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="16dp"
android:background="@drawable/image_2"
android:id="@+id/mainLinearLayout1">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/grivaty"
android:textColor="#FF1304"
android:alpha="0"
android:gravity="left|center"
android:layout_marginLeft="10dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="p"
android:alpha="0"/>
</LinearLayout>
</com.mycompany.myapp.ThreeDLayout>
</LinearLayout>
an.xml
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<rotate
android:duration="5000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:repeatMode="restart"
android:toDegrees="360" />
</set>
MainActivity.java
package com.mycompany.myapp;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
import android.view.*;
import android.widget.*;
import android.os.*;
import android.view.animation.*;
public class MainActivity extends Activity {
private TextView grivaty;
private SensorManager sensorMgr = null;
private float x,y,z;
ThreeDLayout layout ;
boolean aaa=false;
int chux,chuy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
hide();
initUI();
layout = (ThreeDLayout) findViewById(R.id.mainThreeDLayout1);
layout.setTouchable(false);
layout.setTouchMode(ThreeDLayout.MODE_BOTH_X_Y);
LinearLayout imageView = (LinearLayout) findViewById(R.id.mainLinearLayout1);
//动画
Animation animation = AnimationUtils.loadAnimation(this, R.drawable.an);
LinearInterpolator lin = new LinearInterpolator();//设置动画匀速运动
animation.setInterpolator(lin);
imageView.startAnimation(animation);
}
public void hide(){
if (getActionBar() != null){
getActionBar().hide();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
View v = this.getWindow().getDecorView();
v.setSystemUiVisibility(View.GONE);
} else if (Build.VERSION.SDK_INT >= 19) {
//for new api versions.
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
}
}
private void initUI() {
// TODO Auto-generated method stub
grivaty = (TextView)findViewById(R.id.grivaty);
//通过服务得到传感器管理对象
sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
//得到重力传感器实例
//TYPE_ACCELEROMETER 加速度传感器(重力传感器)类型。
//TYPE_ALL 描述所有类型的传感器。
//TYPE_GYROSCOPE 陀螺仪传感器类型
//TYPE_LIGHT 光传感器类型
//TYPE_MAGNETIC_FIELD 恒定磁场传感器类型。
//TYPE_ORIENTATION 方向传感器类型。
//TYPE_PRESSURE 描述一个恒定的压力传感器类型
//TYPE_PROXIMITY 常量描述型接近传感器
//TYPE_TEMPERATURE 温度传感器类型描述
final Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
SensorEventListener lsn = new SensorEventListener() {
@SuppressWarnings("deprecation")
//传感器获取值改变时响应此函数
public void onSensorChanged(SensorEvent e) {
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
z = e.values[SensorManager.DATA_Z];
if(aaa){
chuy=((int)e.values[SensorManager.DATA_X])*10;
chux=((int)e.values[SensorManager.DATA_Y])*10;
aaa=true;
}
// getsensor();
grivaty.setText("x=" +(int) x + " y=" +(int) y + " z=" + (int)z );//左右x值,左正右负,前后位y值,前负后正
float xx=(x)*10;
float yy=(y)*10;
layout.setcamx(yy/5*4);
layout.setcamy(xx/5*4);
layout.setTranslationX(xx*10);
layout.setTranslationY(yy*10);
}
public void onAccuracyChanged(Sensor s, int accuracy) {
}
};
//注册listener,第三个参数是检测的精确度
sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);
}
public void p(View v){
Toast.makeText(this,"",10).show();
}
}
ThreeDLayout.java
package com.mycompany.myapp;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
public class ThreeDLayout extends ViewGroup {
private Camera mCamera;
private Matrix mMatrix;
//this viewgroup's center
private int mCenterX;
private int mCenterY;
//rotateDegree
private float mCanvasRotateY;
private float mCanvasRotateX;
private float mCanvasMaxRotateDegree = 180;
//the touch mode
public static int MODE_X = 0;
public static int MODE_Y = 1;
public static int MODE_BOTH_X_Y = 2;
private int mMode = MODE_BOTH_X_Y;
private float mDensity;
private float[] mValues = new float[9];
//the flag of touch
private boolean isCanTouch = false;
//the degree of animation
private float mDegreeY = 0;
private float mDegreeX = 0;
//the flag of animate
private boolean isPlaying = false;
//the degree of longer animate
private int mLoopAnimateY = 0;
public ThreeDLayout(Context context) {
this(context, null);
}
public ThreeDLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ThreeDLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//set a default background to make sure onDraw() dispatch
if (getBackground() == null) {
setBackgroundColor(Color.parseColor("#ffffff"));
}
DisplayMetrics dm = new DisplayMetrics();
dm = getResources().getDisplayMetrics();
mDensity = dm.density;
mCamera = new Camera();
mMatrix = new Matrix();
}
public void setcamx(float a){
mCanvasRotateX=a;
}
public void setcamy(float y){
mCanvasRotateY=y;
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getChildCount() != 1) {
throw new IllegalStateException("ThreeDLayout can only have one child");
}
View child = getChildAt(0);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//only one child view,so give the same size
setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
}
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child = getChildAt(0);
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w / 2;
mCenterY = h / 2;
}
@Override protected void onDraw(Canvas canvas) {
mMatrix.reset();
mCamera.save();
if (mMode == MODE_Y || mMode == MODE_BOTH_X_Y) {
mCamera.rotateX(mCanvasRotateX);
}
if (mMode == MODE_X || mMode == MODE_BOTH_X_Y) {
mCamera.rotateY(mCanvasRotateY);
}
mCamera.rotateY(mDegreeY);
mCamera.rotateX(mDegreeX);
if (isPlaying) {
mCamera.rotateY(mLoopAnimateY++);
Log.e("wing", mLoopAnimateY + "");
if (mLoopAnimateY == 360) {
mLoopAnimateY = 0;
}
invalidate();
}
mCamera.getMatrix(mMatrix);
// fix the Camera bug,
mMatrix.getValues(mValues);
mValues[6] = mValues[6] / mDensity;
mValues[7] = mValues[7] / mDensity;
mMatrix.setValues(mValues);
mCamera.restore();
mMatrix.preTranslate(-mCenterX, -mCenterY);
mMatrix.postTranslate(mCenterX, mCenterY);
canvas.concat(mMatrix);
super.onDraw(canvas);
}
@Override public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isCanTouch) {
return true;
} else {
return super.onInterceptTouchEvent(ev);
}
}
@Override public boolean onTouchEvent(MotionEvent event) {
if (isCanTouch) {
float x = event.getX();
float y = event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE: {
// rotateCanvasWhenMove(x, y);
invalidate();
return true;
}
case MotionEvent.ACTION_UP: {
mDegreeY = 0;
// rotateCanvasWhenMove(mCenterX, mCenterY);
invalidate();
return true;
}
}
return true;
} else {
return super.onTouchEvent(event);
}
}
/**
* get the value to rotate
*/
/*
private void rotateCanvasWhenMove(float x, float y) {
float dx = x - mCenterX;
float dy = y - mCenterY;
float percentX = dx / mCenterX;
float percentY = dy / mCenterY;
if (percentX > 1f) {
percentX = 1f;
} else if (percentX < -1f) {
percentX = -1f;
}
if (percentY > 1f) {
percentY = 1f;
} else if (percentY < -1f) {
percentY = -1f;
}
mCanvasRotateY = mCanvasMaxRotateDegree * percentX;
mCanvasRotateX = -(mCanvasMaxRotateDegree * percentY);
}
*/
public void setTouchable(boolean canTouch) {
isCanTouch = canTouch;
}
public void setTouchMode(int mode) {
mMode = mode;
isCanTouch = true;
}
/**
* set the max rotate degree
*/
public void setMaxRotateDegree(int degree) {
mCanvasMaxRotateDegree = degree;
}
/**
* start horizontal turn animate
*/
public void startHorizontalAnimate(long duration) {
final ValueAnimator animator = ValueAnimator.ofFloat(-180f, 0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mDegreeY = (float) animation.getAnimatedValue();
invalidate();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animation) {
}
@Override public void onAnimationEnd(Animator animation) {
mDegreeY = 0;
animator.removeAllUpdateListeners();
}
@Override public void onAnimationCancel(Animator animation) {
}
@Override public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(duration);
animator.start();
}
/**
* start horizontal turn animate delayed
*/
public void startHorizontalAnimateDelayed(final long delayed, final long duration) {
new Thread(new Runnable() {
@Override public void run() {
try {
Thread.sleep(delayed);
} catch (InterruptedException e) {
e.printStackTrace();
}
post(new Runnable() {
@Override public void run() {
startHorizontalAnimate(duration);
}
});
}
}).start();
}
/**
* start vertical turn animate
*/
public void startVerticalAnimate(long duration) {
final ValueAnimator animator = ValueAnimator.ofFloat(-180f, 0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mDegreeX = (float) animation.getAnimatedValue();
invalidate();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animation) {
}
@Override public void onAnimationEnd(Animator animation) {
mDegreeX = 0;
animator.removeAllUpdateListeners();
}
@Override public void onAnimationCancel(Animator animation) {
}
@Override public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(duration);
animator.start();
}
/**
* start vertical turn animate delayed
*/
public void startVerticalAnimateDelayed(final long delayed, final long duration) {
new Thread(new Runnable() {
@Override public void run() {
try {
Thread.sleep(delayed);
} catch (InterruptedException e) {
e.printStackTrace();
}
post(new Runnable() {
@Override public void run() {
startVerticalAnimate(duration);
}
});
}
}).start();
}
/**
* start loop animate
*/
public void startHorizontalAnimate() {
isPlaying = true;
invalidate();
}
/**
* stop the loop animate
*/
public void stopAnimate() {
isPlaying = false;
mLoopAnimateY = 0;
invalidate();
}
}
这篇文章到这里就完事了,很是简单,希望对大家能有一些帮助
网友评论