Android joystick,安卓模拟摇杆
安卓模拟游戏摇杆,android实现自定义view
参考文章:https://www.jianshu.com/p/96c982d41623 ,原文部分内容不全。
attrs.xml
<resources> <declare-styleable name="RockerView"> <attr name="areaBackground" format="color|reference" /> <attr name="rockerBackground" format="color|reference" /> <attr name="rockerRadius" format="dimension" /> <attr name="rockerScale" format="float"/> <attr name="rockerSpeedLevel" format="dimension" /> <attr name="rockerCallBackMode" format="dimension" /> </declare-styleable> </resources>
RockerView.java
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.zony.hello.R; import java.util.logging.Level; /** * Created by jinkia on 2016/9/30. * 摇杆控件 */ public class RockerView extends View { private static final String TAG = "RockerView"; private static final int DEFAULT_SIZE = 400; private static final float DEFAULT_ROCKER_SCALE = 0.5f;//默认半径为背景的1/2 private Paint mAreaBackgroundPaint; private Paint mRockerPaint; private Point mRockerPosition; private Point mCenterPoint; private int mAreaRadius; private float mRockerScale; private int mRockerRadius; private CallBackMode mCallBackMode = CallBackMode.CALL_BACK_MODE_MOVE; private OnAngleChangeListener mOnAngleChangeListener; private OnShakeListener mOnShakeListener; private OnDistanceLevelListener mOnDistanceLevelListener; private DirectionMode mDirectionMode; private Direction tempDirection = Direction.DIRECTION_CENTER; private float lastDistance = 0; private boolean hasCall = false; private float baseDistance = 0; private int mDistanceLevel = 10;//分成10分 // 角度 private static final double ANGLE_0 = 0; private static final double ANGLE_360 = 360; // 360°水平方向平分2份的边缘角度 private static final double ANGLE_HORIZONTAL_2D_OF_0P = 90; private static final double ANGLE_HORIZONTAL_2D_OF_1P = 270; // 360°垂直方向平分2份的边缘角度 private static final double ANGLE_VERTICAL_2D_OF_0P = 0; private static final double ANGLE_VERTICAL_2D_OF_1P = 180; // 360°平分4份的边缘角度 private static final double ANGLE_4D_OF_0P = 0; private static final double ANGLE_4D_OF_1P = 90; private static final double ANGLE_4D_OF_2P = 180; private static final double ANGLE_4D_OF_3P = 270; // 360°平分4份的边缘角度(旋转45度) private static final double ANGLE_ROTATE45_4D_OF_0P = 45; private static final double ANGLE_ROTATE45_4D_OF_1P = 135; private static final double ANGLE_ROTATE45_4D_OF_2P = 225; private static final double ANGLE_ROTATE45_4D_OF_3P = 315; // 360°平分8份的边缘角度 private static final double ANGLE_8D_OF_0P = 22.5; private static final double ANGLE_8D_OF_1P = 67.5; private static final double ANGLE_8D_OF_2P = 112.5; private static final double ANGLE_8D_OF_3P = 157.5; private static final double ANGLE_8D_OF_4P = 202.5; private static final double ANGLE_8D_OF_5P = 247.5; private static final double ANGLE_8D_OF_6P = 292.5; private static final double ANGLE_8D_OF_7P = 337.5; // 摇杆可移动区域背景 private static final int AREA_BACKGROUND_MODE_PIC = 0; private static final int AREA_BACKGROUND_MODE_COLOR = 1; private static final int AREA_BACKGROUND_MODE_XML = 2; private static final int AREA_BACKGROUND_MODE_DEFAULT = 3; private int mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; private Bitmap mAreaBitmap; private int mAreaColor; // 摇杆背景 private static final int ROCKER_BACKGROUND_MODE_PIC = 4; private static final int ROCKER_BACKGROUND_MODE_COLOR = 5; private static final int ROCKER_BACKGROUND_MODE_XML = 6; private static final int ROCKER_BACKGROUND_MODE_DEFAULT = 7; private int mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; private Bitmap mRockerBitmap; private int mRockerColor; public RockerView(Context context, AttributeSet attrs) { super(context, attrs); // 获取自定义属性 initAttribute(context, attrs); if (isInEditMode()) { } // 移动区域画笔 mAreaBackgroundPaint = new Paint(); mAreaBackgroundPaint.setAntiAlias(true); // 摇杆画笔 mRockerPaint = new Paint(); mRockerPaint.setAntiAlias(true); // 中心点 mCenterPoint = new Point(); // 摇杆位置 mRockerPosition = new Point(); } /** * 获取属性 * * @param context context * @param attrs attrs */ private void initAttribute(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RockerView); // 可移动区域背景 Drawable areaBackground = typedArray.getDrawable(R.styleable.RockerView_areaBackground); if (null != areaBackground) { // 设置了背景 if (areaBackground instanceof BitmapDrawable) { // 设置了一张图片 mAreaBitmap = ((BitmapDrawable) areaBackground).getBitmap(); mAreaBackgroundMode = AREA_BACKGROUND_MODE_PIC; } else if (areaBackground instanceof GradientDrawable) { // XML mAreaBitmap = drawable2Bitmap(areaBackground); mAreaBackgroundMode = AREA_BACKGROUND_MODE_XML; } else if (areaBackground instanceof ColorDrawable) { // 色值 mAreaColor = ((ColorDrawable) areaBackground).getColor(); mAreaBackgroundMode = AREA_BACKGROUND_MODE_COLOR; } else { // 其他形式 mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; } } else { // 没有设置背景 mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; } // 摇杆背景 Drawable rockerBackground = typedArray.getDrawable(R.styleable.RockerView_rockerBackground); if (null != rockerBackground) { // 设置了摇杆背景 if (rockerBackground instanceof BitmapDrawable) { // 图片 mRockerBitmap = ((BitmapDrawable) rockerBackground).getBitmap(); mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_PIC; } else if (rockerBackground instanceof GradientDrawable) { // XML mRockerBitmap = drawable2Bitmap(rockerBackground); mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_XML; } else if (rockerBackground instanceof ColorDrawable) { // 色值 mRockerColor = ((ColorDrawable) rockerBackground).getColor(); mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_COLOR; } else { // 其他形式 mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; } } else { // 没有设置摇杆背景 mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; } // 摇杆半径 mRockerScale = typedArray.getFloat(R.styleable.RockerView_rockerScale, DEFAULT_ROCKER_SCALE); //距离级别 mDistanceLevel = typedArray.getInt(R.styleable.RockerView_rockerSpeedLevel, 10); //回调模式 mCallBackMode = getCallBackMode(typedArray.getInt(R.styleable.RockerView_rockerCallBackMode, 0)); typedArray.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measureWidth, measureHeight; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { // 具体的值和match_parent measureWidth = widthSize; } else { // wrap_content measureWidth = DEFAULT_SIZE; } if (heightMode == MeasureSpec.EXACTLY) { measureHeight = heightSize; } else { measureHeight = DEFAULT_SIZE; } setMeasuredDimension(measureWidth, measureHeight); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int measuredWidth = getMeasuredWidth(); int measuredHeight = getMeasuredHeight(); int cx = measuredWidth / 2; int cy = measuredHeight / 2; // 中心点 mCenterPoint.set(cx, cy); // 可移动区域的半径 mAreaRadius = (measuredWidth <= measuredHeight) ? (int) (cx / (mRockerScale + 1)) : (int) (cy / (mRockerScale + 1)); mRockerRadius = (int) (mAreaRadius * mRockerScale); // 摇杆位置 if (0 == mRockerPosition.x || 0 == mRockerPosition.y) { mRockerPosition.set(mCenterPoint.x, mCenterPoint.y); } // 画可移动区域 if (AREA_BACKGROUND_MODE_PIC == mAreaBackgroundMode || AREA_BACKGROUND_MODE_XML == mAreaBackgroundMode) { // 图片 Rect src = new Rect(0, 0, mAreaBitmap.getWidth(), mAreaBitmap.getHeight()); Rect dst = new Rect(mCenterPoint.x - mAreaRadius, mCenterPoint.y - mAreaRadius, mCenterPoint.x + mAreaRadius, mCenterPoint.y + mAreaRadius); canvas.drawBitmap(mAreaBitmap, src, dst, mAreaBackgroundPaint); } else if (AREA_BACKGROUND_MODE_COLOR == mAreaBackgroundMode) { // 色值 mAreaBackgroundPaint.setColor(mAreaColor); canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mAreaRadius, mAreaBackgroundPaint); } else { // 其他或者未设置 mAreaBackgroundPaint.setColor(Color.GRAY); canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mAreaRadius, mAreaBackgroundPaint); } // 画摇杆 if (ROCKER_BACKGROUND_MODE_PIC == mRockerBackgroundMode || ROCKER_BACKGROUND_MODE_XML == mRockerBackgroundMode) { // 图片 Rect src = new Rect(0, 0, mRockerBitmap.getWidth(), mRockerBitmap.getHeight()); Rect dst = new Rect(mRockerPosition.x - mRockerRadius, mRockerPosition.y - mRockerRadius, mRockerPosition.x + mRockerRadius, mRockerPosition.y + mRockerRadius); canvas.drawBitmap(mRockerBitmap, src, dst, mRockerPaint); } else if (ROCKER_BACKGROUND_MODE_COLOR == mRockerBackgroundMode) { // 色值 mRockerPaint.setColor(mRockerColor); canvas.drawCircle(mRockerPosition.x, mRockerPosition.y, mRockerRadius, mRockerPaint); } else { // 其他或者未设置 mRockerPaint.setColor(Color.RED); canvas.drawCircle(mRockerPosition.x, mRockerPosition.y, mRockerRadius, mRockerPaint); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN:// 按下 // 回调 开始 callBackStart(); case MotionEvent.ACTION_MOVE:// 移动 float moveX = event.getX(); float moveY = event.getY(); baseDistance = mAreaRadius + 2; Log.d("baseDistance", baseDistance + ""); mRockerPosition = getRockerPositionPoint(mCenterPoint, new Point((int) moveX, (int) moveY), mAreaRadius + mRockerRadius, mRockerRadius); moveRocker(mRockerPosition.x, mRockerPosition.y); break; case MotionEvent.ACTION_UP:// 抬起 case MotionEvent.ACTION_CANCEL:// 移出区域 // 回调 结束 callBackFinish(); if (mOnShakeListener != null) { mOnShakeListener.direction(Direction.DIRECTION_CENTER); } float upX = event.getX(); float upY = event.getY(); moveRocker(mCenterPoint.x, mCenterPoint.y); break; } return true; } /** * 获取摇杆实际要显示的位置(点) * * @param centerPoint 中心点 * @param touchPoint 触摸点 * @param regionRadius 摇杆可活动区域半径 * @param rockerRadius 摇杆半径 * @return 摇杆实际显示的位置(点) */ private Point getRockerPositionPoint(Point centerPoint, Point touchPoint, float regionRadius, float rockerRadius) { // 两点在X轴的距离 float lenX = (float) (touchPoint.x - centerPoint.x); // 两点在Y轴距离 float lenY = (float) (touchPoint.y - centerPoint.y); // 两点距离 float lenXY = (float) Math.sqrt((double) (lenX * lenX + lenY * lenY)); // 计算弧度 double radian = Math.acos(lenX / lenXY) * (touchPoint.y < centerPoint.y ? -1 : 1); // 计算角度 double angle = radian2Angle(radian); if (lenXY + rockerRadius <= regionRadius) { // 触摸位置在可活动范围内 // 回调 返回参数 callBack(angle, (int) lenXY); return touchPoint; } else { // 触摸位置在可活动范围以外 // 计算要显示的位置 int showPointX = (int) (centerPoint.x + (regionRadius - rockerRadius) * Math.cos(radian)); int showPointY = (int) (centerPoint.y + (regionRadius - rockerRadius) * Math.sin(radian)); callBack(angle, (int) Math.sqrt((showPointX - centerPoint.x) * (showPointX - centerPoint.x) + (showPointY - centerPoint.y) * (showPointY - centerPoint.y))); return new Point(showPointX, showPointY); } } /** * 移动摇杆到指定位置 * * @param x x坐标 * @param y y坐标 */ private void moveRocker(float x, float y) { mRockerPosition.set((int) x, (int) y); invalidate(); } /** * 弧度转角度 * * @param radian 弧度 * @return 角度[0, 360) */ private double radian2Angle(double radian) { double tmp = Math.round(radian / Math.PI * 180); return tmp >= 0 ? tmp : 360 + tmp; } /** * Drawable 转 Bitmap * * @param drawable Drawable * @return Bitmap */ private Bitmap drawable2Bitmap(Drawable drawable) { // 取 drawable 的长宽 int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // 取 drawable 的颜色格式 Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; // 建立对应 bitmap Bitmap bitmap = Bitmap.createBitmap(width, height, config); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; } /** * 回调 * 开始 */ private void callBackStart() { tempDirection = Direction.DIRECTION_CENTER; if (null != mOnAngleChangeListener) { mOnAngleChangeListener.onStart(); } if (null != mOnShakeListener) { mOnShakeListener.onStart(); } } /** * 回调 * 返回参数 * * @param angle 摇动角度 */ private void callBack(double angle, float distance) { Log.d("distance", distance + ""); if (Math.abs(distance - lastDistance) >= (baseDistance / mDistanceLevel)) { lastDistance = distance; if (null != mOnDistanceLevelListener) { int level = (int) (distance / (baseDistance / mDistanceLevel)); mOnDistanceLevelListener.onDistanceLevel(level); } } if (null != mOnAngleChangeListener) { mOnAngleChangeListener.angle(angle); } if (null != mOnShakeListener) { if (CallBackMode.CALL_BACK_MODE_MOVE == mCallBackMode) { switch (mDirectionMode) { case DIRECTION_2_HORIZONTAL:// 左右方向 if (ANGLE_0 <= angle && ANGLE_HORIZONTAL_2D_OF_0P > angle || ANGLE_HORIZONTAL_2D_OF_1P <= angle && ANGLE_360 > angle) { // 右 mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle) { // 左 mOnShakeListener.direction(Direction.DIRECTION_LEFT); } break; case DIRECTION_2_VERTICAL:// 上下方向 if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle) { // 下 mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle) { // 上 mOnShakeListener.direction(Direction.DIRECTION_UP); } break; case DIRECTION_4_ROTATE_0:// 四个方向 if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle) { // 右下 mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); } else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle) { // 左下 mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); } else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle) { // 左上 mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); } else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle) { // 右上 mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); } break; case DIRECTION_4_ROTATE_45:// 四个方向 旋转45度 if (ANGLE_0 <= angle && ANGLE_ROTATE45_4D_OF_0P > angle || ANGLE_ROTATE45_4D_OF_3P <= angle && ANGLE_360 > angle) { // 右 mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle) { // 下 mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle) { // 左 mOnShakeListener.direction(Direction.DIRECTION_LEFT); } else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle) { // 上 mOnShakeListener.direction(Direction.DIRECTION_UP); } break; case DIRECTION_8:// 八个方向 if (ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle) { // 右 mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle) { // 右下 mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); } else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle) { // 下 mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle) { // 左下 mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); } else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle) { // 左 mOnShakeListener.direction(Direction.DIRECTION_LEFT); } else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle) { // 左上 mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); } else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle) { // 上 mOnShakeListener.direction(Direction.DIRECTION_UP); } else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle) { // 右上 mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); } break; default: break; } } else if (CallBackMode.CALL_BACK_MODE_STATE_CHANGE == mCallBackMode) { switch (mDirectionMode) { case DIRECTION_2_HORIZONTAL:// 左右方向 if ((ANGLE_0 <= angle && ANGLE_HORIZONTAL_2D_OF_0P > angle || ANGLE_HORIZONTAL_2D_OF_1P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { // 右 tempDirection = Direction.DIRECTION_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle && tempDirection != Direction.DIRECTION_LEFT) { // 左 tempDirection = Direction.DIRECTION_LEFT; mOnShakeListener.direction(Direction.DIRECTION_LEFT); } break; case DIRECTION_2_VERTICAL:// 上下方向 if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN) { // 下 tempDirection = Direction.DIRECTION_DOWN; mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle && tempDirection != Direction.DIRECTION_UP) { // 上 tempDirection = Direction.DIRECTION_UP; mOnShakeListener.direction(Direction.DIRECTION_UP); } break; case DIRECTION_4_ROTATE_0:// 四个方向 if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN_RIGHT) { // 右下 tempDirection = Direction.DIRECTION_DOWN_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); } else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle && tempDirection != Direction.DIRECTION_DOWN_LEFT) { // 左下 tempDirection = Direction.DIRECTION_DOWN_LEFT; mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); } else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle && tempDirection != Direction.DIRECTION_UP_LEFT) { // 左上 tempDirection = Direction.DIRECTION_UP_LEFT; mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); } else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle && tempDirection != Direction.DIRECTION_UP_RIGHT) { // 右上 tempDirection = Direction.DIRECTION_UP_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); } break; case DIRECTION_4_ROTATE_45:// 四个方向 旋转45度 if ((ANGLE_0 <= angle && ANGLE_ROTATE45_4D_OF_0P > angle || ANGLE_ROTATE45_4D_OF_3P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { // 右 tempDirection = Direction.DIRECTION_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN) { // 下 tempDirection = Direction.DIRECTION_DOWN; mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle && tempDirection != Direction.DIRECTION_LEFT) { // 左 tempDirection = Direction.DIRECTION_LEFT; mOnShakeListener.direction(Direction.DIRECTION_LEFT); } else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle && tempDirection != Direction.DIRECTION_UP) { // 上 tempDirection = Direction.DIRECTION_UP; mOnShakeListener.direction(Direction.DIRECTION_UP); } break; case DIRECTION_8:// 八个方向 if ((ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { // 右 tempDirection = Direction.DIRECTION_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_RIGHT); } else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN_RIGHT) { // 右下 tempDirection = Direction.DIRECTION_DOWN_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); } else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle && tempDirection != Direction.DIRECTION_DOWN) { // 下 tempDirection = Direction.DIRECTION_DOWN; mOnShakeListener.direction(Direction.DIRECTION_DOWN); } else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle && tempDirection != Direction.DIRECTION_DOWN_LEFT) { // 左下 tempDirection = Direction.DIRECTION_DOWN_LEFT; mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); } else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle && tempDirection != Direction.DIRECTION_LEFT) { // 左 tempDirection = Direction.DIRECTION_LEFT; mOnShakeListener.direction(Direction.DIRECTION_LEFT); } else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle && tempDirection != Direction.DIRECTION_UP_LEFT) { // 左上 tempDirection = Direction.DIRECTION_UP_LEFT; mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); } else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle && tempDirection != Direction.DIRECTION_UP) { // 上 tempDirection = Direction.DIRECTION_UP; mOnShakeListener.direction(Direction.DIRECTION_UP); } else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle && tempDirection != Direction.DIRECTION_UP_RIGHT) { // 右上 tempDirection = Direction.DIRECTION_UP_RIGHT; mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); } break; default: break; } } } } /** * 回调 * 结束 */ private void callBackFinish() { tempDirection = Direction.DIRECTION_CENTER; if (null != mOnAngleChangeListener) { mOnAngleChangeListener.onFinish(); } if (null != mOnShakeListener) { mOnShakeListener.onFinish(); } } /** * 回调模式 */ public enum CallBackMode { // 有移动就立刻回调 CALL_BACK_MODE_MOVE, // 只有状态变化的时候才回调 CALL_BACK_MODE_STATE_CHANGE, //只有状态变化或者距离变化的时候才回调 CALL_BACK_MODE_STATE_DISTANCE_CHANGE } /** * 设置回调模式 * * @param mode 回调模式 */ public void setCallBackMode(CallBackMode mode) { mCallBackMode = mode; } /** * 摇杆支持几个方向 */ public enum DirectionMode { DIRECTION_2_HORIZONTAL,// 横向 左右两个方向 DIRECTION_2_VERTICAL, // 纵向 上下两个方向 DIRECTION_4_ROTATE_0, // 四个方向 DIRECTION_4_ROTATE_45, // 四个方向 旋转45度 DIRECTION_8 // 八个方向 } /** * 方向 */ public enum Direction { DIRECTION_LEFT, // 左 DIRECTION_RIGHT, // 右 DIRECTION_UP, // 上 DIRECTION_DOWN, // 下 DIRECTION_UP_LEFT, // 左上 DIRECTION_UP_RIGHT, // 右上 DIRECTION_DOWN_LEFT, // 左下 DIRECTION_DOWN_RIGHT, // 右下 DIRECTION_CENTER // 中间 } /** * 添加摇杆摇动角度的监听 * * @param listener 回调接口 */ public void setOnAngleChangeListener(OnAngleChangeListener listener) { mOnAngleChangeListener = listener; } /** * 添加摇动的监听 * * @param directionMode 监听的方向 * @param listener 回调 */ public void setOnShakeListener(DirectionMode directionMode, OnShakeListener listener) { mDirectionMode = directionMode; mOnShakeListener = listener; } /** * 添加摇动的距离变化 */ public void setOnDistanceLevelListener(OnDistanceLevelListener listener) { mOnDistanceLevelListener = listener; } /** * 摇动方向监听接口 */ public interface OnShakeListener { // 开始 void onStart(); /** * 摇动方向 * * @param direction 方向 */ void direction(Direction direction); // 结束 void onFinish(); } /** * 摇动角度的监听接口 */ public interface OnAngleChangeListener { // 开始 void onStart(); /** * 摇杆角度变化 * * @param angle 角度[0,360) */ void angle(double angle); // 结束 void onFinish(); } /** * 摇动距离 */ public interface OnDistanceLevelListener { void onDistanceLevel(int level); } private CallBackMode getCallBackMode(int mode) { switch (mode) { case 0: return CallBackMode.CALL_BACK_MODE_MOVE; case 1: return CallBackMode.CALL_BACK_MODE_STATE_CHANGE; } return mCallBackMode; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步