美文网首页软件测试安卓开发
重力传感器实现炫酷软件背景

重力传感器实现炫酷软件背景

作者: 苦学工 | 来源:发表于2018-12-16 12:05 被阅读46次

软件截图


重力传感器实现炫酷软件背景

最近看到一段视频,利用重力传感器制作了一个很炫的壁纸查看视频
废话不多说直接上源码
点我下载
视频中的那个手,就是靠重力传感器实现的

重力传感器

重力传感器,其实他很早就进入生活中了,市场上很多游戏都用到了重力传感器,但是用到软件上当背景的确少之又少
点我查看实现后的效果
点我下载软件
今天要实现的效果很简单
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();
    }
}

这篇文章到这里就完事了,很是简单,希望对大家能有一些帮助

相关文章

网友评论

    本文标题:重力传感器实现炫酷软件背景

    本文链接:https://www.haomeiwen.com/subject/axpahqtx.html