1313import  android .graphics .Path ;
1414import  android .graphics .RectF ;
1515import  android .util .AttributeSet ;
16+ import  android .util .Log ;
1617import  android .view .View ;
1718import  android .widget .Checkable ;
1819
@@ -31,14 +32,18 @@ public class LoadingToggleButton extends View implements Checkable {
3132 private  OnCheckedChangeListener  mOnCheckedChangeListener ;
3233 private  boolean  mChecked ;
3334 private  float  mSunCenterX ;
35+ 36+  private  float  mAnimatedToggleX ;
37+  private  RectF  mDrawingToggleRect  = new  RectF ();
38+ 3439 private  float  mCenterDistance ;
3540 private  ValueAnimator  mToggleAnimator ;
3641 private  Paint  mPaint ;
3742 private  int  mBgRadius ;
3843 private  int  mToggleRadius ;
3944
40-  private  RectF  mLeftToggleOutline ;
41-  private  RectF  mRightToggleOutline ;
45+  private  RectF  mFixedLeftToggleOutline  =  new RectF () ;
46+  private  RectF  mFixedRightToggleOutline  =  new RectF () ;
4247
4348 private  Path  pathBg ;
4449 private  Path  pathSun ;
@@ -51,6 +56,15 @@ public class LoadingToggleButton extends View implements Checkable {
5156 private  static  final  int [] CheckedStateSet  = {
5257 android .R .attr .state_checked ,
5358 };
59+  private  int  mWidth ;
60+  private  int  mHeight ;
61+ 62+ 63+ 64+  private  int  mRightIndicatorX ;
65+  private  int  mRightIndicatorY ;
66+  private  int  mToggleWidth ;
67+  private  int  mToggleHeight ;
5468
5569 public  LoadingToggleButton (Context  context ) {
5670 super (context );
@@ -97,7 +111,11 @@ private void init(AttributeSet attrs) {
97111 int  toggleChecked  = typedArray .getColor (R .styleable .LoadingToggleButton_ltbToggleCheckedColor , ToggleSettings .TOGGLE_CHECKED_COLOR );
98112 int  backgroundUnCheckColor  = typedArray .getColor (R .styleable .LoadingToggleButton_ltbBackgroundUncheckedColor , ToggleSettings .BACKGROUND_UNCHECKED_COLOR );
99113 int  backgroundCheckColor  = typedArray .getColor (R .styleable .LoadingToggleButton_ltbBackgroundCheckedColor , ToggleSettings .BACKGROUND_CHECKED_COLOR );
114+ 115+  int  bgRadius  = typedArray .getDimensionPixelSize (R .styleable .LoadingToggleButton_ltbBackgroundRadius , ToggleSettings .RADIUS_DEFAULT );
116+ 100117 int  padding  = typedArray .getDimensionPixelSize (R .styleable .LoadingToggleButton_ltbTogglePadding , ToggleSettings .PADDING_DEFAULT );
118+  int  toggleRadius  = typedArray .getDimensionPixelSize (R .styleable .LoadingToggleButton_ltbToggleRadius , ToggleSettings .RADIUS_DEFAULT );
101119 int  duration  = typedArray .getInt (R .styleable .LoadingToggleButton_ltbDuration , ToggleSettings .DURATION_DEFAULT );
102120 boolean  withAnimator  = typedArray .getBoolean (R .styleable .LoadingToggleButton_ltbToggleWithAnimate , true );
103121 toggleSettings  = new  ToggleSettings .Builder ()
@@ -107,6 +125,8 @@ private void init(AttributeSet attrs) {
107125 .setBackgroundCheckedColor (backgroundCheckColor )
108126 .setPadding (padding )
109127 .setDuration (duration )
128+  .setToggleRadius (toggleRadius )
129+  .setBgRadius (bgRadius )
110130 .withAnimator (withAnimator )
111131 .buildSettings ();
112132 typedArray .recycle ();
@@ -116,19 +136,50 @@ private void init(AttributeSet attrs) {
116136
117137 @ Override 
118138 protected  void  onSizeChanged (int  w , int  h , int  oldw , int  oldh ) {
139+  Log .d (TAG , "onSizeChanged() called with: w = ["  + w  + "], h = ["  + h  + "], oldw = ["  + oldw  + "], oldh = ["  + oldh  + "]" );
119140 super .onSizeChanged (w , h , oldw , oldh );
141+ 142+  mWidth  = w ;
143+  mHeight  = h ;
144+ 120145 setUp ();
121146 }
122147
123148 private  void  setUp () {
124-  mBgRadius  = getHeight () / 2 ;
125-  mToggleRadius  = mBgRadius  - mToggleSettings .mPadding ;
126149
127-  mSunCenterX  = mChecked  ? getWidth () - mBgRadius : mBgRadius ;
150+  // toggle size, it may be a long toggle, a circle toggle 
151+  mToggleHeight  = mHeight  - 2  * mToggleSettings .mPadding ;
152+  mToggleWidth  = mToggleHeight ;
153+ 154+  final  int  maxBgRadius  = mHeight  / 2 ;
155+  final  int  maxToggleRadius  = mToggleHeight  / 2 ;
156+ 157+  mBgRadius  = (mToggleSettings .mBgRadius  > maxBgRadius ) ? maxBgRadius 
158+  : (mToggleSettings .mBgRadius  < 0  ? (mToggleSettings .mBgRadius  == -1  ? maxBgRadius  : 0  ) : mToggleSettings .mBgRadius );
159+ 160+  // TODO check negative? 
161+  mToggleRadius  = mToggleSettings .mToggleRadius  > maxToggleRadius  ? maxToggleRadius 
162+  : (mToggleSettings .mToggleRadius  < 0  ? (mToggleSettings .mToggleRadius  == -1  ? maxToggleRadius  : 0 ) : mToggleSettings .mToggleRadius );
163+ 164+  // Two fixed position of toggle's outline, the toggle will animated between these two position 
165+  mFixedRightToggleOutline .right  = mWidth  - mToggleSettings .mPadding ;
166+  mFixedRightToggleOutline .top  = mToggleSettings .mPadding ;
167+  mFixedRightToggleOutline .left  = mFixedRightToggleOutline .right  - mToggleWidth ;
168+  mFixedRightToggleOutline .bottom  = mHeight  - mToggleSettings .mPadding ;
169+ 170+  mFixedLeftToggleOutline .left  = mToggleSettings .mPadding ;
171+  mFixedLeftToggleOutline .top  = mToggleSettings .mPadding ;
172+  mFixedLeftToggleOutline .right  = mFixedLeftToggleOutline .left  + mToggleWidth ;
173+  mFixedLeftToggleOutline .bottom  = mHeight  - mToggleSettings .mPadding ;
174+ 175+ 176+  mDrawingToggleRect .set (mChecked  ? mFixedRightToggleOutline  : mFixedLeftToggleOutline );
177+  mAnimatedToggleX  = mDrawingToggleRect .left ;
178+ 179+  // TODO deprecated? 
180+  mSunCenterX  = mChecked  ? getWidth () - mBgRadius  : mBgRadius ;
128181 mCenterDistance  = 2  * mToggleRadius ;
129182
130-  mLeftToggleOutline  = new  RectF (0 , 0 , mBgRadius  * 2 , mBgRadius  * 2 );
131-  mRightToggleOutline  = new  RectF (getWidth () - mBgRadius  * 2 , 0 , getWidth (), mBgRadius  * 2 );
132183 }
133184
134185 public  void  setToggleSettings (ToggleSettings  toggleSettings ) {
@@ -147,33 +198,56 @@ public ToggleSettings getToggleSettings() {
147198 return  mToggleSettings ;
148199 }
149200
201+ 150202 private  void  animateToggle (boolean  toggleToOn ) {
151203 final  float  originX ;
152204 final  float  endX ;
153205 final  float  originY ;
154206 final  float  endY ;
155-  final  int  startBackgroundColor ;
156-  final  int  endBackgroundColor ;
157-  final  int  startToggleColor ;
158-  final  int  endToggleColor ;
207+  final  int  bgStartColor ;
208+  final  int  bgEndColor ;
209+  final  int  toggleStartColor ;
210+  final  int  toggleEndColor ;
211+ 212+  final  float  toggleStartX ;
213+  final  float  toggleEndX ;
214+ 159215 if  (toggleToOn ) {
216+ 217+  // for DayNightToggle mode, the toggle si animated from sun to moon 
160218 originX  = mBgRadius ;
161-  endX  = getWidth () - mBgRadius ;
162219 originY  = 2  * mToggleRadius ;
220+ 221+  endX  = getWidth () - mBgRadius ;
163222 endY  = mToggleRadius ;
164-  startBackgroundColor  = mToggleSettings .mBackgroundUnCheckedColor ;
165-  endBackgroundColor  = mToggleSettings .mBackgroundCheckedColor ;
166-  startToggleColor  = mToggleSettings .mToggleUnCheckedColor ;
167-  endToggleColor  = mToggleSettings .mToggleCheckedColor ;
223+ 224+  // for a normal toggle 
225+  toggleStartX  = mFixedLeftToggleOutline .left ;
226+  toggleEndX  = mFixedRightToggleOutline .left ;
227+ 228+ 229+  bgStartColor  = mToggleSettings .mBackgroundUnCheckedColor ;
230+  bgEndColor  = mToggleSettings .mBackgroundCheckedColor ;
231+  toggleStartColor  = mToggleSettings .mToggleUnCheckedColor ;
232+  toggleEndColor  = mToggleSettings .mToggleCheckedColor ;
168233 } else  {
234+ 235+ 236+  // for DayNightToggle mode 
169237 originX  = getWidth () - mBgRadius ;
170238 endX  = mBgRadius ;
171239 originY  = mToggleRadius ;
172240 endY  = 2  * mToggleRadius ;
173-  startBackgroundColor  = mToggleSettings .mBackgroundCheckedColor ;
174-  endBackgroundColor  = mToggleSettings .mBackgroundUnCheckedColor ;
175-  startToggleColor  = mToggleSettings .mToggleCheckedColor ;
176-  endToggleColor  = mToggleSettings .mToggleUnCheckedColor ;
241+ 242+ 243+  // for a normal toggle 
244+  toggleStartX  = mFixedRightToggleOutline .left ;
245+  toggleEndX  = mFixedLeftToggleOutline .left ;
246+ 247+  bgStartColor  = mToggleSettings .mBackgroundCheckedColor ;
248+  bgEndColor  = mToggleSettings .mBackgroundUnCheckedColor ;
249+  toggleStartColor  = mToggleSettings .mToggleCheckedColor ;
250+  toggleEndColor  = mToggleSettings .mToggleUnCheckedColor ;
177251 }
178252
179253 mToggleAnimator  = ValueAnimator .ofFloat (0 , 1.0f );
@@ -185,10 +259,13 @@ private void animateToggle(boolean toggleToOn) {
185259 @ Override 
186260 public  void  onAnimationUpdate (ValueAnimator  animation ) {
187261 float  fraction  = animation .getAnimatedFraction ();
262+  mAnimatedToggleX  = floatEvaluator .evaluate (fraction , toggleStartX , toggleEndX );
263+ 188264 mSunCenterX  = floatEvaluator .evaluate (fraction , originX , endX );
189265 mCenterDistance  = floatEvaluator .evaluate (fraction , originY , endY );
190-  mBackgroundColor  = (int ) argbEvaluator .evaluate (fraction , startBackgroundColor , endBackgroundColor );
191-  mToggleColor  = (int ) argbEvaluator .evaluate (fraction , startToggleColor , endToggleColor );
266+ 267+  mBackgroundColor  = (int ) argbEvaluator .evaluate (fraction , bgStartColor , bgEndColor );
268+  mToggleColor  = (int ) argbEvaluator .evaluate (fraction , toggleStartColor , toggleEndColor );
192269 invalidate ();
193270 }
194271 });
@@ -248,40 +325,69 @@ protected int[] onCreateDrawableState(int extraSpace) {
248325 return  drawableState ;
249326 }
250327
328+  RectF  mBgRect  = new  RectF ();
329+ 251330 @ Override 
252331 protected  void  onDraw (Canvas  canvas ) {
253332 super .onDraw (canvas );
254333 pathBg .reset ();
255334 pathSun .reset ();
256335 pathMoon .reset ();
257336
337+  drawBackground (canvas );
338+  drawToggle (canvas );
339+  //drawSun(canvas); 
340+ 341+  if  (mShowAssistantLine ) {
342+  canvas .drawRect (mFixedLeftToggleOutline , mDebugPaint );
343+  canvas .drawRect (mFixedRightToggleOutline , mDebugPaint );
344+  }
345+  }
258346
259347
260-  pathBg .addArc (mLeftToggleOutline , 90 , 180 );
261-  pathBg .moveTo (mBgRadius , 0 );
262-  pathBg .lineTo (mBgRadius  * 4 , 0 );
263-  pathBg .addArc (mRightToggleOutline , 270 , 180 );
264-  pathBg .moveTo (getWidth () - mBgRadius , mBgRadius  * 2 );
265-  pathBg .addRect (mBgRadius , 0 , getWidth () - mBgRadius , mBgRadius  * 2 , Path .Direction .CW );
348+  void  drawToggle (Canvas  canvas ) {
349+  mDrawingToggleRect .set (mFixedLeftToggleOutline );
350+  mDrawingToggleRect .offset (mAnimatedToggleX  - mFixedLeftToggleOutline .left , 0f );
266351
352+  pathSun .addRoundRect (mDrawingToggleRect , mToggleRadius , mToggleRadius , Path .Direction .CW );
353+ 354+  mPaint .setColor (mToggleColor );
267355 mPaint .setStyle (Paint .Style .FILL );
268-  mPaint .setColor (mBackgroundColor );
269-  canvas .drawPath (pathBg , mPaint );
356+  canvas .drawPath (pathSun , mPaint );
270357
358+  if  (mShowAssistantLine ) {
359+  canvas .drawRect (mDrawingToggleRect , mDebugPaint );
360+  }
361+  }
362+ 363+  void  drawSun (Canvas  canvas ) {
271364 pathSun .addCircle (mSunCenterX , mBgRadius , mToggleRadius , Path .Direction .CW );
272-  pathMoon .addCircle (mSunCenterX  - mCenterDistance  * SCALE , mBgRadius  - mCenterDistance  * SCALE , mToggleRadius , Path .Direction .CW );
365+ 366+  //pathMoon.addCircle(mSunCenterX - mCenterDistance * SCALE, mBgRadius - mCenterDistance * SCALE, mToggleRadius, Path.Direction.CW); 
273367
274368 // a big circle subtracts a small circle, results a moon shape 
275369 //pathSun.op(pathMoon, Path.Op.DIFFERENCE); 
276370
277371 mPaint .setColor (mToggleColor );
278372 mPaint .setStyle (Paint .Style .FILL );
279373 canvas .drawPath (pathSun , mPaint );
374+  }
280375
281-  if  (mShowAssistantLine ) {
282-  canvas .drawRect (mLeftToggleOutline , mDebugPaint );
283-  canvas .drawRect (mRightToggleOutline , mDebugPaint );
284-  }
376+  void  drawBackground (Canvas  canvas ) {
377+ 378+ // pathBg.addArc(mFixedLeftToggleOutline, 90, 180); 
379+ // pathBg.moveTo(mBgRadius, 0); 
380+ // pathBg.lineTo(mBgRadius * 4, 0); 
381+ // pathBg.addArc(mFixedRightToggleOutline, 270, 180); 
382+ // pathBg.moveTo(getWidth() - mBgRadius, mBgRadius * 2); 
383+ // pathBg.addRect(mBgRadius, 0, getWidth() - mBgRadius, mBgRadius * 2, Path.Direction.CW); 
384+ 385+  mBgRect .set (0 , 0 , mWidth , mHeight );
386+  pathBg .addRoundRect (mBgRect , mBgRadius  , mBgRadius  , Path .Direction .CW );
387+ 388+  mPaint .setStyle (Paint .Style .FILL );
389+  mPaint .setColor (mBackgroundColor );
390+  canvas .drawPath (pathBg , mPaint );
285391 }
286392
287393 @ Override 
0 commit comments