我是在下面两个源码的基础上进行的修改。

如果需要使用可以先看看下面两个代码是否能够满足要求如果可以满足优先使用下面两个。我改动是因为我需要一个方向和级别同时返回的回调而已,所以修改了一下。

RockerView: 虚拟摇杆实现方向: 两个方向、四个方向、八个方向(集成好,可选)实现距离: 自定义分级,摇杆剧中心的距离(XML可设置)实现触发方式:状态改变和移动

AndroidRocker: Android 摇杆

首先实现一个RockView类

package com.example.myesptest.RockView;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.view.MotionEvent;
import android.view.View;import com.example.myesptest.R;public class RockerView extends View {private static final int DEFAULT_SIZE = 400;private static final float DEFAULT_ROCKER_SCALE = 0.5f;//默认半径为背景的1/2private final Paint mAreaBackgroundPaint;private final Paint mRockerPaint;private Point mRockerPosition;private final 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 OnShakeAngleDistanceLevelListener mOnShakeAngleDistanceLevelListener;private DirectionMode mDirectionMode = DirectionMode.DIRECTION_8;private Direction tempDirection = Direction.DIRECTION_CENTER;private Direction temp1Direction = Direction.DIRECTION_CENTER;private float last1Level = 0;private double last1Angle = 0;private float lastDistance = 0;private double lastAngle = 0;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);// 移动区域画笔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) {// XMLmAreaBitmap = 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) {// XMLmRockerBitmap = 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();}@Overrideprotected 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_parentmeasureWidth = widthSize;} else {// wrap_contentmeasureWidth = DEFAULT_SIZE;}if (heightMode == MeasureSpec.EXACTLY) {measureHeight = heightSize;} else {measureHeight = DEFAULT_SIZE;}setMeasuredDimension(measureWidth, measureHeight);}Rect src = new Rect();Rect dst = new Rect();@Overrideprotected 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) {// 图片src.set(0, 0, mAreaBitmap.getWidth(), mAreaBitmap.getHeight());dst.set(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) {// 图片src.set(0, 0, mRockerBitmap.getWidth(), mRockerBitmap.getHeight());dst.set(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);}}@Overridepublic 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);}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(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;// 建立对应 bitmapBitmap 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;temp1Direction = Direction.DIRECTION_CENTER;if (null != mOnAngleChangeListener) {mOnAngleChangeListener.onStart();}if (null != mOnShakeListener) {mOnShakeListener.onStart();}if (null != mOnShakeAngleDistanceLevelListener) {mOnShakeAngleDistanceLevelListener.onStart();}}/*** 回调* 返回参数** @param angle 摇动角度*/private void callBack(double angle, float distance) {if (Math.abs(distance - lastDistance) >= (baseDistance / mDistanceLevel)) {lastDistance = distance;if (null != mOnDistanceLevelListener) {int level = (int) (distance / (baseDistance / mDistanceLevel));mOnDistanceLevelListener.onDistanceLevel(level);}}if (lastAngle != angle) {lastAngle = angle;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;}}}if (null != mOnShakeAngleDistanceLevelListener) {int level = (int) (distance / (baseDistance / mDistanceLevel));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) {// 右mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle) {// 左mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);}break;case DIRECTION_2_VERTICAL:// 上下方向if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle) {// 下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle) {// 上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);}break;case DIRECTION_4_ROTATE_0:// 四个方向if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle) {// 右下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_RIGHT, angle, level);} else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle) {// 左下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_LEFT, angle, level);} else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle) {// 左上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_LEFT, angle, level);} else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle) {// 右上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_RIGHT, angle, level);}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) {// 右mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle) {// 下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle) {// 左mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);} else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle) {// 上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);}break;case DIRECTION_8:// 八个方向if (ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle) {// 右mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle) {// 右下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_RIGHT, angle, level);} else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle) {// 下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle) {// 左下mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_LEFT, angle, level);} else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle) {// 左mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);} else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle) {// 左上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_LEFT, angle, level);} else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle) {// 上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);} else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle) {// 右上mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_RIGHT, angle, level);}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) &&(temp1Direction != Direction.DIRECTION_RIGHT || last1Angle != angle || last1Level != level)) {// 右temp1Direction = Direction.DIRECTION_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle &&(temp1Direction != Direction.DIRECTION_LEFT || last1Angle != angle || last1Level != level)) {// 左temp1Direction = Direction.DIRECTION_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);}break;case DIRECTION_2_VERTICAL:// 上下方向if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle &&(temp1Direction != Direction.DIRECTION_DOWN || last1Angle != angle || last1Level != level)) {// 下temp1Direction = Direction.DIRECTION_DOWN;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle &&(temp1Direction != Direction.DIRECTION_UP || last1Angle != angle || last1Level != level)) {// 上temp1Direction = Direction.DIRECTION_UP;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);}break;case DIRECTION_4_ROTATE_0:// 四个方向if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle &&(temp1Direction != Direction.DIRECTION_DOWN_RIGHT || last1Angle != angle || last1Level != level)) {// 右下temp1Direction = Direction.DIRECTION_DOWN_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_RIGHT, angle, level);} else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle &&(temp1Direction != Direction.DIRECTION_DOWN_LEFT || last1Angle != angle || last1Level != level)) {// 左下temp1Direction = Direction.DIRECTION_DOWN_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_LEFT, angle, level);} else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle &&(temp1Direction != Direction.DIRECTION_UP_LEFT || last1Angle != angle || last1Level != level)) {// 左上temp1Direction = Direction.DIRECTION_UP_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_LEFT, angle, level);} else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle &&(temp1Direction != Direction.DIRECTION_UP_RIGHT || last1Angle != angle || last1Level != level)) {// 右上temp1Direction = Direction.DIRECTION_UP_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_RIGHT, angle, level);}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) &&(temp1Direction != Direction.DIRECTION_RIGHT || last1Angle != angle || last1Level != level)) {// 右temp1Direction = Direction.DIRECTION_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle &&(temp1Direction != Direction.DIRECTION_DOWN || last1Angle != angle || last1Level != level)) {// 下temp1Direction = Direction.DIRECTION_DOWN;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle &&(temp1Direction != Direction.DIRECTION_LEFT || last1Angle != angle || last1Level != level)) {// 左temp1Direction = Direction.DIRECTION_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);} else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle &&(temp1Direction != Direction.DIRECTION_UP || last1Angle != angle || last1Level != level)) {// 上temp1Direction = Direction.DIRECTION_UP;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);}break;case DIRECTION_8:// 八个方向if ((ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle)&& (temp1Direction != Direction.DIRECTION_RIGHT || last1Angle != angle || last1Level != level)) {// 右temp1Direction = Direction.DIRECTION_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_RIGHT, angle, level);} else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle &&(temp1Direction != Direction.DIRECTION_DOWN_RIGHT || last1Angle != angle || last1Level != level)) {// 右下temp1Direction = Direction.DIRECTION_DOWN_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_RIGHT, angle, level);} else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle &&(temp1Direction != Direction.DIRECTION_DOWN || last1Angle != angle || last1Level != level)) {// 下temp1Direction = Direction.DIRECTION_DOWN;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN, angle, level);} else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle &&(temp1Direction != Direction.DIRECTION_DOWN_LEFT || last1Angle != angle || last1Level != level)) {// 左下temp1Direction = Direction.DIRECTION_DOWN_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_DOWN_LEFT, angle, level);} else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle &&(temp1Direction != Direction.DIRECTION_LEFT || last1Angle != angle || last1Level != level)) {// 左temp1Direction = Direction.DIRECTION_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_LEFT, angle, level);} else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle &&(temp1Direction != Direction.DIRECTION_UP_LEFT || last1Angle != angle || last1Level != level)) {// 左上temp1Direction = Direction.DIRECTION_UP_LEFT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_LEFT, angle, level);} else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle &&(temp1Direction != Direction.DIRECTION_UP || last1Angle != angle || last1Level != level)) {// 上temp1Direction = Direction.DIRECTION_UP;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP, angle, level);} else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle &&(temp1Direction != Direction.DIRECTION_UP_RIGHT || last1Angle != angle || last1Level != level)) {// 右上temp1Direction = Direction.DIRECTION_UP_RIGHT;last1Angle = angle;last1Level = level;mOnShakeAngleDistanceLevelListener.onShakeAngleDistanceLevel(Direction.DIRECTION_UP_RIGHT, angle, level);}break;default:break;}}}}/*** 回调* 结束*/private void callBackFinish() {tempDirection = Direction.DIRECTION_CENTER;temp1Direction = Direction.DIRECTION_CENTER;if (null != mOnAngleChangeListener) {mOnAngleChangeListener.onFinish();}if (null != mOnShakeListener) {mOnShakeListener.onFinish();}if (null != mOnShakeAngleDistanceLevelListener) {mOnShakeAngleDistanceLevelListener.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 void setOnShakeAngleDistanceLevelListener(OnShakeAngleDistanceLevelListener listener) {mOnShakeAngleDistanceLevelListener = 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);}/*** 摇动方向+角度+距离*/public interface OnShakeAngleDistanceLevelListener {// 开始void onStart();void onShakeAngleDistanceLevel(Direction direction, double angle, int level);// 结束void onFinish();}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;}
}

