前幾天收到這麼乙個需求,本來以為挺簡單的,沒想到最後發現實現起來還是有點小麻煩的,在這裡小小的總結一下。
先看看下面這張需求的樣圖:
然後在看一下最終實現的效果圖,可能是gif錄製軟體的問題,有一些浮影,忽略就好了:
首先要分析一下最核心的地方,如何獲取到滑動距離對應的弧長,看圖:
p1是手指按下的點,很明顯要想知道當前進度弧邊的值,就是要求出角d的值。
以p為圓心點,atan(b)=math.atan((-p.y)/(-p.x));
所以角d的值為:math.todegrees(atan);
那麼角b的值就得出來了,b=math.todegrees(atan) + mprogressoffest;
圖中的圓可以分為四個象限,同理可以得出四個象限中求得弧長的方法:
/**
* 更新當前進度對應弧度
** @param x 按下x座標點
* @param y 按下y座標點
*/private
void
updatecurrentangle
(float x,
float y)
//02:第二象限-左上角區域
if(pointx <=
0&& pointy <=0)
//03:第三象限-左下角區域
if(pointx <=
0&& pointy >=0)
else
}//04:第四象限-右下角區域
if(pointx >=
0&& pointy >=0)
}
獲取手指按下的區域,避免誤判斷:
/**
* 按下時判斷按下的點是否按在圓環範圍內
** @param x x座標點
* @param y y座標點
*/private
boolean
istoucharc
(float x,
float y)
/** * 計算某點到圓點的距離
** @param x x座標點
* @param y y座標點
*/private
double
gettouchradius
(float x,
float y)
繪製bitmap;
/**
* 繪製小圓點bitmap
** @param canvas canvas
*/private
void
drawdragbitmap
(canvas canvas)
重寫ontouchevent事件;
@override
public
boolean
ontouchevent
(motionevent event)
break
;case motionevent.action_move:
if(mistouchonarc)
break
;case motionevent.action_up:
mistouchonarc =
false
; mtouchquadrant =0;
if(moncirqueprogresschangelistener != null)
moncirqueprogresschangelistener.
onchangeend
(mminprogress, mmaxprogress,
integer.
parseint
(mtext.
replace
("℃",""
)));
break;}
invalidate()
;return
true
;}
到這裡基本這個自定義控制項也就實現完了。但是!是不是!忘了點!什麼?沒錯,就是讓我蛋疼不已的圓環上下限值判斷。
由於手指滑動的時候,當前的angle值的範圍是0-360,因此不可能簡單的限定上下限。沒有做任何判斷的話,在起點處是可以隨意滑動的,如下圖所示:
很明顯這樣是不行的,然後就是一陣雞飛狗跳,簡(ou)簡(xin)單(li)單(xue)的一陣折騰之後,基本實現了要求,最後更新currentangle的**如下:
/**
* 更新當前進度對應弧度
** @param x 按下x座標點
* @param y 按下y座標點
*/private
void
updatecurrentangle
(float x,
float y)
//02:第二象限-左上角區域
if(pointx <=
0&& pointy <=0)
tan_x = pointx *(-
1); tan_y = pointy *(-
1); atan = math.
atan
(tan_y / tan_x)
;//求弧邊
mcurrentangle =
(int
) math.
todegrees
(atan)
+ mprogressoffest;
mlastquadrant =2;
}//03:第三象限-左下角區域
if(pointx <=
0&& pointy >=0)
}else
} mlastquadrant =3;
}//04:第四象限-右下角區域
//保證dragbitmap在峰值的時候不會因為滑到這個象限更新currentangle
if(pointx >=
0&& pointy >=0)
mlastangle = mcurrentangle;
}
其實做之前就真的覺得是挺簡單的乙個自定義控制項,結果萬萬沒想到因為最後這麼一點**折騰了半天。雖然最後這坨**看著確實挺蛋疼的,但是暫時也想不到什麼好的方法了,先這樣吧。
最後貼上完整**:
免費獲取安卓開發架構的資料(包括fultter、高階ui、效能優化、架構師課程、 ndk、kotlin、混合式開發(reactnative+weex)和一線網際網路公司關於android面試的題目彙總可以加入【安卓開發架構】
c 自定義可拖動變形控制項
public class 控制項移動變形類 usercontrol 控制項類 rectangle 傳遞控制項 傳遞控制項相對於本控制項的範圍 rectangle 本控制項 本控制項相對於自己的範圍 rectangle 調節點邊框 new rectangle 8 8個點相對於本控制項的範圍 recta...
自定義控制項的拖動
自定義控制項的拖動 新增事件 this.mouseup new system.windows.forms.mouseeventhandler this.dragend this.mousemove new system.windows.forms.mouseeventhandler this.dra...
自定義控制項的拖動
新增事件 this.mouseup new system.windows.forms.mouseeventhandler this.dragend this.mousemove new system.windows.forms.mouseeventhandler this.dragmove this...