0x0 åè¨
æè®¾è®¡ç½ç»å¸¸ä¼æå¾å¤ä¼ç§æ¼äº®ç交äºè®¾è®¡ä½åï¼æä¸å¤©ï¼å¶éè¿æ ·çææï¼å¨ç»æµç
ï¼äº¤äºèªç¶ï¼äºæ¯å头èªå·±è§£åå
¶ä¸çå
ç´ ï¼åäºä¸ªå¼æºæ§ä»¶ï¼åæ¥å¤©æäºä¸ç¾æ¥ä¸ªstarï¼è§å¾å¾å欢è¿ï¼ä»å¤©ä¸é¨åè¿æ½¦èå ç¬ï¼å享æ¡åç»è¿ï¼å¸æå¯¹åè¡ææå¸®å©ã
0x1 åå¤
1ãé»è®¤ç¶æï¼ç´çº¿ï¼é¦å°¾æ 注ï¼é»è®¤å¼æ 注ã
2ãæææä¸ï¼æ²çº¿å¨ç»æ§è¡ï¼æ è¯å°åè§åå°æ¾å¤§ï¼å¼çæ æ³¨æ ¹æ®æ²çº¿æ³¢å³°ç¸å¯¹ä½ç½®ä¸åï¼åä¸åéç§»å¨ï¼åæ¶ï¼æ æ³¨èæ¯æ¸åå æ·±ï¼å¨ç»ç»æã
3ãæææå¨ææï¼æ²çº¿ãå°åå½¢ãæ æ³¨ä¸è
åæ¶è·é触æ¸ç¹ç§»å¨ï¼åæ¶æ´æ°æ 注å¼ã
4ãææç¦»å¼å±å¹ï¼æ²çº¿æ¶åå¨ç»æ§è¡ï¼æ è¯å°åè§å缩å°å°é»è®¤ç¶æï¼éä¸çå¼è·éæ³¢å³°ä¸æ²å°é»è®¤ç¶æï¼æ æ³¨èæ¯æ¸åæ¶å¤±ï¼å¨ç»ç»æã
åå½¢æç¤ºå¨é¨å
æè§£ç¶æä¸é¨åï¼é»è®¤ç¶æã触æ¸è¿ç¨ä¸ã触æ¸åç¶æãå
¶ä¸é»è®¤ç¶æä¸æç¤ºå¨å¾å°çåå½¢ï¼è·ç¦»æ°´å¹³æ²çº¿ä¸æ¹ä¸ä¸ªçº¦å®è·ç¦»ï¼å½æä¸è¿ç¨ä¸ï¼åæä¸æ¹åæ ä¸åï¼åç´å¾éæ¸å¢å¤§ï¼åé¡¶é¨ä¸æ²çº¿çè·ç¦»ä¸åï¼ç´å°å¨ç»ç»æã
1ãæ§ä»¶å
å
ç´ ï¼æ å°ºãæ æ³¨ç¨çå°åãéä¸å¼ï¼åå¯é
ç½®åèªçé¢è²ï¼
2ãå¯é
ç½®å¼èå´ï¼
3ãå¯é
ç½®é»è®¤å¼ï¼
4ãå¯å®æ¶çå¬éä¸çå¼ã
5ã坿¾ç¤ºåä½ã
éè¿éææªå¾å¯ç¥æ¬æ§ä»¶ä¸»è¦å
ç´ ä¸ºè§¦æ¸è§¦åçæ²çº¿åå
¶ä¼¸ç¼©ææã让æä»¬æ¥ç®ååæä¸ä¸æ²çº¿é¨åçç»æï¼
//è¿éå±ç¤ºæ²çº¿æè§£å¾
æè§£åï¼è§¦æ¸é¨å为å
é¶è´å¡å°æ²çº¿ï¼äºä¸ªåºåç¹ï¼å个æ§å¶ç¹ï¼æä»¬å°å®æåæä¸¤ä¸ªä¸é¶æ²çº¿å³å¯ãå
¶ä¸ï¼é¦å°¾åºåç¹çYåæ åºå®ï¼Xåæ éç触æ¸ä½ç½®ç¸å¯¹ç§»å¨ï¼å©ä¸çåºåç¹Xåæ ç¸å¯¹åºå®ï¼Yåæ æ ¹æ®å¨ç»è§å¾åéãå说æ§å¶ç¹ï¼ä¸ºä¿éé»è®¤ç¶æä¸ï¼æ²çº¿é¨å为水平ï¼é¦å°¾ä¸¤ä¸ªæ§å¶ç¹çYåæ åºå®ï¼Xåæ ç¸å¯¹åºå®ï¼ä¸é´ä¸¤ä¸ªæ§å¶ç¹Yåæ åä¸é´é£ä¸ªåºåç¹ä¸è´ï¼Xç¸å¯¹ä¸é´åºåç¹åºå®ã
ï¼éè¿ä¸é¢çæè§£ï¼å¯ä»¥è®©æ²çº¿å¨é»è®¤ç¶æä¸æ¯ä¸æ¡æ°´å¹³ç´çº¿ï¼å¹¶ä¸å¨æä¸ç¶æä¸ï¼ä¸æ°´å¹³ä½ç½®ã波峰ä½ç½®ï¼è½ææ¯è¾èªç¶çè¿åº¦å¼§å½¢ï¼ä¸è³äºé£ä¹ç硬ãï¼
åå½¢æç¤ºå¨é¨å
æ®éåå½¢ï¼ç¸å¯¹èªèº«åºé¨åä¸å大ãåä¸ç¼©å°è¿åã
æä¸æ¶çå¨ç»éç¨æ®éçValueAnimatorï¼åéLinearInterpolatorãå¦å¤è¿æä¸ªéä¸å¼çèæ¯ååï¼æ ¹æ®å¨ç»è¿åº¦æ¹åç»ç¬Alphaå¼å³å¯ã
//è¿éåç¹å¨ç»ä»£ç å°ã
0x2 代ç å®ç°
泡æ¯è¶ï¼æ½èµ·è¢å弿¸ï¼
ç»§æ¿Viewï¼
public class BezierSeekBar extends View {
public BezierSeekBar(Context context) {
super(context);
init(context, null);
public BezierSeekBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
public BezierSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public BezierSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
private void init(Context context, AttributeSet attrs) {
this.context = context;
å¤å¶ä»£ç
å
ç»å¶åºæ²çº¿ææï¼
bezierPath.moveTo(this.fingerX - circleRadiusMax * 2 * 3, (float) 2 * height / 3);
bezierPath.cubicTo(this.fingerX - circleRadiusMax * 2 * 2, (float) 2 * height / 3, this.fingerX - circleRadiusMax * 2 * 1, (float) 2 * height / 3 - bezierHeight, this.fingerX, (float) 2 * height / 3 - bezierHeight);
bezierPath.moveTo(this.fingerX, (float) 2 * height / 3 - bezierHeight);
bezierPath.cubicTo(this.fingerX + circleRadiusMax * 2, (float) 2 * height / 3 - bezierHeight, this.fingerX + circleRadiusMax * 2 * 2, (float) 2 * height / 3, this.fingerX + circleRadiusMax * 2 * 3, (float) 2 * height / 3);
å¤å¶ä»£ç
æ¹åå
¶Yåæ ï¼è®©æ²çº¿æ¢å¤é»è®¤ç¶æï¼
ç»å¶å®æ´çº¿æ¡ï¼
bezierPath.reset();
bezierPath.moveTo(0, (float) 2 * height / 3);
bezierPath.lineTo(this.fingerX - circleRadiusMax * 2 * 3, (float) 2 * height / 3);
bezierPath.moveTo(this.fingerX - circleRadiusMax * 2 * 3, (float) 2 * height / 3);
bezierPath.cubicTo(this.fingerX - circleRadiusMax * 2 * 2, (float) 2 * height / 3, this.fingerX - circleRadiusMax * 2 * 1, (float) 2 * height / 3 - bezierHeight, this.fingerX, (float) 2 * height / 3 - bezierHeight);
bezierPath.moveTo(this.fingerX, (float) 2 * height / 3 - bezierHeight);
bezierPath.cubicTo(this.fingerX + circleRadiusMax * 2, (float) 2 * height / 3 - bezierHeight, this.fingerX + circleRadiusMax * 2 * 2, (float) 2 * height / 3, this.fingerX + circleRadiusMax * 2 * 3, (float) 2 * height / 3);
bezierPath.lineTo(width, (float) 2 * height / 3);
canvas.drawPath(bezierPath, bezierPaint);
å¤å¶ä»£ç
æ·»å Touchäºä»¶æ¦æªï¼æä¸æ¶æ¾ç¤ºæ²çº¿ï¼
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
fingerX = event.getX()
if (fingerX < 0F) fingerX = 0F
if (fingerX > width) fingerX = width
//触æ¸ä»è´¨è¿å
¥æ§ä»¶ï¼å¼å§å¨ç»è¿æ¸¡
this.animatorFingerIn.start()
break
case MotionEvent.ACTION_MOVE:
fingerX = event.getX()
if (fingerX < 0F) fingerX = 0F
if (fingerX > width) fingerX = width
postInvalidate()
break
case MotionEvent.ACTION_UP:
//触æ¸ä»è´¨ç¦»å¼æ§ä»¶ï¼æ§è¡å¨ç»
this.animatorFingerOut.start()
break
valueSelected = Integer.valueOf(decimalFormat.format(valueMin + (valueMax - valueMin) * fingerX / width))
if (selectedListener != null) {
selectedListener.onSelected(valueSelected)
return true
å¤å¶ä»£ç
æ·»å å¨ç»ææï¼
this.animatorFingerIn = ValueAnimator.ofFloat(0f, 1f)
this.animatorFingerIn.setDuration(200L)
this.animatorFingerIn.setInterpolator(new LinearInterpolator())
this.animatorFingerOut = ValueAnimator.ofFloat(1f, 0f)
this.animatorFingerOut.setDuration(200L)
this.animatorFingerOut.setInterpolator(new LinearInterpolator())
this.animatorFingerOut.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float progress = (float) animation.getAnimatedValue()
animInFinshed = (progress >= 0.15F)
txtSelectedBgPaint.setAlpha((int) (255 * (progress - 0.15F)))
if (progress >= 0.95F) {
textPaint.setColor(colorValueSelected)
} else {
textPaint.setColor(colorValue)
bezierHeight = circleRadiusMax * 1.5F * progress
circleRadius = circleRadiusMin + (circleRadiusMax - circleRadiusMin) * progress
spaceToLine = circleRadiusMin * 2 * (1F - progress)
postInvalidate()
å¤å¶ä»£ç
ç»å¶åå½¢æç¤ºå¨ï¼æ ¹æ®å¨ç»è¿åº¦æ¹åå
¶å¤§å°ï¼
canvas.drawCircle(this.fingerX, (float) 2 * height / 3 + spaceToLine + circleRadius, circleRadius, ballPaint);
å¤å¶ä»£ç
æ·»å å
¶å®è¾
å©å
ç´ åï¼é
ç½®éç¨å±æ§ï¼æåºå
Œ
±æ¹æ³ï¼
<declare-styleable name="BezierSeekBar">
//æ²çº¿é¢è²
<attr name="bsBar_color_line" format="reference|color" />
//åå½¢æç¤ºå¨é¢è²
<attr name="bsBar_color_ball" format="reference|color" />
//éå¼çææ¬é¢è²
<attr name="bsBar_color_value" format="reference|color" />
//éä¸å¼çææ¬é¢è²
<attr name="bsBar_color_value_selected" format="reference|color" />
//éä¸å¼çææ¬é¢è²èæ¯
<attr name="bsBar_color_bg_selected" format="reference|color" />
//é弿å°
<attr name="bsBar_value_min" format="integer" />
//é弿大
<attr name="bsBar_value_max" format="integer" />
//é»è®¤éä¸å¼
<attr name="bsBar_value_selected" format="integer" />
<attr name="bsBar_unit" format="reference|string" />
</declare-styleable>
å¤å¶ä»£ç
private void initAttr(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.BezierSeekBar)
this.colorBall = attributes.getColor(R.styleable.BezierSeekBar_bsBar_color_ball, Color.BLACK)
this.colorLine = attributes.getColor(R.styleable.BezierSeekBar_bsBar_color_line, Color.BLACK)
this.colorValue = attributes.getColor(R.styleable.BezierSeekBar_bsBar_color_value, Color.BLACK)
this.colorValueSelected = attributes.getColor(R.styleable.BezierSeekBar_bsBar_color_value_selected, Color.WHITE)
this.colorBgSelected = attributes.getColor(R.styleable.BezierSeekBar_bsBar_color_bg_selected, Color.BLACK)
this.valueMin = attributes.getInteger(R.styleable.BezierSeekBar_bsBar_value_min, 30)
this.valueMax = attributes.getInteger(R.styleable.BezierSeekBar_bsBar_value_max, 150)
this.valueSelected = attributes.getInteger(R.styleable.BezierSeekBar_bsBar_value_selected, 65)
this.unit = attributes.getString(R.styleable.BezierSeekBar_bsBar_unit) + ""
attributes.recycle()
å¤å¶ä»£ç
æåï¼æµè¯ä¸ä¸:
<tech.nicesky.bezierseekbar.BezierSeekBar
android:id="@+id/bsBar_test"
app:bsBar_color_ball="@android:color/white"
app:bsBar_color_bg_selected="@android:color/white"
app:bsBar_color_line="@android:color/white"
app:bsBar_color_value="@android:color/white"
app:bsBar_color_value_selected="#ef5350"
app:bsBar_value_min="30"
app:bsBar_value_max="120"
app:bsBar_value_selected="65"
app:bsBar_unit="kg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
å¤å¶ä»£ç
å®ç¾ :) ! éä¸demo APKï¼
æ¬æ§ä»¶ä¸»è¦æ¶åå°è´å¡å°æ²çº¿çåºç¡çè§£ååºç¨ãå¨ç»çåºç¡åºç¨ãèªå®ä¹æ§ä»¶çå¸¸è§æµç¨ï¼éç¹è¿æ¯çç»åç§UIææçåææè§£åæè·¯æ´çã
欢è¿Starï¼å¼æºå°åï¼
https:
å¤å¶ä»£ç