然后在value文件夹下创建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><!--areaBackground 设置区域背景rockerBackground 设置摇杆的样式rockerScale 设置摇杆的相对于背景的比例rockerSpeedLevel 设置当前位置相对于中心点的距离的比例  如:10  则中心点到边缘的距离分为 10 分越靠外数值越大 0-10rockerCallBackMode 有变化就回调,或者是方向改变才会回调--><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>

使用非常简单

mViewBinding.rockerView.setOnShakeAngleDistanceLevelListener(new RockerView.OnShakeAngleDistanceLevelListener() {@Overridepublic void onStart() {}@Overridepublic void onShakeAngleDistanceLevel(RockerView.Direction direction, double angle, int level) {LogUtil.d(TAG, "onShakeAngleDistanceLevel:" + direction + ":" + angle + ":" + level);}@Overridepublic void onFinish() {}});

其他具体的回调用法可以看源码可以看readme。

改后的源码

RockerViewUDP: esp32的测试程序,包含摇杆插件,udp通信,esp32的视频传输,对应博文https://mp.csdn.net/mp_blog/creation/editor?spm=1010.2135.3001.4503

android 摇杆控件实现RockerView相关推荐

  1. Android | 自定义摇杆控件

    控件已开源,gitee项目地址:https://gitee.com/y141111/RockerView 先看实现的功能,如不能满足需求,不必浪费宝贵的时间继续阅读 Android摇杆控件 功能 实现 ...

  2. Android开源控件ViewPager Indicator的使用方法

     1月16日厦门 OSC 源创会火热报名中,奖品多多哦   摘要 Android开源控件ViewPager Indicator的使用介绍 ViewPagerIndicator 目录[-] 1. V ...

  3. 日历控件的android代码,Android日历控件PickTime代码实例

    Android日历控件PickTime代码实例 发布时间:2020-10-03 16:05:51 来源:脚本之家 阅读:86 作者:手撕高达的村长 最近做项目,需要设置用户的生日,所以做这样一个功能. ...

  4. android 获取控件高度_安卓开发入门教程UI控件_ImageView

    什么是ImageView ImageView是用于显示图片的UI控件. 基础样例 1.展示本地图片 效果图 代码 <ImageViewandroid:layout_width="wra ...

  5. xamarin.android 控件,Android 库控件 - Xamarin | Microsoft Docs

    Xamarin Android 库控件Xamarin.Android Gallery control 03/15/2018 本文内容 Gallery是一种布局小组件,用于显示水平滚动列表中的项,并将当 ...

  6. android 获取控件在屏幕中的坐标

    今天,简单讲讲android如何获取控件在屏幕中的坐标. 这个其实也很简单,但是昨天做一个功能时,需要功能控件的坐标做一些逻辑操作时,居然不知道怎么做.所以在网上查找了资料后,解决了这个问题.这里记录 ...

  7. Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)

    目录 前言 本文涉及文章 其他相关文章 1.数据准备 1.1 数据来源 2.曲线展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3.曲线完善 3.1 图表背景. ...

  8. Android AutoCompleteTextView控件实现类似百度搜索提示,限制输入数字长度

    Android AutoCompleteTextView 控件实现类似被搜索提示,效果如下 1.首先贴出布局代码 activity_main.xml: <?xml version="1 ...

  9. android控件使用大全,Android常见控件使用详解

    本文实例为大家分享了六种Android常见控件的使用方法,供大家参考,具体内容如下 1.TextView 主要用于界面上显示一段文本信息 2.Button 用于和用户交互的一个按钮控件 //为Butt ...

