Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit afa081e

Browse files
committed
Added round rectangle toggle, user can set the background radius and toggle radius in XML
1 parent ef56c1c commit afa081e

File tree

4 files changed

+235
-47
lines changed

4 files changed

+235
-47
lines changed

‎app/src/main/res/layout/activity_main.xml‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,63 @@
1616
android:layout_width="50dp"
1717
android:layout_height="25dp"
1818
app:ltbChecked="true"
19+
app:ltbBackgroundRadius="5dp"
20+
app:ltbToggleRadius="4dp"
1921
app:ltbBackgroundCheckedColor="@color/colorAccent"
2022
app:ltbBackgroundUncheckedColor="@android:color/darker_gray"
2123
app:ltbToggleCheckedColor="@android:color/white"
2224
app:ltbToggleUncheckedColor="@android:color/white"
2325
app:ltbDuration="300"
2426
/>
2527

28+
<cn.intret.lab.library.LoadingToggleButton
29+
android:id="@+id/toggle2"
30+
app:layout_constraintLeft_toLeftOf="parent"
31+
app:layout_constraintTop_toBottomOf="@id/toggle"
32+
android:layout_marginLeft="16dp"
33+
android:layout_marginTop="16dp"
34+
android:layout_width="50dp"
35+
android:layout_height="25dp"
36+
app:ltbChecked="false"
37+
app:ltbBackgroundRadius="5dp"
38+
app:ltbToggleRadius="4dp"
39+
app:ltbBackgroundCheckedColor="@color/colorAccent"
40+
app:ltbBackgroundUncheckedColor="@android:color/darker_gray"
41+
app:ltbToggleCheckedColor="@android:color/white"
42+
app:ltbToggleUncheckedColor="@android:color/white"
43+
app:ltbDuration="300"
44+
/>
45+
46+
<cn.intret.lab.library.LoadingToggleButton
47+
android:id="@+id/toggle_round"
48+
app:layout_constraintLeft_toLeftOf="parent"
49+
app:layout_constraintTop_toBottomOf="@id/toggle2"
50+
android:layout_marginLeft="16dp"
51+
android:layout_marginTop="16dp"
52+
android:layout_width="50dp"
53+
android:layout_height="25dp"
54+
app:ltbChecked="false"
55+
app:ltbBackgroundCheckedColor="@android:color/holo_purple"
56+
app:ltbBackgroundUncheckedColor="@android:color/darker_gray"
57+
app:ltbToggleCheckedColor="@android:color/white"
58+
app:ltbToggleUncheckedColor="@android:color/white"
59+
app:ltbDuration="300"
60+
/>
61+
62+
<cn.intret.lab.library.LoadingToggleButton
63+
android:id="@+id/toggle_round2"
64+
app:layout_constraintLeft_toLeftOf="parent"
65+
app:layout_constraintTop_toBottomOf="@id/toggle_round"
66+
android:layout_marginLeft="16dp"
67+
android:layout_marginTop="16dp"
68+
android:layout_width="50dp"
69+
android:layout_height="25dp"
70+
app:ltbChecked="true"
71+
app:ltbBackgroundCheckedColor="@android:color/holo_purple"
72+
app:ltbBackgroundUncheckedColor="@android:color/darker_gray"
73+
app:ltbToggleCheckedColor="@android:color/white"
74+
app:ltbToggleUncheckedColor="@android:color/white"
75+
app:ltbDuration="300"
76+
/>
77+
2678
</android.support.constraint.ConstraintLayout>

‎library/src/main/java/cn/intret/lab/library/LoadingToggleButton.java‎

Lines changed: 141 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import android.graphics.Path;
1414
import android.graphics.RectF;
1515
import android.util.AttributeSet;
16+
import android.util.Log;
1617
import android.view.View;
1718
import 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 = newRectF();
46+
private RectF mFixedRightToggleOutline = newRectF();
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

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /