├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── KqwRockerLibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── kongqw │ │ └── rockerlibrary │ │ ├── Logger.java │ │ └── view │ │ └── RockerView.java │ └── res │ └── values │ ├── attrs.xml │ └── strings.xml ├── Readme.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── kongqw │ │ └── kqwrockerdemo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── kongqw │ │ │ └── kqwrockerdemo │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable │ │ ├── area_bg.png │ │ ├── default_area_bg.xml │ │ ├── default_rocker_bg.xml │ │ └── rocker_bg.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── view_big.png │ │ └── view_small.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── view_big.png │ │ └── view_small.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── view_big.png │ │ └── view_small.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── kongqw │ └── kqwrockerdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | KqwRockerDemo -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /KqwRockerLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /KqwRockerLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 15 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:23.4.0' 25 | } 26 | -------------------------------------------------------------------------------- /KqwRockerLibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /KqwRockerLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /KqwRockerLibrary/src/main/java/com/kongqw/rockerlibrary/Logger.java: -------------------------------------------------------------------------------- 1 | package com.kongqw.rockerlibrary; 2 | 3 | /** 4 | * Created by kqw on 2016/9/1. 5 | * Logger 6 | */ 7 | public class Logger { 8 | 9 | public static void i(String tag, String msg) { 10 | // Log.i(tag, msg); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /KqwRockerLibrary/src/main/java/com/kongqw/rockerlibrary/view/RockerView.java: -------------------------------------------------------------------------------- 1 | package com.kongqw.rockerlibrary.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Canvas; 7 | import android.graphics.Color; 8 | import android.graphics.Paint; 9 | import android.graphics.PixelFormat; 10 | import android.graphics.Point; 11 | import android.graphics.Rect; 12 | import android.graphics.drawable.BitmapDrawable; 13 | import android.graphics.drawable.ColorDrawable; 14 | import android.graphics.drawable.Drawable; 15 | import android.graphics.drawable.GradientDrawable; 16 | import android.util.AttributeSet; 17 | import android.view.MotionEvent; 18 | import android.view.View; 19 | 20 | import com.kongqw.rockerlibrary.Logger; 21 | import com.kongqw.rockerlibrary.R; 22 | 23 | /** 24 | * Created by kqw on 2016/8/30. 25 | * 摇杆控件 26 | */ 27 | public class RockerView extends View { 28 | private static final String TAG = "RockerView"; 29 | 30 | private static final int DEFAULT_SIZE = 400; 31 | private static final int DEFAULT_ROCKER_RADIUS = DEFAULT_SIZE / 8; 32 | 33 | private Paint mAreaBackgroundPaint; 34 | private Paint mRockerPaint; 35 | 36 | private Point mRockerPosition; 37 | private Point mCenterPoint; 38 | 39 | private int mAreaRadius; 40 | private int mRockerRadius; 41 | 42 | private CallBackMode mCallBackMode = CallBackMode.CALL_BACK_MODE_MOVE; 43 | private OnAngleChangeListener mOnAngleChangeListener; 44 | private OnShakeListener mOnShakeListener; 45 | 46 | private DirectionMode mDirectionMode; 47 | private Direction tempDirection = Direction.DIRECTION_CENTER; 48 | // 角度 49 | private static final double ANGLE_0 = 0; 50 | private static final double ANGLE_360 = 360; 51 | // 360°水平方向平分2份的边缘角度 52 | private static final double ANGLE_HORIZONTAL_2D_OF_0P = 90; 53 | private static final double ANGLE_HORIZONTAL_2D_OF_1P = 270; 54 | // 360°垂直方向平分2份的边缘角度 55 | private static final double ANGLE_VERTICAL_2D_OF_0P = 0; 56 | private static final double ANGLE_VERTICAL_2D_OF_1P = 180; 57 | // 360°平分4份的边缘角度 58 | private static final double ANGLE_4D_OF_0P = 0; 59 | private static final double ANGLE_4D_OF_1P = 90; 60 | private static final double ANGLE_4D_OF_2P = 180; 61 | private static final double ANGLE_4D_OF_3P = 270; 62 | // 360°平分4份的边缘角度(旋转45度) 63 | private static final double ANGLE_ROTATE45_4D_OF_0P = 45; 64 | private static final double ANGLE_ROTATE45_4D_OF_1P = 135; 65 | private static final double ANGLE_ROTATE45_4D_OF_2P = 225; 66 | private static final double ANGLE_ROTATE45_4D_OF_3P = 315; 67 | 68 | // 360°平分8份的边缘角度 69 | private static final double ANGLE_8D_OF_0P = 22.5; 70 | private static final double ANGLE_8D_OF_1P = 67.5; 71 | private static final double ANGLE_8D_OF_2P = 112.5; 72 | private static final double ANGLE_8D_OF_3P = 157.5; 73 | private static final double ANGLE_8D_OF_4P = 202.5; 74 | private static final double ANGLE_8D_OF_5P = 247.5; 75 | private static final double ANGLE_8D_OF_6P = 292.5; 76 | private static final double ANGLE_8D_OF_7P = 337.5; 77 | 78 | // 摇杆可移动区域背景 79 | private static final int AREA_BACKGROUND_MODE_PIC = 0; 80 | private static final int AREA_BACKGROUND_MODE_COLOR = 1; 81 | private static final int AREA_BACKGROUND_MODE_XML = 2; 82 | private static final int AREA_BACKGROUND_MODE_DEFAULT = 3; 83 | private int mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; 84 | private Bitmap mAreaBitmap; 85 | private int mAreaColor; 86 | // 摇杆背景 87 | private static final int ROCKER_BACKGROUND_MODE_PIC = 4; 88 | private static final int ROCKER_BACKGROUND_MODE_COLOR = 5; 89 | private static final int ROCKER_BACKGROUND_MODE_XML = 6; 90 | private static final int ROCKER_BACKGROUND_MODE_DEFAULT = 7; 91 | private int mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; 92 | private Bitmap mRockerBitmap; 93 | private int mRockerColor; 94 | 95 | 96 | public RockerView(Context context, AttributeSet attrs) { 97 | super(context, attrs); 98 | 99 | // 获取自定义属性 100 | initAttribute(context, attrs); 101 | 102 | if (isInEditMode()) { 103 | Logger.i(TAG, "RockerView: isInEditMode"); 104 | } 105 | 106 | // 移动区域画笔 107 | mAreaBackgroundPaint = new Paint(); 108 | mAreaBackgroundPaint.setAntiAlias(true); 109 | 110 | // 摇杆画笔 111 | mRockerPaint = new Paint(); 112 | mRockerPaint.setAntiAlias(true); 113 | 114 | // 中心点 115 | mCenterPoint = new Point(); 116 | // 摇杆位置 117 | mRockerPosition = new Point(); 118 | } 119 | 120 | /** 121 | * 获取属性 122 | * 123 | * @param context context 124 | * @param attrs attrs 125 | */ 126 | private void initAttribute(Context context, AttributeSet attrs) { 127 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RockerView); 128 | 129 | // 可移动区域背景 130 | Drawable areaBackground = typedArray.getDrawable(R.styleable.RockerView_areaBackground); 131 | if (null != areaBackground) { 132 | // 设置了背景 133 | if (areaBackground instanceof BitmapDrawable) { 134 | // 设置了一张图片 135 | mAreaBitmap = ((BitmapDrawable) areaBackground).getBitmap(); 136 | mAreaBackgroundMode = AREA_BACKGROUND_MODE_PIC; 137 | } else if (areaBackground instanceof GradientDrawable) { 138 | // XML 139 | mAreaBitmap = drawable2Bitmap(areaBackground); 140 | mAreaBackgroundMode = AREA_BACKGROUND_MODE_XML; 141 | } else if (areaBackground instanceof ColorDrawable) { 142 | // 色值 143 | mAreaColor = ((ColorDrawable) areaBackground).getColor(); 144 | mAreaBackgroundMode = AREA_BACKGROUND_MODE_COLOR; 145 | } else { 146 | // 其他形式 147 | mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; 148 | } 149 | } else { 150 | // 没有设置背景 151 | mAreaBackgroundMode = AREA_BACKGROUND_MODE_DEFAULT; 152 | } 153 | // 摇杆背景 154 | Drawable rockerBackground = typedArray.getDrawable(R.styleable.RockerView_rockerBackground); 155 | if (null != rockerBackground) { 156 | // 设置了摇杆背景 157 | if (rockerBackground instanceof BitmapDrawable) { 158 | // 图片 159 | mRockerBitmap = ((BitmapDrawable) rockerBackground).getBitmap(); 160 | mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_PIC; 161 | } else if (rockerBackground instanceof GradientDrawable) { 162 | // XML 163 | mRockerBitmap = drawable2Bitmap(rockerBackground); 164 | mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_XML; 165 | } else if (rockerBackground instanceof ColorDrawable) { 166 | // 色值 167 | mRockerColor = ((ColorDrawable) rockerBackground).getColor(); 168 | mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_COLOR; 169 | } else { 170 | // 其他形式 171 | mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; 172 | } 173 | } else { 174 | // 没有设置摇杆背景 175 | mRockerBackgroundMode = ROCKER_BACKGROUND_MODE_DEFAULT; 176 | } 177 | 178 | // 摇杆半径 179 | mRockerRadius = typedArray.getDimensionPixelOffset(R.styleable.RockerView_rockerRadius, DEFAULT_ROCKER_RADIUS); 180 | 181 | Logger.i(TAG, "initAttribute: mAreaBackground = " + areaBackground + " mRockerBackground = " + rockerBackground + " mRockerRadius = " + mRockerRadius); 182 | typedArray.recycle(); 183 | } 184 | 185 | @Override 186 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 187 | int measureWidth, measureHeight; 188 | 189 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 190 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 191 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 192 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 193 | 194 | if (widthMode == MeasureSpec.EXACTLY) { 195 | // 具体的值和match_parent 196 | measureWidth = widthSize; 197 | } else { 198 | // wrap_content 199 | measureWidth = DEFAULT_SIZE; 200 | } 201 | if (heightMode == MeasureSpec.EXACTLY) { 202 | measureHeight = heightSize; 203 | } else { 204 | measureHeight = DEFAULT_SIZE; 205 | } 206 | Logger.i(TAG, "onMeasure: --------------------------------------"); 207 | Logger.i(TAG, "onMeasure: widthMeasureSpec = " + widthMeasureSpec + " heightMeasureSpec = " + heightMeasureSpec); 208 | Logger.i(TAG, "onMeasure: widthMode = " + widthMode + " measureWidth = " + widthSize); 209 | Logger.i(TAG, "onMeasure: heightMode = " + heightMode + " measureHeight = " + widthSize); 210 | Logger.i(TAG, "onMeasure: measureWidth = " + measureWidth + " measureHeight = " + measureHeight); 211 | setMeasuredDimension(measureWidth, measureHeight); 212 | } 213 | 214 | @Override 215 | protected void onDraw(Canvas canvas) { 216 | super.onDraw(canvas); 217 | 218 | int measuredWidth = getMeasuredWidth(); 219 | int measuredHeight = getMeasuredHeight(); 220 | 221 | int cx = measuredWidth / 2; 222 | int cy = measuredHeight / 2; 223 | // 中心点 224 | mCenterPoint.set(cx, cy); 225 | // 可移动区域的半径 226 | mAreaRadius = (measuredWidth <= measuredHeight) ? cx : cy; 227 | 228 | // 摇杆位置 229 | if (0 == mRockerPosition.x || 0 == mRockerPosition.y) { 230 | mRockerPosition.set(mCenterPoint.x, mCenterPoint.y); 231 | } 232 | 233 | // 画可移动区域 234 | if (AREA_BACKGROUND_MODE_PIC == mAreaBackgroundMode || AREA_BACKGROUND_MODE_XML == mAreaBackgroundMode) { 235 | // 图片 236 | Rect src = new Rect(0, 0, mAreaBitmap.getWidth(), mAreaBitmap.getHeight()); 237 | Rect dst = new Rect(mCenterPoint.x - mAreaRadius, mCenterPoint.y - mAreaRadius, mCenterPoint.x + mAreaRadius, mCenterPoint.y + mAreaRadius); 238 | canvas.drawBitmap(mAreaBitmap, src, dst, mAreaBackgroundPaint); 239 | } else if (AREA_BACKGROUND_MODE_COLOR == mAreaBackgroundMode) { 240 | // 色值 241 | mAreaBackgroundPaint.setColor(mAreaColor); 242 | canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mAreaRadius, mAreaBackgroundPaint); 243 | } else { 244 | // 其他或者未设置 245 | mAreaBackgroundPaint.setColor(Color.GRAY); 246 | canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mAreaRadius, mAreaBackgroundPaint); 247 | } 248 | 249 | // 画摇杆 250 | if (ROCKER_BACKGROUND_MODE_PIC == mRockerBackgroundMode || ROCKER_BACKGROUND_MODE_XML == mRockerBackgroundMode) { 251 | // 图片 252 | Rect src = new Rect(0, 0, mRockerBitmap.getWidth(), mRockerBitmap.getHeight()); 253 | Rect dst = new Rect(mRockerPosition.x - mRockerRadius, mRockerPosition.y - mRockerRadius, mRockerPosition.x + mRockerRadius, mRockerPosition.y + mRockerRadius); 254 | canvas.drawBitmap(mRockerBitmap, src, dst, mRockerPaint); 255 | } else if (ROCKER_BACKGROUND_MODE_COLOR == mRockerBackgroundMode) { 256 | // 色值 257 | mRockerPaint.setColor(mRockerColor); 258 | canvas.drawCircle(mRockerPosition.x, mRockerPosition.y, mRockerRadius, mRockerPaint); 259 | } else { 260 | // 其他或者未设置 261 | mRockerPaint.setColor(Color.RED); 262 | canvas.drawCircle(mRockerPosition.x, mRockerPosition.y, mRockerRadius, mRockerPaint); 263 | } 264 | } 265 | 266 | @Override 267 | public boolean onTouchEvent(MotionEvent event) { 268 | switch (event.getAction()) { 269 | case MotionEvent.ACTION_DOWN:// 按下 270 | // 回调 开始 271 | callBackStart(); 272 | case MotionEvent.ACTION_MOVE:// 移动 273 | float moveX = event.getX(); 274 | float moveY = event.getY(); 275 | mRockerPosition = getRockerPositionPoint(mCenterPoint, new Point((int) moveX, (int) moveY), mAreaRadius, mRockerRadius); 276 | moveRocker(mRockerPosition.x, mRockerPosition.y); 277 | break; 278 | case MotionEvent.ACTION_UP:// 抬起 279 | case MotionEvent.ACTION_CANCEL:// 移出区域 280 | // 回调 结束 281 | callBackFinish(); 282 | float upX = event.getX(); 283 | float upY = event.getY(); 284 | moveRocker(mCenterPoint.x, mCenterPoint.y); 285 | Logger.i(TAG, "onTouchEvent: 抬起位置 : x = " + upX + " y = " + upY); 286 | break; 287 | } 288 | return true; 289 | } 290 | 291 | /** 292 | * 获取摇杆实际要显示的位置(点) 293 | * 294 | * @param centerPoint 中心点 295 | * @param touchPoint 触摸点 296 | * @param regionRadius 摇杆可活动区域半径 297 | * @param rockerRadius 摇杆半径 298 | * @return 摇杆实际显示的位置(点) 299 | */ 300 | private Point getRockerPositionPoint(Point centerPoint, Point touchPoint, float regionRadius, float rockerRadius) { 301 | // 两点在X轴的距离 302 | float lenX = (float) (touchPoint.x - centerPoint.x); 303 | // 两点在Y轴距离 304 | float lenY = (float) (touchPoint.y - centerPoint.y); 305 | // 两点距离 306 | float lenXY = (float) Math.sqrt((double) (lenX * lenX + lenY * lenY)); 307 | // 计算弧度 308 | double radian = Math.acos(lenX / lenXY) * (touchPoint.y < centerPoint.y ? -1 : 1); 309 | // 计算角度 310 | double angle = radian2Angle(radian); 311 | 312 | // 回调 返回参数 313 | callBack(angle); 314 | 315 | Logger.i(TAG, "getRockerPositionPoint: 角度 :" + angle); 316 | if (lenXY + rockerRadius <= regionRadius) { // 触摸位置在可活动范围内 317 | return touchPoint; 318 | } else { // 触摸位置在可活动范围以外 319 | // 计算要显示的位置 320 | int showPointX = (int) (centerPoint.x + (regionRadius - rockerRadius) * Math.cos(radian)); 321 | int showPointY = (int) (centerPoint.y + (regionRadius - rockerRadius) * Math.sin(radian)); 322 | return new Point(showPointX, showPointY); 323 | } 324 | } 325 | 326 | /** 327 | * 移动摇杆到指定位置 328 | * 329 | * @param x x坐标 330 | * @param y y坐标 331 | */ 332 | private void moveRocker(float x, float y) { 333 | mRockerPosition.set((int) x, (int) y); 334 | Logger.i(TAG, "onTouchEvent: 移动位置 : x = " + mRockerPosition.x + " y = " + mRockerPosition.y); 335 | invalidate(); 336 | } 337 | 338 | /** 339 | * 弧度转角度 340 | * 341 | * @param radian 弧度 342 | * @return 角度[0, 360) 343 | */ 344 | private double radian2Angle(double radian) { 345 | double tmp = Math.round(radian / Math.PI * 180); 346 | return tmp >= 0 ? tmp : 360 + tmp; 347 | } 348 | 349 | /** 350 | * Drawable 转 Bitmap 351 | * 352 | * @param drawable Drawable 353 | * @return Bitmap 354 | */ 355 | private Bitmap drawable2Bitmap(Drawable drawable) { 356 | // 取 drawable 的长宽 357 | int width = drawable.getIntrinsicWidth(); 358 | int height = drawable.getIntrinsicHeight(); 359 | // 取 drawable 的颜色格式 360 | Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 361 | // 建立对应 bitmap 362 | Bitmap bitmap = Bitmap.createBitmap(width, height, config); 363 | Canvas canvas = new Canvas(bitmap); 364 | drawable.setBounds(0, 0, width, height); 365 | drawable.draw(canvas); 366 | return bitmap; 367 | } 368 | 369 | /** 370 | * 回调 371 | * 开始 372 | */ 373 | private void callBackStart() { 374 | tempDirection = Direction.DIRECTION_CENTER; 375 | if (null != mOnAngleChangeListener) { 376 | mOnAngleChangeListener.onStart(); 377 | } 378 | if (null != mOnShakeListener) { 379 | mOnShakeListener.onStart(); 380 | } 381 | } 382 | 383 | /** 384 | * 回调 385 | * 返回参数 386 | * 387 | * @param angle 摇动角度 388 | */ 389 | private void callBack(double angle) { 390 | if (null != mOnAngleChangeListener) { 391 | mOnAngleChangeListener.angle(angle); 392 | } 393 | if (null != mOnShakeListener) { 394 | if (CallBackMode.CALL_BACK_MODE_MOVE == mCallBackMode) { 395 | switch (mDirectionMode) { 396 | case DIRECTION_2_HORIZONTAL:// 左右方向 397 | if (ANGLE_0 <= angle && ANGLE_HORIZONTAL_2D_OF_0P > angle || ANGLE_HORIZONTAL_2D_OF_1P <= angle && ANGLE_360 > angle) { 398 | // 右 399 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 400 | } else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle) { 401 | // 左 402 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 403 | } 404 | break; 405 | case DIRECTION_2_VERTICAL:// 上下方向 406 | if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle) { 407 | // 下 408 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 409 | } else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle) { 410 | // 上 411 | mOnShakeListener.direction(Direction.DIRECTION_UP); 412 | } 413 | break; 414 | case DIRECTION_4_ROTATE_0:// 四个方向 415 | if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle) { 416 | // 右下 417 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); 418 | } else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle) { 419 | // 左下 420 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); 421 | } else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle) { 422 | // 左上 423 | mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); 424 | } else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle) { 425 | // 右上 426 | mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); 427 | } 428 | break; 429 | case DIRECTION_4_ROTATE_45:// 四个方向 旋转45度 430 | if (ANGLE_0 <= angle && ANGLE_ROTATE45_4D_OF_0P > angle || ANGLE_ROTATE45_4D_OF_3P <= angle && ANGLE_360 > angle) { 431 | // 右 432 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 433 | } else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle) { 434 | // 下 435 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 436 | } else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle) { 437 | // 左 438 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 439 | } else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle) { 440 | // 上 441 | mOnShakeListener.direction(Direction.DIRECTION_UP); 442 | } 443 | break; 444 | case DIRECTION_8:// 八个方向 445 | if (ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle) { 446 | // 右 447 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 448 | } else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle) { 449 | // 右下 450 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); 451 | } else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle) { 452 | // 下 453 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 454 | } else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle) { 455 | // 左下 456 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); 457 | } else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle) { 458 | // 左 459 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 460 | } else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle) { 461 | // 左上 462 | mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); 463 | } else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle) { 464 | // 上 465 | mOnShakeListener.direction(Direction.DIRECTION_UP); 466 | } else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle) { 467 | // 右上 468 | mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); 469 | } 470 | break; 471 | default: 472 | break; 473 | } 474 | } else if (CallBackMode.CALL_BACK_MODE_STATE_CHANGE == mCallBackMode) { 475 | switch (mDirectionMode) { 476 | case DIRECTION_2_HORIZONTAL:// 左右方向 477 | if ((ANGLE_0 <= angle && ANGLE_HORIZONTAL_2D_OF_0P > angle || ANGLE_HORIZONTAL_2D_OF_1P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { 478 | // 右 479 | tempDirection = Direction.DIRECTION_RIGHT; 480 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 481 | } else if (ANGLE_HORIZONTAL_2D_OF_0P <= angle && ANGLE_HORIZONTAL_2D_OF_1P > angle && tempDirection != Direction.DIRECTION_LEFT) { 482 | // 左 483 | tempDirection = Direction.DIRECTION_LEFT; 484 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 485 | } 486 | break; 487 | case DIRECTION_2_VERTICAL:// 上下方向 488 | if (ANGLE_VERTICAL_2D_OF_0P <= angle && ANGLE_VERTICAL_2D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN) { 489 | // 下 490 | tempDirection = Direction.DIRECTION_DOWN; 491 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 492 | } else if (ANGLE_VERTICAL_2D_OF_1P <= angle && ANGLE_360 > angle && tempDirection != Direction.DIRECTION_UP) { 493 | // 上 494 | tempDirection = Direction.DIRECTION_UP; 495 | mOnShakeListener.direction(Direction.DIRECTION_UP); 496 | } 497 | break; 498 | case DIRECTION_4_ROTATE_0:// 四个方向 499 | if (ANGLE_4D_OF_0P <= angle && ANGLE_4D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN_RIGHT) { 500 | // 右下 501 | tempDirection = Direction.DIRECTION_DOWN_RIGHT; 502 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); 503 | } else if (ANGLE_4D_OF_1P <= angle && ANGLE_4D_OF_2P > angle && tempDirection != Direction.DIRECTION_DOWN_LEFT) { 504 | // 左下 505 | tempDirection = Direction.DIRECTION_DOWN_LEFT; 506 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); 507 | } else if (ANGLE_4D_OF_2P <= angle && ANGLE_4D_OF_3P > angle && tempDirection != Direction.DIRECTION_UP_LEFT) { 508 | // 左上 509 | tempDirection = Direction.DIRECTION_UP_LEFT; 510 | mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); 511 | } else if (ANGLE_4D_OF_3P <= angle && ANGLE_360 > angle && tempDirection != Direction.DIRECTION_UP_RIGHT) { 512 | // 右上 513 | tempDirection = Direction.DIRECTION_UP_RIGHT; 514 | mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); 515 | } 516 | break; 517 | case DIRECTION_4_ROTATE_45:// 四个方向 旋转45度 518 | if ((ANGLE_0 <= angle && ANGLE_ROTATE45_4D_OF_0P > angle || ANGLE_ROTATE45_4D_OF_3P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { 519 | // 右 520 | tempDirection = Direction.DIRECTION_RIGHT; 521 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 522 | } else if (ANGLE_ROTATE45_4D_OF_0P <= angle && ANGLE_ROTATE45_4D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN) { 523 | // 下 524 | tempDirection = Direction.DIRECTION_DOWN; 525 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 526 | } else if (ANGLE_ROTATE45_4D_OF_1P <= angle && ANGLE_ROTATE45_4D_OF_2P > angle && tempDirection != Direction.DIRECTION_LEFT) { 527 | // 左 528 | tempDirection = Direction.DIRECTION_LEFT; 529 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 530 | } else if (ANGLE_ROTATE45_4D_OF_2P <= angle && ANGLE_ROTATE45_4D_OF_3P > angle && tempDirection != Direction.DIRECTION_UP) { 531 | // 上 532 | tempDirection = Direction.DIRECTION_UP; 533 | mOnShakeListener.direction(Direction.DIRECTION_UP); 534 | } 535 | break; 536 | case DIRECTION_8:// 八个方向 537 | if ((ANGLE_0 <= angle && ANGLE_8D_OF_0P > angle || ANGLE_8D_OF_7P <= angle && ANGLE_360 > angle) && tempDirection != Direction.DIRECTION_RIGHT) { 538 | // 右 539 | tempDirection = Direction.DIRECTION_RIGHT; 540 | mOnShakeListener.direction(Direction.DIRECTION_RIGHT); 541 | } else if (ANGLE_8D_OF_0P <= angle && ANGLE_8D_OF_1P > angle && tempDirection != Direction.DIRECTION_DOWN_RIGHT) { 542 | // 右下 543 | tempDirection = Direction.DIRECTION_DOWN_RIGHT; 544 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_RIGHT); 545 | } else if (ANGLE_8D_OF_1P <= angle && ANGLE_8D_OF_2P > angle && tempDirection != Direction.DIRECTION_DOWN) { 546 | // 下 547 | tempDirection = Direction.DIRECTION_DOWN; 548 | mOnShakeListener.direction(Direction.DIRECTION_DOWN); 549 | } else if (ANGLE_8D_OF_2P <= angle && ANGLE_8D_OF_3P > angle && tempDirection != Direction.DIRECTION_DOWN_LEFT) { 550 | // 左下 551 | tempDirection = Direction.DIRECTION_DOWN_LEFT; 552 | mOnShakeListener.direction(Direction.DIRECTION_DOWN_LEFT); 553 | } else if (ANGLE_8D_OF_3P <= angle && ANGLE_8D_OF_4P > angle && tempDirection != Direction.DIRECTION_LEFT) { 554 | // 左 555 | tempDirection = Direction.DIRECTION_LEFT; 556 | mOnShakeListener.direction(Direction.DIRECTION_LEFT); 557 | } else if (ANGLE_8D_OF_4P <= angle && ANGLE_8D_OF_5P > angle && tempDirection != Direction.DIRECTION_UP_LEFT) { 558 | // 左上 559 | tempDirection = Direction.DIRECTION_UP_LEFT; 560 | mOnShakeListener.direction(Direction.DIRECTION_UP_LEFT); 561 | } else if (ANGLE_8D_OF_5P <= angle && ANGLE_8D_OF_6P > angle && tempDirection != Direction.DIRECTION_UP) { 562 | // 上 563 | tempDirection = Direction.DIRECTION_UP; 564 | mOnShakeListener.direction(Direction.DIRECTION_UP); 565 | } else if (ANGLE_8D_OF_6P <= angle && ANGLE_8D_OF_7P > angle && tempDirection != Direction.DIRECTION_UP_RIGHT) { 566 | // 右上 567 | tempDirection = Direction.DIRECTION_UP_RIGHT; 568 | mOnShakeListener.direction(Direction.DIRECTION_UP_RIGHT); 569 | } 570 | break; 571 | default: 572 | break; 573 | } 574 | } 575 | } 576 | } 577 | 578 | /** 579 | * 回调 580 | * 结束 581 | */ 582 | private void callBackFinish() { 583 | tempDirection = Direction.DIRECTION_CENTER; 584 | if (null != mOnAngleChangeListener) { 585 | mOnAngleChangeListener.onFinish(); 586 | } 587 | if (null != mOnShakeListener) { 588 | mOnShakeListener.onFinish(); 589 | } 590 | } 591 | 592 | /** 593 | * 回调模式 594 | */ 595 | public enum CallBackMode { 596 | // 有移动就立刻回调 597 | CALL_BACK_MODE_MOVE, 598 | // 只有状态变化的时候才回调 599 | CALL_BACK_MODE_STATE_CHANGE 600 | } 601 | 602 | /** 603 | * 设置回调模式 604 | * 605 | * @param mode 回调模式 606 | */ 607 | public void setCallBackMode(CallBackMode mode) { 608 | mCallBackMode = mode; 609 | } 610 | 611 | /** 612 | * 摇杆支持几个方向 613 | */ 614 | public enum DirectionMode { 615 | DIRECTION_2_HORIZONTAL,// 横向 左右两个方向 616 | DIRECTION_2_VERTICAL, // 纵向 上下两个方向 617 | DIRECTION_4_ROTATE_0, // 四个方向 618 | DIRECTION_4_ROTATE_45, // 四个方向 旋转45度 619 | DIRECTION_8 // 八个方向 620 | } 621 | 622 | /** 623 | * 方向 624 | */ 625 | public enum Direction { 626 | DIRECTION_LEFT, // 左 627 | DIRECTION_RIGHT, // 右 628 | DIRECTION_UP, // 上 629 | DIRECTION_DOWN, // 下 630 | DIRECTION_UP_LEFT, // 左上 631 | DIRECTION_UP_RIGHT, // 右上 632 | DIRECTION_DOWN_LEFT, // 左下 633 | DIRECTION_DOWN_RIGHT, // 右下 634 | DIRECTION_CENTER // 中间 635 | } 636 | 637 | /** 638 | * 添加摇杆摇动角度的监听 639 | * 640 | * @param listener 回调接口 641 | */ 642 | public void setOnAngleChangeListener(OnAngleChangeListener listener) { 643 | mOnAngleChangeListener = listener; 644 | } 645 | 646 | /** 647 | * 添加摇动的监听 648 | * 649 | * @param directionMode 监听的方向 650 | * @param listener 回调 651 | */ 652 | public void setOnShakeListener(DirectionMode directionMode, OnShakeListener listener) { 653 | mDirectionMode = directionMode; 654 | mOnShakeListener = listener; 655 | } 656 | 657 | /** 658 | * 摇动方向监听接口 659 | */ 660 | public interface OnShakeListener { 661 | // 开始 662 | void onStart(); 663 | 664 | /** 665 | * 摇动方向 666 | * 667 | * @param direction 方向 668 | */ 669 | void direction(Direction direction); 670 | 671 | // 结束 672 | void onFinish(); 673 | } 674 | 675 | /** 676 | * 摇动角度的监听接口 677 | */ 678 | public interface OnAngleChangeListener { 679 | // 开始 680 | void onStart(); 681 | 682 | /** 683 | * 摇杆角度变化 684 | * 685 | * @param angle 角度[0,360) 686 | */ 687 | void angle(double angle); 688 | 689 | // 结束 690 | void onFinish(); 691 | } 692 | } 693 | -------------------------------------------------------------------------------- /KqwRockerLibrary/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /KqwRockerLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | KqwRockerLibrary 3 | 4 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | --- 2 | 转载请说明出处! 3 | 作者:[kqw攻城狮](http://kongqw.github.io/about/index.html) 4 | 出处:[个人站](http://kongqw.com/2016/09/01/2016-09-01-Android%E8%87%AA%E5%AE%9A%E4%B9%89%E6%91%87%E6%9D%86/) | [CSDN](http://blog.csdn.net/q4878802/article/details/52402529) 5 | 6 | --- 7 | 8 | [![](https://jitpack.io/v/kongqw/AndroidRocker.svg)](https://jitpack.io/#kongqw/AndroidRocker) 9 | 10 | # 部署 11 | 12 | To get a Git project into your build: 13 | 14 | Step 1. Add the JitPack repository to your build file 15 | 16 | Add it in your root build.gradle at the end of repositories: 17 | 18 | ``` gradle 19 | allprojects { 20 | repositories { 21 | ... 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | ``` 26 | 27 | Step 2. Add the dependency 28 | 29 | ``` gradle 30 | dependencies { 31 | compile 'com.github.kongqw:AndroidRocker:1.0.1' 32 | } 33 | ``` 34 | 35 | # 使用 36 | 37 | ## XML 38 | 39 | ``` xml 40 | 47 | ``` 48 | 49 | ## Activity 50 | 51 | ### 初始化 52 | 53 | ``` java 54 | RockerView rockerView = (RockerView) findViewById(R.id.rockerView); 55 | ``` 56 | 57 | ### 设置回调模式 58 | 59 | ``` java 60 | // 设置回调模式 61 | rockerView.setCallBackMode(RockerView.CallBackMode.CALL_BACK_MODE_STATE_CHANGE); 62 | ``` 63 | 64 | ### 监听摇动方向 65 | 66 | ``` java 67 | // 监听摇动方向 68 | rockerView.setOnShakeListener(RockerView.DirectionMode.DIRECTION_8, new RockerView.OnShakeListener() { 69 | @Override 70 | public void onStart() { 71 | mLogLeft.setText(null); 72 | } 73 | 74 | @Override 75 | public void direction(RockerView.Direction direction) { 76 | mLogLeft.setText("摇动方向 : " + getDirection(direction)); 77 | } 78 | 79 | @Override 80 | public void onFinish() { 81 | mLogLeft.setText(null); 82 | } 83 | }); 84 | ``` 85 | 86 | ### 监听摇动角度 87 | 88 | ``` java 89 | // 监听摇动角度 90 | rockerViewRight.setOnAngleChangeListener(new RockerView.OnAngleChangeListener() { 91 | @Override 92 | public void onStart() { 93 | mLogRight.setText(null); 94 | } 95 | 96 | @Override 97 | public void angle(double angle) { 98 | mLogRight.setText("摇动角度 : " + angle); 99 | } 100 | 101 | @Override 102 | public void onFinish() { 103 | mLogRight.setText(null); 104 | } 105 | }); 106 | ``` 107 | 108 | ------------------------- 109 | 110 | # 效果图 111 | 112 | ![效果图](http://img.blog.csdn.net/20160901182847783) 113 | 114 | ![效果图](http://img.blog.csdn.net/20160901182902455) 115 | 116 | # 源码 117 | 118 | [KqwRockerDemo](https://github.com/kongqw/KqwRockerDemo) 119 | 120 | 喜欢就给个`star`,谢谢! 121 | 122 | # 功能 123 | 124 | * 支持自适应大小 125 | * 支持2个方向、4个方向、8个方向的摇动监听 126 | * 支持摇动角度获取 127 | * 可选回调模式 128 | * 支持可摇动区域自定义 129 | * 支持摇杆自定义 130 | * 支持设置图片、色值、Share图形 131 | 132 | # 使用 133 | 134 | ``` java 135 | 143 | ``` 144 | 145 | 146 | # 参数 147 | 148 | | 参数 | 是否必须 | 描述 | 149 | |------------------|------|----------------| 150 | | areaBackground | 可选 | 可摇动区域的背景 | 151 | | rockerBackground | 可选 | 摇杆的背景 | 152 | | rockerRadius | 可选 | 摇杆半径 | 153 | 154 | 155 | # 设置回调方式 156 | 157 | ``` java 158 | setCallBackMode(CallBackMode mode) 159 | ``` 160 | 161 | 参数 162 | 163 | | 回调方式 | 描述 | 164 | |-----------------------------|-------------------| 165 | | CALL_BACK_MODE_MOVE | 有移动就立刻回调 | 166 | | CALL_BACK_MODE_STATE_CHANGE | 状态有变化的时候回调 | 167 | 168 | 169 | 170 | # 监听摇动角度 171 | 172 | 返回角度的取值范围:[0°,360°) 173 | 174 | ![取值范围](http://img.blog.csdn.net/20160901183045786) 175 | 176 | ``` java 177 | setOnAngleChangeListener(OnAngleChangeListener listener) 178 | ``` 179 | 180 | # 监听摇动方向 181 | 182 | ``` java 183 | setOnShakeListener(DirectionMode directionMode, OnShakeListener listener) 184 | ``` 185 | 186 | 支持监听的方向 187 | 188 | | 方向 | 图 | 描述 | 189 | |------------------------|------------------|------| 190 | | DIRECTION_2_HORIZONTAL |![左右两个方向](http://img.blog.csdn.net/20160901183144896)| 横向 左右两个方向 | 191 | | DIRECTION_2_VERTICAL |![上下两个方向](http://img.blog.csdn.net/20160901183332084)| 纵向 上下两个方向 | 192 | | DIRECTION_4_ROTATE_0 | ![四个方向](http://img.blog.csdn.net/20160901183347055) |四个方向 | 193 | | DIRECTION_4_ROTATE_45 | ![四个方向 旋转45°](http://img.blog.csdn.net/20160901183404461) |四个方向 旋转45° | 194 | | DIRECTION_8 | ![八个方向](http://img.blog.csdn.net/20160901183419477) |八个方向 | 195 | 196 | 197 | 方向描述 198 | 199 | | 方向 | 描述 | 200 | |----------------------|-----| 201 | | DIRECTION_LEFT | 左 | 202 | | DIRECTION_RIGHT | 右 | 203 | | DIRECTION_UP | 上 | 204 | | DIRECTION_DOWN | 下 | 205 | | DIRECTION_UP_LEFT | 左上 | 206 | | DIRECTION_UP_RIGHT | 右上 | 207 | | DIRECTION_DOWN_LEFT | 左下 | 208 | | DIRECTION_DOWN_RIGHT | 右下 | 209 | | DIRECTION_CENTER | 中间 | 210 | 211 | 212 | # 例子 213 | 214 | ``` java 215 | RockerView rockerViewLeft = (RockerView) findViewById(R.id.rockerView_left); 216 | if (rockerViewLeft != null) { 217 | rockerViewLeft.setCallBackMode(RockerView.CallBackMode.CALL_BACK_MODE_STATE_CHANGE); 218 | rockerViewLeft.setOnShakeListener(RockerView.DirectionMode.DIRECTION_8, new RockerView.OnShakeListener() { 219 | @Override 220 | public void onStart() { 221 | mLogLeft.setText(null); 222 | } 223 | 224 | @Override 225 | public void direction(RockerView.Direction direction) { 226 | mLogLeft.setText("摇动方向 : " + getDirection(direction)); 227 | } 228 | 229 | @Override 230 | public void onFinish() { 231 | mLogLeft.setText(null); 232 | } 233 | }); 234 | } 235 | 236 | RockerView rockerViewRight = (RockerView) findViewById(R.id.rockerView_right); 237 | if (rockerViewRight != null) { 238 | rockerViewRight.setOnAngleChangeListener(new RockerView.OnAngleChangeListener() { 239 | @Override 240 | public void onStart() { 241 | mLogRight.setText(null); 242 | } 243 | 244 | @Override 245 | public void angle(double angle) { 246 | mLogRight.setText("摇动角度 : " + angle); 247 | } 248 | 249 | @Override 250 | public void onFinish() { 251 | mLogRight.setText(null); 252 | } 253 | }); 254 | } 255 | ``` 256 | 257 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "kong.qingwei.kqwrockerdemo" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile project(':KqwRockerLibrary') 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/kongqw/kqwrockerdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.kongqw.kqwrockerdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongqw/kqwrockerdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.kongqw.kqwrockerdemo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.widget.TextView; 6 | 7 | import com.kongqw.rockerlibrary.view.RockerView; 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | 11 | private TextView mLogLeft; 12 | private TextView mLogRight; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_main); 18 | mLogLeft = (TextView) findViewById(R.id.log_left); 19 | mLogRight = (TextView) findViewById(R.id.log_right); 20 | 21 | RockerView rockerViewLeft = (RockerView) findViewById(R.id.rockerView_left); 22 | if (rockerViewLeft != null) { 23 | rockerViewLeft.setCallBackMode(RockerView.CallBackMode.CALL_BACK_MODE_STATE_CHANGE); 24 | rockerViewLeft.setOnShakeListener(RockerView.DirectionMode.DIRECTION_8, new RockerView.OnShakeListener() { 25 | @Override 26 | public void onStart() { 27 | mLogLeft.setText(null); 28 | } 29 | 30 | @Override 31 | public void direction(RockerView.Direction direction) { 32 | mLogLeft.setText("摇动方向 : " + getDirection(direction)); 33 | } 34 | 35 | @Override 36 | public void onFinish() { 37 | mLogLeft.setText(null); 38 | } 39 | }); 40 | } 41 | 42 | RockerView rockerViewRight = (RockerView) findViewById(R.id.rockerView_right); 43 | if (rockerViewRight != null) { 44 | rockerViewRight.setOnAngleChangeListener(new RockerView.OnAngleChangeListener() { 45 | @Override 46 | public void onStart() { 47 | mLogRight.setText(null); 48 | } 49 | 50 | @Override 51 | public void angle(double angle) { 52 | mLogRight.setText("摇动角度 : " + angle); 53 | } 54 | 55 | @Override 56 | public void onFinish() { 57 | mLogRight.setText(null); 58 | } 59 | }); 60 | } 61 | } 62 | 63 | private String getDirection(RockerView.Direction direction) { 64 | String message = null; 65 | switch (direction) { 66 | case DIRECTION_LEFT: 67 | message = "左"; 68 | break; 69 | case DIRECTION_RIGHT: 70 | message = "右"; 71 | break; 72 | case DIRECTION_UP: 73 | message = "上"; 74 | break; 75 | case DIRECTION_DOWN: 76 | message = "下"; 77 | break; 78 | case DIRECTION_UP_LEFT: 79 | message = "左上"; 80 | break; 81 | case DIRECTION_UP_RIGHT: 82 | message = "右上"; 83 | break; 84 | case DIRECTION_DOWN_LEFT: 85 | message = "左下"; 86 | break; 87 | case DIRECTION_DOWN_RIGHT: 88 | message = "右下"; 89 | break; 90 | default: 91 | break; 92 | } 93 | return message; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/area_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/drawable/area_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/default_area_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/default_rocker_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rocker_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/drawable/rocker_bg.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 22 | 23 | 29 | 30 | 39 | 40 | 46 | 47 | 54 | 55 | 63 | 64 | 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/view_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-hdpi/view_big.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/view_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-hdpi/view_small.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/view_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xhdpi/view_big.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/view_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xhdpi/view_small.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/view_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xxhdpi/view_big.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/view_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xxhdpi/view_small.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | KqwRockerDemo 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/kongqw/kqwrockerdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.kongqw.kqwrockerdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongqw/AndroidRocker/285969b98e211045f4563402cf285c7865a4f9a3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 28 10:19:15 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':KqwRockerLibrary' 2 | --------------------------------------------------------------------------------