/*
* Created by LuaView.
* Copyright (c) 2017, Alibaba Group. All rights reserved.
*
* This source code is licensed under the MIT.
* For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
*/
package com.taobao.luaview.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.view.View;
import com.taobao.luaview.extend.SensorInterpreter;
import com.taobao.luaview.userdata.ui.UDImageView;
import com.taobao.luaview.userdata.ui.UDView;
import com.taobao.luaview.util.LogUtil;
import com.taobao.luaview.view.imageview.BaseImageView;
import com.taobao.luaview.view.interfaces.ILVView;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* LuaView-ImageView
*
* @author song
* @date 15/8/20
*/
public class LVImageView extends BaseImageView implements ILVView, SensorEventListener {
private UDImageView mLuaUserdata;
private SensorManager mSensorManager;
private SensorInterpreter mSensorInterpreter;
//图片运动的偏移
private float mMotionOffsetX = 0;
private float mMotionOffsetY = 0;
/**
* 开关控制是否普通的JuImageView
* 默认关闭,只有调用 {@link LVImageView#setMotionDistanceXY(float, float)} 才打开
* 从而调用 {@link LVImageView#registerSensorManager(int)} 才会注册监听器
* 以此保证不是所有的{@link LVImageView}都会监听SensorEvent
*/
private boolean mMotionDetect = false;
public LVImageView(Globals globals, LuaValue metaTable, Varargs varargs) {
super(globals.getContext());
this.mLuaUserdata = new UDImageView(this, globals, metaTable, varargs);
init();
}
private void init() {
this.setScaleType(ScaleType.FIT_XY);//默认FIT_XY
}
@Override
public UDView getUserdata() {
return mLuaUserdata;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (mSensorInterpreter == null) return;
final float[] vectors = mSensorInterpreter.interpretSensorEvent(getContext(), event);
// Return if interpretation of data failed
if (vectors == null) return;
// Set translation on ImageView matrix
setTranslate(vectors[2], -vectors[1]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
* Sets the maximum percentage of the image that image matrix is allowed to translate
* for each sensor reading.
*
* @param motionDistanceX horizontall motion
* @param motionDistanceY vertical motion
*/
public void setMotionDistanceXY(float motionDistanceX, float motionDistanceY) {
mMotionDetect = true;
if (mSensorInterpreter == null) {
mSensorInterpreter = new SensorInterpreter();
mSensorInterpreter.setTiltSensitivity(1); // TODO: 11/16/16 配置一个可接受的默认敏感度
}
registerSensorManager();
mMotionOffsetX = motionDistanceX;
mMotionOffsetY = motionDistanceY;
}
/**
* Sets the image view's translation coordinates. These values must be between -1 and 1,
* representing the transaction percentage from the center.
*
* @param x the horizontal translation
* @param y the vertical translation
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void setTranslate(float x, float y) {
if (Math.abs(x) > 1 || Math.abs(y) > 1) {
throw new IllegalArgumentException("Parallax effect cannot translate more than 100% of its off-screen size");
}
setTranslationX(x * mMotionOffsetX);
setTranslationY(y * mMotionOffsetY);
}
/**
* Registers a sensor manager with the parallax ImageView. Should be called in onResume
* or onStart lifecycle callbacks from an Activity or Fragment.
*/
public void registerSensorManager() {
registerSensorManager(SensorManager.SENSOR_DELAY_GAME);
}
/**
* Registers a sensor manager with the parallax ImageView. Should be called in onResume
* or onStart lifecycle callbacks from an Activity or Fragment.
*
* @param samplingPeriodUs the sensor sampling period rate
*/
public void registerSensorManager(int samplingPeriodUs) {
if (getContext() == null || mSensorManager != null || !mMotionDetect) return;
// Acquires a sensor manager
mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
if (sensor == null) {
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
if (sensor == null) {
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
}
}
if (sensor != null) {
mSensorManager.registerListener(this, sensor, samplingPeriodUs);
} else {
LogUtil.i("LuaViewSDK Exception", "Rotation sensor is null");
}
}
}
/**
* Unregisters the ParallaxImageView's SensorManager. Should be called in onPause or onStop
* lifecycle callbacks from an Activity or Fragment to avoid leaking sensor usage.
*/
public void unregisterSensorManager() {
unregisterSensorManager(false);
}
/**
* Unregisters the ParallaxImageView's SensorManager. Should be called in onPause from
* an Activity or Fragment to avoid continuing sensor usage.
*
* @param resetTranslation if the image translation should be reset to the origin
*/
public void unregisterSensorManager(boolean resetTranslation) {
if (mSensorManager == null || mSensorInterpreter == null) return;
mSensorManager.unregisterListener(this);
mSensorManager = null;
mSensorInterpreter.reset();
if (resetTranslation) {
setTranslate(0, 0);
}
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == View.VISIBLE) {
registerSensorManager();
}
if (visibility == View.GONE) {
unregisterSensorManager();
}
}
}