Android自定義控制項 可拖動控制的圓環控制條

2021-09-19 07:36:59 字數 3569 閱讀 4873

前幾天收到這麼乙個需求,本來以為挺簡單的,沒想到最後發現實現起來還是有點小麻煩的,在這裡小小的總結一下。

先看看下面這張需求的樣圖:

然後在看一下最終實現的效果圖,可能是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...