├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── leroy │ │ └── switchbutton │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── leroy │ │ │ └── switchbutton │ │ │ ├── MainActivity.java │ │ │ └── widget │ │ │ └── SwitchButton.java │ └── res │ │ ├── drawable │ │ └── cloud.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── leroy │ └── switchbutton │ └── ExampleUnitTest.java ├── build.gradle ├── gifImage ├── SwitchButton.gif └── SwitchButton.mp4 ├── 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 | SwitchButton -------------------------------------------------------------------------------- /.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 | 23 | 24 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwitchButton 2 | 最近看到一个酷炫的日间夜间模式切换按钮,于是就动手写了仿写了一个安卓版本的。 3 | PO上效果图,录制的不太好。 4 | 5 | ![这是实际的运行效果][1] 6 | 7 | [1]: https://github.com/BaymaxTong/SwitchButton/blob/master/gifImage/SwitchButton.gif 8 | 9 | 10 | License 11 | ------- 12 | 13 |    Copyright 2016-2018 BaymaxTong. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | Unless required by applicable law or agreed to in writing, software 22 | distributed under the License is distributed on an "AS IS" BASIS, 23 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | See the License for the specific language governing permissions and 25 | limitations under the License. 26 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "24.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.leroy.switchbutton" 9 | minSdkVersion 19 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(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | } 27 | -------------------------------------------------------------------------------- /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:\Users\baymax\AppData\Local\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/leroy/switchbutton/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.leroy.switchbutton; 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 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/leroy/switchbutton/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.leroy.switchbutton; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends AppCompatActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/leroy/switchbutton/widget/SwitchButton.java: -------------------------------------------------------------------------------- 1 | package com.leroy.switchbutton.widget; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ArgbEvaluator; 6 | import android.animation.ValueAnimator; 7 | import android.annotation.TargetApi; 8 | import android.content.Context; 9 | import android.content.res.TypedArray; 10 | import android.graphics.Bitmap; 11 | import android.graphics.Canvas; 12 | import android.graphics.Paint; 13 | import android.graphics.Rect; 14 | import android.graphics.RectF; 15 | import android.graphics.drawable.BitmapDrawable; 16 | import android.os.Build; 17 | import android.support.annotation.ColorInt; 18 | import android.util.AttributeSet; 19 | import android.view.SoundEffectConstants; 20 | import android.view.View; 21 | import android.view.animation.AccelerateDecelerateInterpolator; 22 | import android.widget.Checkable; 23 | 24 | import com.leroy.switchbutton.R; 25 | 26 | /** 27 | * DayOrNight SwitchButton 28 | * Created by leroy on 2016/9/6. 29 | */ 30 | public class SwitchButton extends View implements Checkable{ 31 | private static final int ANIMATION_DURATION = 300; 32 | 33 | private static final int DEFAULT_WIDTH = 120; //width of SwitchButton 34 | private static final int DEFAULT_HEIGHT = DEFAULT_WIDTH / 2; 35 | private static final int DEFAULT_SPOT_PADDING = 6; 36 | private static final int DEFAULT_BORDER_WIDTH = 4; 37 | 38 | private static final int DEFAULT_SWITCH_ON_COLOR = 0xFF9EE3FB; 39 | private static final int DEFAULT_SWITCH_ON_COLOR_OUT = 0xFF86C3D7; 40 | private static final int DEFAULT_SWITCH_OFF_COLOR = 0xFF3C4145; 41 | private static final int DEFAULT_SWITCH_OFF_COLOR_OUT = 0xFF1C1C1C; 42 | private static final int DEFAULT_SPOT_ON_COLOR = 0xFFE1C348; 43 | private static final int DEFAULT_SPOT_ON_COLOR_IN = 0xFFFFDF6D; 44 | private static final int DEFAULT_SPOT_OFF_COLOR = 0xFFE3E7C7; 45 | private static final int DEFAULT_SPOT_OFF_COLOR_IN = 0xFFFFFFFF; 46 | 47 | private static final int SWITCH_OFF_POS = 0; 48 | private static final int SWITCH_ON_POS = 1; 49 | 50 | private int switchOnColor; 51 | private int switchOffColor; 52 | private int spotOnColor; 53 | private int spotOnColorIn; 54 | private int spotOffColor; 55 | private int spotOffColorIn; 56 | private int switchOnStrokeColor; 57 | private int switchOffStrokeColor; 58 | private int spotPadding; 59 | private float currentPos; 60 | private boolean mChecked; 61 | private boolean mBroadcasting; 62 | private boolean isMoving; 63 | private int duration; 64 | 65 | private OnCheckedChangeListener onCheckedChangeListener; 66 | 67 | private ValueAnimator valueAnimator; 68 | 69 | private enum State { 70 | SWITCH_ANIMATION_OFF, SWITCH_ANIMATION_ON, SWITCH_ON, SWITCH_OFF 71 | } 72 | 73 | private State state; 74 | 75 | public SwitchButton(Context context) { 76 | super(context); 77 | switchOnColor = DEFAULT_SWITCH_ON_COLOR; 78 | switchOffColor = DEFAULT_SWITCH_OFF_COLOR; 79 | spotOnColor = DEFAULT_SPOT_ON_COLOR; 80 | spotOnColorIn = DEFAULT_SPOT_ON_COLOR_IN; 81 | spotOffColor = DEFAULT_SPOT_OFF_COLOR; 82 | spotOffColorIn = DEFAULT_SPOT_OFF_COLOR_IN; 83 | spotPadding = dp2px(DEFAULT_SPOT_PADDING); 84 | switchOnStrokeColor = switchOnColor; 85 | switchOffStrokeColor = switchOffColor; 86 | duration = ANIMATION_DURATION; 87 | state = mChecked ? State.SWITCH_ON : State.SWITCH_OFF; 88 | 89 | setClickable(true); 90 | } 91 | 92 | public SwitchButton(Context context, AttributeSet attrs) { 93 | super(context, attrs); 94 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Switch); 95 | switchOnColor = a.getColor(R.styleable.Switch_switchOnColor, DEFAULT_SWITCH_ON_COLOR); 96 | switchOffColor = a.getColor(R.styleable.Switch_switchOffColor, DEFAULT_SWITCH_OFF_COLOR); 97 | spotOnColor = a.getColor(R.styleable.Switch_spotOnColor, DEFAULT_SPOT_ON_COLOR); 98 | spotOnColorIn = a.getColor(R.styleable.Switch_spotOnColor, DEFAULT_SPOT_ON_COLOR_IN); 99 | spotOffColor = a.getColor(R.styleable.Switch_spotOffColor, DEFAULT_SPOT_OFF_COLOR); 100 | spotOffColorIn = a.getColor(R.styleable.Switch_spotOnColor, DEFAULT_SPOT_OFF_COLOR_IN); 101 | spotPadding = a.getDimensionPixelSize(R.styleable.Switch_spotPadding, dp2px(DEFAULT_SPOT_PADDING)); 102 | switchOnStrokeColor = a.getColor(R.styleable.Switch_switchOnStrokeColor, switchOnColor); 103 | switchOffStrokeColor = a.getColor(R.styleable.Switch_switchOffStrokeColor, switchOffColor); 104 | duration = a.getInteger(R.styleable.Switch_duration, ANIMATION_DURATION); 105 | mChecked = a.getBoolean(R.styleable.Switch_checked, false); 106 | a.recycle(); 107 | 108 | state = mChecked ? State.SWITCH_ON : State.SWITCH_OFF; 109 | setClickable(true); 110 | } 111 | 112 | @Override 113 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 114 | int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 115 | int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 116 | int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); 117 | int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); 118 | 119 | int width = dp2px(DEFAULT_WIDTH) + getPaddingLeft() + getPaddingRight(); 120 | int height = dp2px(DEFAULT_HEIGHT) + getPaddingTop() + getPaddingBottom(); 121 | 122 | if (widthSpecMode != MeasureSpec.AT_MOST) { 123 | width = Math.max(width, widthSpecSize); 124 | } 125 | 126 | if (heightSpecMode != MeasureSpec.AT_MOST) { 127 | height = Math.max(height, heightSpecSize); 128 | } 129 | 130 | setMeasuredDimension(width, height); 131 | 132 | } 133 | 134 | @Override 135 | protected void onDraw(Canvas canvas) { 136 | super.onDraw(canvas); 137 | int w = getWidth(); 138 | int h = getHeight(); 139 | int pl = getPaddingLeft(); 140 | int pt = getPaddingTop(); 141 | int pr = getPaddingRight(); 142 | int pb = getPaddingBottom(); 143 | int wp = w - pl - pr; 144 | int hp = h - pt - pb; 145 | int sw = dp2px(DEFAULT_WIDTH); 146 | int sh = dp2px(DEFAULT_HEIGHT); 147 | 148 | int dx = pl + (wp - sw) / 2; 149 | int dy = pt + (hp - sh) / 2; 150 | canvas.translate(dx, dy); 151 | 152 | switch (state) { 153 | case SWITCH_ON: 154 | drawSwitchOn(canvas); 155 | break; 156 | case SWITCH_OFF: 157 | drawSwitchOff(canvas); 158 | break; 159 | case SWITCH_ANIMATION_ON: 160 | drawSwitchOnAnim(canvas); 161 | break; 162 | case SWITCH_ANIMATION_OFF: 163 | drawSwitchOffAnim(canvas); 164 | break; 165 | } 166 | } 167 | 168 | private void drawSwitchOn(Canvas canvas) { 169 | float[] rectAttrs = compRoundRectAttr(SWITCH_OFF_POS); 170 | drawRoundRect(canvas, switchOnColor, rectAttrs); 171 | 172 | float[] ovalAttrs = compOvalAttr(SWITCH_ON_POS); 173 | drawOval(canvas, spotOnColor, ovalAttrs); 174 | drawOvalIn(canvas, spotOnColorIn, ovalAttrs); 175 | drawCloud(canvas, 1); 176 | 177 | drawRoundRectStroke(canvas, DEFAULT_SWITCH_ON_COLOR_OUT); 178 | } 179 | 180 | private void drawSwitchOff(Canvas canvas) { 181 | float[] rectAttrs = compRoundRectAttr(SWITCH_OFF_POS); 182 | drawRoundRect(canvas, switchOffColor, rectAttrs); 183 | 184 | float[] ovalAttrs = compOvalAttr(SWITCH_OFF_POS); 185 | drawOval(canvas, spotOffColor, ovalAttrs); 186 | drawOvalIn(canvas, spotOffColorIn, ovalAttrs); 187 | drawCircleDot(canvas, spotOffColor, spotOffColorIn, 1, ovalAttrs); 188 | drawCircleDot2(canvas, spotOffColor, spotOffColorIn, 1, ovalAttrs); 189 | drawCircleDot3(canvas, spotOffColor, spotOffColorIn, 1, ovalAttrs); 190 | drawStar(canvas, DEFAULT_SPOT_OFF_COLOR_IN, 1); 191 | 192 | drawRoundRectStroke(canvas, DEFAULT_SWITCH_OFF_COLOR_OUT); 193 | } 194 | 195 | private void drawSwitchOnAnim(Canvas canvas) { 196 | float[] rectAttrs = compRoundRectAttr(SWITCH_OFF_POS); 197 | drawRoundRect(canvas, switchOnColor, rectAttrs); 198 | 199 | // rectAttrs = compRoundRectAttr(currentPos); fix drawRoundRect issue by lgyjg 200 | // drawRoundRect(canvas, switchOffColor, rectAttrs); 201 | 202 | float[] ovalShadeOnAttrs = compRoundRectShadeOnAttr(currentPos * 3/2); 203 | float[] ovalAttrs = compOvalAttr(currentPos* 3/2); 204 | int color = compColor(currentPos, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_ON_COLOR); 205 | int colorIn = compColor(currentPos, DEFAULT_SPOT_OFF_COLOR_IN, DEFAULT_SPOT_ON_COLOR_IN); 206 | drawRoundRect(canvas, color, ovalShadeOnAttrs); 207 | drawOval(canvas, color, ovalAttrs); 208 | drawOvalIn(canvas, colorIn, ovalAttrs); 209 | if(currentPos > 0.6) { 210 | drawCloud(canvas, currentPos); 211 | } 212 | 213 | int strokeColor = compColor(currentPos, DEFAULT_SWITCH_OFF_COLOR_OUT, DEFAULT_SWITCH_ON_COLOR_OUT); 214 | drawRoundRectStroke(canvas, strokeColor); 215 | } 216 | 217 | private void drawSwitchOffAnim(Canvas canvas) { 218 | float[] rectAttrs = compRoundRectAttr(SWITCH_OFF_POS); 219 | if (currentPos != 1) { 220 | drawRoundRect(canvas, switchOffColor, rectAttrs); 221 | } 222 | 223 | // rectAttrs = compRoundRectAttr(1 - currentPos); 224 | drawRoundRect(canvas, switchOffColor, rectAttrs); 225 | 226 | float[] ovalAttrs; 227 | if(currentPos > 2.0/3){ 228 | ovalAttrs = compOvalAttr(0); 229 | }else{ 230 | ovalAttrs = compOvalAttr(1 - currentPos * 3/2); 231 | } 232 | float[] ovalShadeOffAttrs = compRoundRectShadeOffAttr(1 - currentPos * 3/2); 233 | int color = compColor(currentPos, DEFAULT_SPOT_ON_COLOR, DEFAULT_SPOT_OFF_COLOR); 234 | int colorIn = compColor(currentPos, DEFAULT_SPOT_ON_COLOR_IN, DEFAULT_SPOT_OFF_COLOR_IN); 235 | drawRoundRect(canvas, color, ovalShadeOffAttrs); 236 | drawOval(canvas, color, ovalAttrs); 237 | drawOvalIn(canvas, colorIn, ovalAttrs); 238 | if(currentPos > 2.0/3){ 239 | drawCircleDot(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, 1, ovalAttrs); 240 | drawCircleDot2(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, 1, ovalAttrs); 241 | drawCircleDot3(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, 1, ovalAttrs); 242 | }else{ 243 | drawCircleDot(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, currentPos * 3/2, ovalAttrs); 244 | drawCircleDot2(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, currentPos * 3/2, ovalAttrs); 245 | drawCircleDot3(canvas, DEFAULT_SPOT_OFF_COLOR, DEFAULT_SPOT_OFF_COLOR_IN, currentPos * 3/2, ovalAttrs); 246 | } 247 | if(currentPos > 0.6) { 248 | drawStar(canvas, DEFAULT_SPOT_OFF_COLOR_IN, currentPos); 249 | } 250 | 251 | int strokeColor = compColor(currentPos, DEFAULT_SWITCH_ON_COLOR_OUT, DEFAULT_SWITCH_OFF_COLOR_OUT); 252 | drawRoundRectStroke(canvas, strokeColor); 253 | } 254 | 255 | private void drawRoundRect(Canvas canvas, int color, float[] attrs) { 256 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 257 | paint.setStyle(Paint.Style.FILL); 258 | paint.setStrokeCap(Paint.Cap.ROUND); 259 | RectF rectF = new RectF(); 260 | paint.setColor(color); 261 | rectF.set(attrs[0], attrs[1], attrs[2], attrs[3]); 262 | canvas.drawRoundRect(rectF, attrs[4], attrs[4], paint); 263 | } 264 | 265 | private void drawRoundRectStroke(Canvas canvas, int color) { 266 | int sw = dp2px(DEFAULT_WIDTH); 267 | int sh = dp2px(DEFAULT_HEIGHT); 268 | 269 | float left = dp2pxFloat((float) 2.4); 270 | float right = sw - left; 271 | float top = dp2pxFloat((float) 2.4); 272 | float bottom = sh - top; 273 | float radius = (bottom - top) * 0.5f; 274 | 275 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 276 | paint.setStyle(Paint.Style.STROKE); 277 | paint.setColor(color); 278 | paint.setStrokeWidth(dp2pxFloat((float) 3.6)); 279 | RectF rectF = new RectF(); 280 | rectF.set(left, top, right, bottom); 281 | canvas.drawRoundRect(rectF, radius, radius, paint); 282 | } 283 | 284 | private void drawOvalIn(Canvas canvas, int color, float[] attrs) { 285 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 286 | paint.setStyle(Paint.Style.FILL); 287 | paint.setColor(color); 288 | int borderWidth = dp2px(DEFAULT_BORDER_WIDTH); 289 | RectF rectFIn = new RectF(attrs[0] + borderWidth, attrs[1] + borderWidth, attrs[2] - borderWidth, attrs[3] - borderWidth); 290 | canvas.drawOval(rectFIn, paint); 291 | } 292 | 293 | private void drawOval(Canvas canvas, int color, float[] attrs) { 294 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 295 | paint.setStyle(Paint.Style.FILL); 296 | paint.setColor(color); 297 | RectF rectF = new RectF(attrs[0], attrs[1], attrs[2], attrs[3]); 298 | canvas.drawOval(rectF, paint); 299 | } 300 | 301 | private void drawCircleDot(Canvas canvas, int color,int colorIn, float pos, float[] attrs) { 302 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 303 | paint.setStyle(Paint.Style.FILL); 304 | float rad = attrs[2] - dp2px(9) - (attrs[0] + attrs[2])/2; 305 | float x = attrs[2] - dp2px(9) - rad + (float)(rad * Math.cos(pos * Math.PI/3)); 306 | float y = (attrs[1] + attrs[3])/2 - (float)(rad * Math.sin(pos * Math.PI/3)); 307 | paint.setColor(color); 308 | RectF rectF = new RectF(x - dp2px(7), y - dp2px(7), x + dp2px(7), y + dp2px(7)); 309 | canvas.drawOval(rectF, paint); 310 | paint.setColor(colorIn); 311 | RectF rectFIn = new RectF(x - dp2px(3), y - dp2px(3), x + dp2px(3), y + dp2px(3)); 312 | canvas.drawOval(rectFIn, paint); 313 | } 314 | 315 | private void drawCircleDot2(Canvas canvas, int color,int colorIn, float pos, float[] attrs) { 316 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 317 | paint.setStyle(Paint.Style.FILL); 318 | float rad = attrs[2] - dp2px(7) - (attrs[0] + attrs[2])/2; 319 | float x = attrs[2] - dp2px(7) - rad + (float)(rad * Math.cos(Math.PI * 5 /12 + pos * Math.PI* 5 /12)); 320 | float y = (attrs[1] + attrs[3])/2 - (float)(rad * Math.sin(Math.PI * 5 /12 + pos * Math.PI* 5 /12)); 321 | paint.setColor(color); 322 | RectF rectF = new RectF(x - dp2px(5), y - dp2px(5), x + dp2px(5), y + dp2px(5)); 323 | canvas.drawOval(rectF, paint); 324 | paint.setColor(colorIn); 325 | RectF rectFIn = new RectF(x - dp2px(1), y - dp2px(1), x + dp2px(1), y + dp2px(1)); 326 | canvas.drawOval(rectFIn, paint); 327 | } 328 | 329 | private void drawCircleDot3(Canvas canvas, int color,int colorIn, float pos, float[] attrs) { 330 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 331 | paint.setStyle(Paint.Style.FILL); 332 | float rad = attrs[2] - dp2px(9) - (attrs[0] + attrs[2])/2; 333 | float x = attrs[2] - dp2px(9) - rad + (float)(rad * Math.cos(Math.PI * 16 /12 + pos * Math.PI* 5 /12)); 334 | float y = (attrs[1] + attrs[3])/2 - (float)(rad * Math.sin(Math.PI * 16 /12 + pos * Math.PI* 5 /12)); 335 | paint.setColor(color); 336 | RectF rectF = new RectF(x - dp2px(5), y - dp2px(5), x + dp2px(5), y + dp2px(5)); 337 | canvas.drawOval(rectF, paint); 338 | paint.setColor(colorIn); 339 | RectF rectFIn = new RectF(x - dp2px(1), y - dp2px(1), x + dp2px(1), y + dp2px(1)); 340 | canvas.drawOval(rectFIn, paint); 341 | } 342 | 343 | private void drawCloud(Canvas canvas, float pos) { 344 | int sw = dp2px(DEFAULT_WIDTH); 345 | int sh = dp2px(DEFAULT_HEIGHT); 346 | 347 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 348 | paint.setDither(true); 349 | paint.setFilterBitmap(true); 350 | Bitmap cloudBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.cloud)).getBitmap(); 351 | int cloudWidth = cloudBitmap.getWidth(); 352 | int cloudHeight = cloudBitmap.getHeight(); 353 | Rect mSrcRect = new Rect(0, 0, cloudWidth, cloudHeight); 354 | RectF mDestRect; 355 | if(pos <= 0.9){ 356 | float t = pos*10 - 6; 357 | mDestRect = new RectF(sw/2 - dp2px(18) - dp2px(t), sh/2 - dp2px(4) - dp2px(t), sw/2 + dp2px(18) + dp2px(t), sh/2 + dp2px(20) + dp2px(t)); 358 | }else{ 359 | float t = 2*(pos*10 - 9); 360 | mDestRect = new RectF(sw/2 - dp2px(22) + dp2px(t), sh/2 - dp2px(8) + dp2px(t), sw/2 + dp2px(22) - dp2px(t), sh/2 + dp2px(24) - dp2px(t)); 361 | } 362 | canvas.drawBitmap(cloudBitmap, mSrcRect, mDestRect, paint); 363 | } 364 | 365 | private void drawStar(Canvas canvas, int color, float pos) { 366 | int sw = dp2px(DEFAULT_WIDTH); 367 | int sh = dp2px(DEFAULT_HEIGHT); 368 | 369 | float stars[][] = new float[7][2]; 370 | stars[0][0] = (float) (sw/2.0); 371 | stars[0][1] = (float) (sh/5.0); 372 | 373 | stars[1][0] = (float) (sw * 3/4.0); 374 | stars[1][1] = (float) (sh/5.0); 375 | 376 | stars[2][0] = (float) (sw * 5/8.0); 377 | stars[2][1] = (float) (sh * 2/5.0); 378 | 379 | stars[3][0] = (float) (sw * 27/40.0); 380 | stars[3][1] = (float) (sh * 3/5.0); 381 | 382 | stars[4][0] = (float) (sw * 5/6.0); 383 | stars[4][1] = (float) (sh * 9/20.0); 384 | 385 | stars[5][0] = (float) (sw * 4/5.0); 386 | stars[5][1] = (float) (sh * 7/10.0); 387 | 388 | stars[6][0] = (float) (sw * 11/20.0); 389 | stars[6][1] = (float) (sh * 3/4.0); 390 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 391 | paint.setStyle(Paint.Style.FILL); 392 | paint.setColor(color); 393 | 394 | float t = 10 * pos - 6; 395 | if(pos > 0.8){ 396 | t = 10 - 10 * pos; 397 | } 398 | canvas.drawCircle(stars[0][0], stars[0][1], 6 + 2*t, paint); 399 | canvas.drawCircle(stars[1][0], stars[1][1], 5 + 2*t, paint); 400 | canvas.drawCircle(stars[2][0], stars[2][1], 5 + 2*t, paint); 401 | canvas.drawCircle(stars[3][0], stars[3][1], 4 + 2*t, paint); 402 | canvas.drawCircle(stars[4][0], stars[4][1], 8 - 2*t, paint); 403 | canvas.drawCircle(stars[5][0], stars[5][1], 7 - 2*t, paint); 404 | canvas.drawCircle(stars[6][0], stars[6][1], 7 - 2*t, paint); 405 | } 406 | 407 | private float[] compRoundRectAttr(float pos) { 408 | int sw = dp2px(DEFAULT_WIDTH); 409 | int sh = dp2px(DEFAULT_HEIGHT); 410 | 411 | float left = sw * pos; 412 | float right = sw - left; 413 | float top = sh * pos; 414 | float bottom = sh - top; 415 | float radius = (bottom - top) * 0.5f; 416 | 417 | return new float[]{left, top, right, bottom, radius}; 418 | } 419 | 420 | private float[] compRoundRectShadeOnAttr(float pos) { 421 | int sw = dp2px(DEFAULT_WIDTH); 422 | int sh = dp2px(DEFAULT_HEIGHT); 423 | int oh = sh - 2 * spotPadding; 424 | float left, right, top, bottom; 425 | if(pos < 0.35){ 426 | left = 0; 427 | right = spotPadding + (sw - sh) * pos + oh; 428 | top = spotPadding; 429 | bottom = oh + top; 430 | }else{ 431 | left = spotPadding + (sw - sh) * pos *2/3; 432 | right = spotPadding + (sw - sh) * pos *2/3+ oh; 433 | top = spotPadding; 434 | bottom = oh + top; 435 | } 436 | float radius = (bottom - top) * 0.5f; 437 | return new float[]{left, top, right, bottom, radius}; 438 | } 439 | 440 | private float[] compRoundRectShadeOffAttr(float pos) { 441 | int sw = dp2px(DEFAULT_WIDTH); 442 | int sh = dp2px(DEFAULT_HEIGHT); 443 | int oh = sh - 2 * spotPadding; 444 | float left, right, top, bottom; 445 | 446 | if(pos > 0.65){ 447 | left = spotPadding + (sw - sh) * pos; 448 | right = sw - spotPadding; 449 | top = spotPadding; 450 | bottom = oh + top; 451 | }else{ 452 | left = spotPadding + (sw - sh) * (2*pos + 1)/3; 453 | right = spotPadding + (sw - sh) * (2*pos + 1)/3 + oh; 454 | top = spotPadding; 455 | bottom = oh + top; 456 | } 457 | float radius = (bottom - top) * 0.5f; 458 | return new float[]{left, top, right, bottom, radius}; 459 | } 460 | 461 | private float[] compOvalAttr(float pos) { 462 | if(pos > 1){ 463 | pos = 1; 464 | } 465 | int sw = dp2px(DEFAULT_WIDTH); 466 | int sh = dp2px(DEFAULT_HEIGHT); 467 | int oh = sh - 2 * spotPadding; 468 | 469 | float left = spotPadding + (sw - sh) * pos; 470 | float right = left + oh; 471 | float top = spotPadding; 472 | float bottom = oh + top; 473 | 474 | return new float[]{left, top, right, bottom}; 475 | } 476 | 477 | private int compColor(float fraction, int startColor, int endColor) { 478 | return (Integer) new ArgbEvaluator().evaluate(fraction, startColor, endColor); 479 | } 480 | 481 | @Override 482 | public boolean performClick() { 483 | toggle(); 484 | 485 | final boolean handled = super.performClick(); 486 | if (!handled) { 487 | // View only makes a sound effect if the onClickListener was 488 | // called, so we'll need to make one here instead. 489 | playSoundEffect(SoundEffectConstants.CLICK); 490 | } 491 | 492 | return handled; 493 | } 494 | 495 | public int dp2px(float dpValue) { 496 | float scale = getResources().getDisplayMetrics().density; 497 | return (int) (dpValue * scale + 0.5f); 498 | } 499 | 500 | public float dp2pxFloat(float dpValue) { 501 | float scale = getResources().getDisplayMetrics().density; 502 | return dpValue * scale + 0.5f; 503 | } 504 | 505 | @TargetApi(Build.VERSION_CODES.KITKAT) 506 | @Override 507 | public void setChecked(boolean checked) { 508 | if (isMoving) { 509 | return; 510 | } 511 | 512 | if (mChecked != checked) { 513 | mChecked = checked; 514 | 515 | // Avoid infinite recursions if setChecked() is called from a listener 516 | if (mBroadcasting) { 517 | return; 518 | } 519 | 520 | mBroadcasting = true; 521 | if (onCheckedChangeListener != null) { 522 | onCheckedChangeListener.onCheckedChanged(this, mChecked); 523 | } 524 | mBroadcasting = false; 525 | 526 | if (mChecked) { 527 | state = State.SWITCH_ANIMATION_ON; 528 | } else { 529 | state = State.SWITCH_ANIMATION_OFF; 530 | } 531 | 532 | if (isAttachedToWindow() && isLaidOut()) { 533 | animateToCheckedState(); 534 | } else { 535 | // Immediately move the thumb to the new position. 536 | cancelPositionAnimator(); 537 | currentPos = 0; 538 | } 539 | } 540 | } 541 | 542 | private void cancelPositionAnimator() { 543 | if (valueAnimator != null) { 544 | valueAnimator.cancel(); 545 | } 546 | } 547 | 548 | private void animateToCheckedState() { 549 | valueAnimator = ValueAnimator.ofFloat(0, 1); 550 | valueAnimator.setDuration(duration); 551 | valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 552 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 553 | @Override 554 | public void onAnimationUpdate(ValueAnimator animation) { 555 | currentPos = (float) animation.getAnimatedValue(); 556 | invalidate(); 557 | } 558 | }); 559 | 560 | valueAnimator.addListener(new AnimatorListenerAdapter() { 561 | @Override 562 | public void onAnimationStart(Animator animation) { 563 | super.onAnimationStart(animation); 564 | isMoving = true; 565 | } 566 | 567 | @Override 568 | public void onAnimationEnd(Animator animation) { 569 | super.onAnimationEnd(animation); 570 | isMoving = false; 571 | } 572 | }); 573 | 574 | if (!valueAnimator.isRunning()) { 575 | valueAnimator.start(); 576 | currentPos = 0; 577 | } 578 | } 579 | 580 | public int getDuration() { 581 | return duration; 582 | } 583 | 584 | public void setDuration(int duration) { 585 | this.duration = duration; 586 | } 587 | 588 | @Override 589 | public boolean isChecked() { 590 | return mChecked; 591 | } 592 | 593 | @Override 594 | public void toggle() { 595 | setChecked(!mChecked); 596 | } 597 | 598 | public int getSwitchOnColor() { 599 | return switchOnColor; 600 | } 601 | 602 | public void setSwitchOnColor(@ColorInt int switchOnColor) { 603 | this.switchOnColor = switchOnColor; 604 | invalidate(); 605 | } 606 | 607 | public int getSwitchOffColor() { 608 | return switchOffColor; 609 | } 610 | 611 | public void setSwitchOffColor(@ColorInt int switchOffColor) { 612 | this.switchOffColor = switchOffColor; 613 | invalidate(); 614 | } 615 | 616 | public int getSpotOnColor() { 617 | return spotOnColor; 618 | } 619 | 620 | public void setSpotOnColor(@ColorInt int spotOnColor) { 621 | this.spotOnColor = spotOnColor; 622 | invalidate(); 623 | } 624 | 625 | public int getSpotOffColor() { 626 | return spotOffColor; 627 | } 628 | 629 | public void setSpotOffColor(@ColorInt int spotOffColor) { 630 | this.spotOffColor = spotOffColor; 631 | invalidate(); 632 | } 633 | 634 | public int getSpotPadding() { 635 | return spotPadding; 636 | } 637 | 638 | public void setSpotPadding(int spotPadding) { 639 | this.spotPadding = spotPadding; 640 | invalidate(); 641 | } 642 | 643 | public int getSwitchOffStrokeColor() { 644 | return switchOffStrokeColor; 645 | } 646 | 647 | public void setSwitchOffStrokeColor(int switchOffStrokeColor) { 648 | this.switchOffStrokeColor = switchOffStrokeColor; 649 | invalidate(); 650 | } 651 | 652 | public int getSwitchOnStrokeColor() { 653 | return switchOnStrokeColor; 654 | } 655 | 656 | public void setSwitchOnStrokeColor(int switchOnStrokeColor) { 657 | this.switchOnStrokeColor = switchOnStrokeColor; 658 | invalidate(); 659 | } 660 | 661 | public OnCheckedChangeListener getOnCheckedChangeListener() { 662 | return onCheckedChangeListener; 663 | } 664 | 665 | public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) { 666 | this.onCheckedChangeListener = onCheckedChangeListener; 667 | } 668 | 669 | public interface OnCheckedChangeListener { 670 | /** 671 | * Called when the checked state of a switch has changed. 672 | * 673 | * @param s The switch whose state has changed. 674 | * @param isChecked The new checked state of switch. 675 | */ 676 | void onCheckedChanged(SwitchButton s, boolean isChecked); 677 | } 678 | } 679 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/app/src/main/res/drawable/cloud.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/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/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /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 | SwitchButton 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/leroy/switchbutton/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.leroy.switchbutton; 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.0.0' 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 | -------------------------------------------------------------------------------- /gifImage/SwitchButton.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/gifImage/SwitchButton.gif -------------------------------------------------------------------------------- /gifImage/SwitchButton.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/gifImage/SwitchButton.mp4 -------------------------------------------------------------------------------- /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/BaymaxTong/SwitchButton/eba4b49a3438ff86b85462bfd2fcfad732fe0b57/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 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.10-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' 2 | --------------------------------------------------------------------------------