效果图:
首先进入页面要先判断手机是否有陀螺仪传感器:
PackageManager pm = getPackageManager();
// 获取是否支持电话
boolean telephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
// 是否支持GSM
boolean gsm = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM);
// 是否支持CDMA
boolean cdma = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
//是否支持NFC
boolean nfc = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
//是否支持陀螺仪传感器
boolean gyroscope = pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_GYROSCOPE);
Toast.makeText(MainActivity.this, gyroscope ? "支持:陀螺仪" : "不支持:陀螺仪", Toast.LENGTH_SHORT).show();
自定义布局实现手机左右移动(倾斜),背景图跟着移动:
package com.example.gravitysensorbackground;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ImageView;
import androidx.annotation.Nullable;
public class XImageView extends androidx.appcompat.widget.AppCompatImageView {
private double scaleX;
private double scaleY;
private float lenX;
private float lenY;
public XImageView(Context context) {
super(context);
init();
}
public XImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public XImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setScaleType(ScaleType.CENTER_CROP);
}
@Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(ScaleType.CENTER_CROP);
}
public void setGyroscopeManager(GyroscopeManager gyroscopeManager) {
if (gyroscopeManager != null) {
gyroscopeManager.addView(this);
}
}
public void update(double scaleX, double scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
if (getDrawable() != null) {
int drawableWidth = getDrawable().getIntrinsicWidth();
int drawableHeight = getDrawable().getIntrinsicHeight();
lenX = Math.abs((drawableWidth - width) * 0.5f);
lenY = Math.abs((drawableHeight - height) * 0.5f);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null || isInEditMode()) {
super.onDraw(canvas);
return;
}
float currentOffsetX = (float) (lenX * scaleX);
float currentOffsetY = (float) (lenY * scaleY);
canvas.save();
canvas.translate(currentOffsetX, 0);
canvas.translate(0, currentOffsetY);
super.onDraw(canvas);
canvas.restore();
}
}
陀螺仪管理类:
package com.example.gravitysensorbackground;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import java.util.ArrayList;
import java.util.List;
public class GyroscopeManager implements SensorEventListener {
// 将纳秒转化为秒
private static final float NS2S = 1.0f / 1000000000.0f;
private List<XImageView> list_views = new ArrayList<>();
private SensorManager sensorManager;
private long endTimestamp;
private double angleX;
private double angleY;
//0到π/2
private double maxAngle = Math.PI / 3;
public void addView(XImageView xImageView) {
if (xImageView != null && !list_views.contains(xImageView)) {
list_views.add(xImageView);
}
}
public void register(Context context) {
if (sensorManager == null) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}
Sensor mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
sensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_FASTEST);
endTimestamp = 0;
// angleX = 0;
angleY = 0;
}
public void unregister() {
if (sensorManager != null) {
sensorManager.unregisterListener(this);
sensorManager = null;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
if (endTimestamp == 0) {
endTimestamp = event.timestamp;
return;
}
// angleX += event.values[0] * (event.timestamp - endTimestamp) * NS2S;
angleY += event.values[1] * (event.timestamp - endTimestamp) * NS2S;
/* if (angleX > maxAngle) {
angleX = maxAngle;
}
if (angleX < -maxAngle) {
angleX = -maxAngle;
}*/
if (angleY > maxAngle) {
angleY = maxAngle;
}
if (angleY < -maxAngle) {
angleY = -maxAngle;
}
for (XImageView view : list_views) {
if (view != null) {
view.update(angleY / maxAngle, angleX / maxAngle);
}
}
endTimestamp = event.timestamp;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
在此把纵向倾斜手机的功能注释了,如有需要自行解开。(提示:图片尽可能的大于控件,否则图片背景移动的时候容易显示图片之外的空白地方。因为图片用的是src属性,用background没有效果。)
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<com.example.gravitysensorbackground.XImageView
android:id="@+id/iv1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/bg" />
<com.example.gravitysensorbackground.XImageView
android:id="@+id/iv2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/tree" />
</RelativeLayout>
</LinearLayout>
项目地址: