Android仿自如裸眼3DBanner效果

这篇博客介绍了如何在Android中利用BGABanner库创建两个联动的Banner,并结合重力感应实现上层Banner随手机倾斜角度平滑移动的效果。主要涉及SensorEventListener接口的使用,以及SensorManager获取设备加速度和地磁场数据,通过SensorManager的旋转矩阵和欧拉角计算实现视图滚动。

123.gif

 

突然想起来更新一篇,昨天看到自如这个banner好像挺有意思的,自己也试着搞了搞,上面的图片素材是扒的其他大佬项目里面的,有问题的话联系删除.

这个效果很简单,两个viewpager重叠起来关联一下就好了,网上也有很多办法的,我用的是BGABanner-Android实现的,贴个链接

https://github.com/bingoogolapple/BGABanner-Android

这个可以实现两个banner联动,主要是用BGAGuideLinkageLayout把需要关联的banner包起来就好了

然后进行第二步实现重力感应移动上面一层view

主要代码贴一下

public class SensorLayout extends FrameLayout implements SensorEventListener {
    private final SensorManager mSensorManager;
    private float[] mAccelerateValues;
    private float[] mMagneticValues;
    private final Scroller mScroller;
    private double mDegreeYMin = -50;
    private double mDegreeYMax = 50;
    private double mDegreeXMin = -50;
    private double mDegreeXMax = 50;
    private static final double MOVE_DISTANCE_X = 40;
    private static final double MOVE_DISTANCE_Y = 40;
    private int mDirection = 1;
    private final float[] values = new float[3];
    private final float[] R = new float[9];

    public SensorLayout(@NonNull Context context) {
        this(context, null);
    }

    public SensorLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SensorLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScroller = new Scroller(context);
        mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
        if (mSensorManager != null) {
            Sensor accelerateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            // 地磁场传感器
            Sensor magneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
            mSensorManager.registerListener(this, accelerateSensor, SensorManager.SENSOR_DELAY_GAME);
            mSensorManager.registerListener(this, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            mAccelerateValues = event.values;
        }
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            mMagneticValues = event.values;
        }

        if (mMagneticValues != null && mAccelerateValues != null)
            SensorManager.getRotationMatrix(R, null, mAccelerateValues, mMagneticValues);
        SensorManager.getOrientation(R, values);
        // x轴的偏转角度
        double degreeX = (float) Math.toDegrees(values[1]);
        // y轴的偏转角度
        double degreeY = (float) Math.toDegrees(values[2]);
        int scrollX = mScroller.getFinalX();
        int scrollY = mScroller.getFinalY();
        if (degreeY <= 0 && degreeY > mDegreeYMin) {
            scrollX = (int) (degreeY / Math.abs(mDegreeYMin) * MOVE_DISTANCE_X * mDirection);
        } else if (degreeY > 0 && degreeY < mDegreeYMax) {
            scrollX = (int) (degreeY / Math.abs(mDegreeYMax) * MOVE_DISTANCE_X * mDirection);
        }
        if (degreeX <= 0 && degreeX > mDegreeXMin) {
            scrollY = (int) (degreeX / Math.abs(mDegreeXMin) * MOVE_DISTANCE_Y * mDirection);
        } else if (degreeX > 0 && degreeX < mDegreeXMax) {
            scrollY = (int) (degreeX / Math.abs(mDegreeXMax) * MOVE_DISTANCE_Y * mDirection);
        }
        smoothScroll(scrollX, scrollY);
    }


    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    public void smoothScroll(int destX, int destY) {
        int scrollY = getScrollY();
        int delta = destY - scrollY;
        mScroller.startScroll(destX, scrollY, 0, delta, 200);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    public void unregister() {
        mSensorManager.unregisterListener(this);
    }

    public void setDegreeYMin(double degreeYMin) {
        mDegreeYMin = degreeYMin;
    }

    public void setDegreeYMax(double degreeYMax) {
        mDegreeYMax = degreeYMax;
    }

    public void setDegreeXMin(double degreeXMin) {
        mDegreeXMin = degreeXMin;
    }

    public void setDegreeXMax(double degreeXMax) {
        mDegreeXMax = degreeXMax;
    }

    public void setDirection(@ADirection int direction) {
        mDirection = direction;
    }

    @IntDef({DIRECTION_LEFT, DIRECTION_RIGHT})
    @Retention(RetentionPolicy.SOURCE)
    @Target(ElementType.PARAMETER)
    public @interface ADirection {

    }

    public static final int DIRECTION_LEFT = 1;
    public static final int DIRECTION_RIGHT = -1;
}

然后在xml里面把需要移动的控件包起来就完事了...有啥问题可以滴滴,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值