iOS 自定義控制項入門 可拖動的環形進度

2021-07-03 10:53:42 字數 2893 閱讀 7246

我們的自定義控制項繼承自uicontrol類,它是uiview的子類,是所有uikit控制項(uibutton, uislider, uiswitch等等等)的父類。

uicontrol例項的作用是建立相應的邏輯來將action分發到相應的target,90%的情況下,它會根據自身的狀態(例如highlighted, selected和disabled等)來繪製使用者介面。

uicontrol主要完成三個重要任務:

因此,對於這篇文章中要完成的圓形進度條,我們將要完成以下任務:

繪製乙個使用者可以通過拖動手柄滑塊來進行互動的使用者介面,使用者的操作會被轉化為target對應的actions,控制項將滑塊的frame origin轉換為0-360之間的乙個值,並用於target/action上。下面將分三步進行講解,這三步對應上面提到的三個重要任務。

如圖,我們將通過core graphics來繪製灰色的進度條背景、紅色的進度條、滑塊手柄,關於core graphics的基礎知識,本文不作詳細介紹.。

- (void)drawrect:(cgrect)rect
其中pointfromangle方法是從給定的角度得到圓環上對應的經緯度,只是簡單的使用了一下基本的三角函式關係:

-(cgpoint)pointfromangle:(int)angleint
完成了1.1,現在我們已經繪製好了使用者介面,但是它還不能響應我們的觸控事件。我們只要重寫(override)uicontrol的三個方法,就可以跟蹤使用者操作。

當使用者在uicontrol的bound內進行觸控,begintrackingwithtouch方法會被呼叫,此方法會返回bool型別,返回yes表示要繼續跟蹤觸控事件。

-(bool)begintrackingwithtouch:(uitouch *)touch withevent:(uievent *)event
上面的方法返回了yes,表示要繼續跟蹤觸控事件,所以當使用者在螢幕上拖動時,continuetrackingwithtouch會被呼叫,該方法返回的bool值表示是否繼續跟蹤touch事件。通過該方法我們將根據使用者觸控的位置更新手柄的位置。

-(bool)continuetrackingwithtouch:(uitouch *)touch withevent:(uievent *)event
其中,我們呼叫了movehandle:方法來更新滑動手柄的位置:

-(void)movehandle:(cgpoint)lastpoint
anglefromnorth(

cgpoint

p1,cgpoint

p2,bool

flipped

)方法是

計算中心點到任意點的角度,

是從蘋果是示例**clockcontrol中拿來的函式,比較複雜(數學沒學好...),就直接當作蘋果提供的乙個方法來呼叫就行。

static inline float anglefromnorth(cgpoint p1, cgpoint p2, bool flipped)
當結束跟蹤時,這個方法會被呼叫,我們的例子中不需要override這個方法

現在,圓形滑塊控制項可以工作了,拖動滑動手柄看看。

如果希望自己定製的控制項與uicontrol行為保持一致,那麼當控制項的值發生變化時,需要進行通知處理:使用sendactionsforcontrolevents方法,並制定特定的事件型別,值改變對應的事件一般是uicontroleventvaluechanged。

蘋果已經預定義了許多事件型別(xcode中,在uicontroleventvaluechanged上cmd + 滑鼠單擊)。如果你的控制項是繼承自uitextfield,那麼我們可能會對uicontroleventedigitingdidbegin感興趣,如果要做乙個touch up action,可以使用uicontroltouchupinside。在本文前部分的continuetrackingwithtouch方法裡面,我們已經呼叫了sendactionsforcontrolevents方法。

這樣處理之後,當控制項值發生變化時,每乙個物件(觀察者——註冊該事件)都會收到響應的通知。

除了通過使用者觸控事件來改變進度,有時我們還想通過**進行修改,我們只要自己實現儲存角度的屬性angle的set方法:

-(void)changeangle:(int)angle

好了,現在我們在viewcontroller中使用我們的控制項:

jxcircleslider *slider = [[jxcircleslider alloc] initwithframe:cgrectmake(0, 0, 250, 250)];

slider.center = self.view.center;

[slider addtarget:self action:@selector(newvalue:) forcontrolevents:uicontroleventvaluechanged];

[slider changeangle:120];

[self.view addsubview:slider];

我們先進行初始化,然後設定為居中顯示,註冊了值改變響應事件,當進度值改變時,會呼叫一下方法

-(void)newvalue:(jxcircleslider*)slider
專案源**:

最終效果如下:

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...