1 Star 0 Fork 5

刘朋程/RockerView

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
unnamed.patch 39.33 KB
一键复制 编辑 原始数据 按行查看 历史
海滩飘舞的白叶 提交于 2021-04-26 19:21 . test
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
Index: RockerView/src/test/java/com/shy/rockerview/ExampleUnitTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/src/test/java/com/shy/rockerview/ExampleUnitTest.java (date 1619405398584)
+++ RockerView/src/test/java/com/shy/rockerview/ExampleUnitTest.java (date 1619405398584)
@@ -0,0 +1,17 @@
+package com.shy.rockerview;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
Index: RockerView/src/main/AndroidManifest.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/src/main/AndroidManifest.xml (date 1619405398451)
+++ RockerView/src/main/AndroidManifest.xml (date 1619405398451)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.shy.rockerview">
+
+</manifest>
\ No newline at end of file
Index: RockerView/proguard-rules.pro
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/proguard-rules.pro (date 1619405398077)
+++ RockerView/proguard-rules.pro (date 1619405398077)
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
Index: RockerView/src/main/res/values/attrs.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/src/main/res/values/attrs.xml (date 1619407383203)
+++ RockerView/src/main/res/values/attrs.xml (date 1619407383203)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!--
+ areaBackground 设置区域背景
+ rockerBackground 设置摇杆的样式
+ rockerScale 设置摇杆的相对于背景的比例
+ rockerSpeedLevel 设置当前位置相对于中心点的距离的比例 如:10 则中心点到边缘的距离分为 10 分越靠外数值越大 0-10
+ rockerCallBackMode 有变化就回调,或者是方向改变才会回调-->
+ <declare-styleable name="RockerView">
+ <attr name="areaBackground" format="color|reference" />
+ <attr name="rockerBackground" format="color|reference" />
+ <attr name="rockerScale" format="float"/>
+ <attr name="rockerSpeedLevel" format="integer" />
+ <attr name="rockerCallBackMode">
+ <flag name="CALL_BACK_MODE_MOVE" value="0" />
+ <flag name="CALL_BACK_MODE_STATE_CHANGE" value="1" />
+ </attr>
+ </declare-styleable>
+</resources>
\ No newline at end of file
Index: RockerView/src/main/java/com/shy/rockerview/MyRockerView.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/src/main/java/com/shy/rockerview/MyRockerView.java (date 1619407328647)
+++ RockerView/src/main/java/com/shy/rockerview/MyRockerView.java (date 1619407328647)
@@ -0,0 +1,731 @@
+package com.shy.rockerview;
+
+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;
+
+public class MyRockerView 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 MyRockerView(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.e("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.e("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 listenr) {
+ mOnDistanceLevelListener = listenr;
+ }
+
+ /**
+ * 摇动方向监听接口
+ */
+ 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;
+ }
+}
\ No newline at end of file
Index: RockerView/build.gradle
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/build.gradle (date 1619417119639)
+++ RockerView/build.gradle (date 1619417119639)
@@ -0,0 +1,42 @@
+plugins {
+ id 'com.android.library'
+
+ id 'com.github.dcendents.android-maven'
+}
+
+group 'com.gitee.cnhnwy'
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ minSdkVersion 17
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.2.1'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
Index: RockerView/.gitignore
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/.gitignore (date 1619405397884)
+++ RockerView/.gitignore (date 1619405397884)
@@ -0,0 +1,1 @@
+/build
\ No newline at end of file
Index: RockerView/src/androidTest/java/com/shy/rockerview/ExampleInstrumentedTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- RockerView/src/androidTest/java/com/shy/rockerview/ExampleInstrumentedTest.java (date 1619405398548)
+++ RockerView/src/androidTest/java/com/shy/rockerview/ExampleInstrumentedTest.java (date 1619405398548)
@@ -0,0 +1,26 @@
+package com.shy.rockerview;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.shy.rockerview.test", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git RockerView/consumer-rules.pro RockerView/consumer-rules.pro
new file mode 100644
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/MingYangFather/RockerView.git
git@gitee.com:MingYangFather/RockerView.git
MingYangFather
RockerView
RockerView
master

搜索帮助