最新文章

  1. mysql外键无法删除_mysql外键无法删除数据的情况
  2. 一个简单的因数分解java代码
  3. Angular Universal 的演进历史
  4. 哈希表(闭散列、拉链法--哈希桶)
  5. why I need a flow learn note.
  6. PHP监測memcache服务端的执行状况
  7. Hadoop系列之Aggregate用法
  8. 编译的html帮助文件(.chm)打不开,chm文件无法打开怎么办
  9. 【无线芯片解读】2.4G专题:(SI24R1简版)Ci24R1
  10. 2018年交通运行年报发布,深圳交通高质量发展取得新突破
  11. 快速入门了解后端网络方面必备知识
  12. 从数字0~99999中,数字“8”一共出现了多少次
  13. 《沈剑架构师训练营》第7章 - 架构解耦
  14. MATLAB imagesc中将nan、inf或者特定值设为白色(或透明色)
  15. 计算机二级各个科目的区别,计算机二级考试的各个科目的内容及区别
  16. 【Linux共享内存】
  17. 新人学Kungfu功夫开源量化,应该这样入手
  18. 精通脚本黑客--电骡下载
  19. 队列及其应用-取牌游戏
  20. 闪萌联手风语筑将推出国内首个NFT表情包数字藏品

热门文章

  1. 题7.15:要求输入一个职工号,用折半查找法查找出该职工的姓名,从主函数输入要查找的职工号,输出该职工姓名。按职工号由小到大顺序排序,姓名顺序也随之调整
  2. 763.Partition Labels (Medium)
  3. Linux per_cpu机制的详解
  4. android yuv旋转,针对移动端摄像头yuv旋转、裁剪、镜像、格式转换算法的实现
  5. 5.15 vs2019 静态编译_Go Web 开发如何优雅的包含静态资源文件?
  6. MANIFEST.MF文件详解
  7. 【译转】智能化css检测法,好优化拒绝冗杂代码
  8. 砥砺前行20载,他见证了中国制造信息化的成长
  9. php获取qq号,php实现只需要一个QQ号就可以获得用户信息
  10. 100多个神奇网站,学习娱乐大全,总有一款适合你。。。