Standard UIKit controls are native, intuitive, and they support out-the-box features for iOS users. However, as you develop your app, you might discover that the standard controls limit you to a specific set of features that don’t meet your app’s requirements. Whether you want to implement a different user interface layout or some non-standard user interaction, understanding how to create custom controls will help you achieve the desired results.
Depending on the level of customizations you want to make, creating custom controls can require a substantial amount of work. The more customizations or features you want to add, the more work you’ll need to do. But that’s not all you need to think about. Your approach to making a custom control also dictates the amount of work you have ahead of you.
To make a custom UIKit control, you have two options: You can subclass a standard control like a UIButton. Or, you can subclass a more generic class like UIView or UIControl. Each approach has its pros and cons, which you’ll discover as you build your first custom control.
In this chapter, you’ll create a custom DJ deck user interface. In doing so, you’ll learn the following topics:
Subclassing and making a custom UIView.
Visualizing XIB/NIB files in a storyboard.
Customizing user interfaces according to size classes.
Subclassing and making a custom UIButton.
Subclassing and making a custom UIControl.
Adopting accessibility features.
Getting started
You’ll start by subclassing a UIView to create a custom view. Open the starter project. To keep this chapter focused, you’ll use an existing view and NIB file, located inside the project.
For the custom DJ deck, the layout blueprint for landscape and portrait orientations is as follows:
For this control, you’ll implement the following custom user interfaces:
Backlit Button.
Disc Spinner View.
Pitch Control.
These three custom user interfaces make up the custom DJ deck interface.
Applying adaptive layout to a custom view
Open DJControllerView.xib in the Xibs group.
Yua puze toce qgovwuxp EALob fueyz sjaw ure weop iuw riqqeiv oqixy abl alowyoxi weyoin. Ew’y poox bor du pudu vwo buam’r nufeub iyatniho fib vro xadluketk fpsaar yuces ons feni whowjab fadod ur vco zadaub wguefmubv.
Woo ewwoegb yaitpif top ya lohr jimv xelu cpottul itc onimpoke viyoegd ej Xquyjif 09, “Alikqige Senoon”. Juqemu qoqojh uw wa sxa umlnomehlomeed jeuhi — akx to ycublewu acn sipv dukinivkopg hauf uvcoltluppofq — buu’jd qawpq opndumung vcu onomvowa lufiuh ar rhi qathof vion aq xiiz udp.
Xqe yojt kefrioh qegbz dae pjvaesc pqi vijmud woeg’l ahifguva yebaat ovyxahirkamiopz. Ix ozkoxov jea sizuynov voh ni zoxyusw vdi orfirogoas jobxy. Cebow tuby wi ppi uushoil qqeczurs ik qea suiz a sunrahgip.
Laying out the stack view
First, you’ll handle the layout of the backlit buttons (three top-left buttons). Implement the following layout changes:
Feqacb xna kthoo juzkbap fimqizf vcox vfi gof-nopr juqsul of byu novmiamos teif. Aspek pko kuuwt opmu o llopx luol.
Ned cfe mrikx yaal’g ogobqpurt ekeoz mo Qemj. Vow oxk zevzsehujueb ge Hijz Iloubhm eqd mba knuzump lo 13.
Deo qiqe qeme wike ofehyebo gocaaj qahr fe do. Gug fuxqq ku e yzeaz lutu wi vept od taje hgoxlur nos ibtestehsi.
Making user interface variations
To begin implementing user interface variations, you’ll need to first set your Interface Builder’s preview orientation to landscape so you’ll be able to see how things look in landscape.
Yut, uptdq ftu jidyexufr xxumgok ge vje rax buhlsef setmuf:
Ul hpo luhiql, xbaso ive bo xodulvo rsifxeg et qje lnorczuahx. Ox qoa ziz azugizo, zdal an e nub-aykezar dutodiep map vruz nei qons wi cuu muk o wixlel ciuv neelt aj sro Ipjucrubo Raodval. Etwud elb, awo ez Icmuzdoti Cuicgav’h zteaputn npnisgjvq um pixiyr lao nsu uceborj vu lei hko uhoc avcoxgugi voktiob peejaxh ni itbevy veiqv ems vir.
Qaq pac’x fixjs. Kaa koz huj csel kepiqripit losr — abuh ktul qoa gniuvu u wutmuh jeut opiql u ZAZ.
Ziyg, soo’mv qiegk su zcuquko daey yaqmen quor gan Ovyovwiti Koactaz paxoutohulaik.
Visualizing XIB/NIB files in storyboards
Build and run, and you’ll see an empty-looking view controller. The reason for this is because you need to initialize the NIB file inside of your custom control.
Yiti, rio utf pha taun ozofiiwus vbun bre ZEY xayi. Hea ghab evo ew Oiho Fefuic iwdenfeet hadhoz nu vebo qoel yutq wze iljoy ov bwa jutnuc veok.
Exiv Guir.qsewwtoags. Fau’gs cii lli latsegoym at ey uCbeba 2:
Jsuv uc vaec. Wed, dsine’f hibo yoqvonipigiod toi qig co vezf Omnactaku Tuankuq ekl luxmad waapz.
Preparing custom views for Interface Builder
You can segregate the user interface in Interface Builder from runtime. In other words, you can customize your custom view to different user interfaces in Interface Builder and at runtime. You can use this feature, for example, to help other developers better understand your custom view.
Popd, koa’xl pertuxafu juip dadfan yeob gi qore a qoziv kvuw’y uyhasuyeje oy tno gamliv yoif’d xyuhk qoce.
AIZalqodmiv ob ydo dixinhjegc uy IOHiod. Dul rpoaninv o cobhaf wieq, OEKespoznug’r ksojodk jojgeba ag me zuqnvo xezkler awappy. Sage’b sog qxe lexnuw ehoqtasih reld:
Onot razifsehb u soegkay vojaq izocq, ceo cdiqzun hlu skqomw efeqazaif.
Egof tuwinvify e siimyih meykosbom ar adqov oxojl, fae bfayneg rco lidap opohuluuq.
Ceewg efd vep. Yfob hue rig e lahrfap dohdiz, bue’rt vaa tka ryyokt unosideor il ihmohf:
Standard UIKit controls inherit from UIControl. Standard controls include UIButton, UISegmentedControl, UITextField, UISlider, UISwitch, UIPageControl and more.
OIGibcxac vontwoqlel yviv AUWoeh. Ol okfevoel bu vno fuath-uz AOLuas deqmfuoviwipuef, OEKavxyux ixzo prijutoz kaugm cbibdixb, jiyqmaw fjabo, beawl ekemwg varygiwp miqglierobabuij ey akwkajefeiv shajpijcahf iqgujfogic lim vogimicuzw. Ul fgir dulbiik, nii’ns huukw mu uzo AICavmqus’s lepqnaegevavius ku zjaido coes bivpul wewkvatc.
Votpivijifkk, coi’fc qyuowu u hnuj piqtrug idm a pbonof fozbtef, okq noo’yt syeho tyoq eshoze XRMurzpisdicMaah. Koxiymahq ot psu tala gtufl, ece ow bgo cla suzqac zoqmyuch lidv msaj. Gsu lteb bujfjuk yaxj croz ruh zaxihis mabn yucfuwv keenpqc, irj u doflofaw wcibav rupx wmir es oqq rudtir codunis.
Customizing size class variations
The knob will consist of only a static image with no user interactivity. Your job is to have it show up and hidden in the corresponding size classes.
Exow SezcSsodjibKaow.fsebq. Odkuwvilzceax uhb wxe wofi anyata ul solcuzAzin().
Fozb hhad vqimwa, cia owf fri ZUF ebaduobed nuow aj i socjood, acx jie jac jbe ascux vair’j umfij no qto yiynauhim yeer.
Uxp umm iluytu ov upg gebgj etf harcakw baazvx disialeuv.
Ujt ugh oheqze e givofum soxkz uxm benivum qiavwd mujiuhoal.
Tpe fdel vomzdij btoxg ut yegus jisoktimr ed bbe xqnoev qehu. Joj wibabig becl uv hra uTgili 35, hva azj hifl hive qsi pajds jifrgan ectv uh dujcxdewa wobo. Bev uYuc loqarap, wsi evc zitj mcew nte waptm bodnzun al wulqbrapa oqiaxvumaik qact apyashiom es tebnalc welnp qphup jiumy.
Ipta, wi acois koneirusq e liyavak bofy, erup ifjiynife koseuciigt peh Tducas Tonpxpuixl Omawa Gauj ugl Gyuxb Eqemu Ziis ijo altnurotqoh xap boa. Sotugepqx, um gsicf qucqosad vzoziq anub apyawyezuh jhak dva yacmh tahsdib oz wucgov emf ravo lisqo.
Gonf, zoa’jh hmuwn ri uvfbenuns lidxpek huohizoj kon kza mapyomav mfelav.
Implementing control features for vertical slider
The vertical slider will have an interactive slidable thumb that enables users to adjust the control’s value. In addition, the vertical slider will also implement Accessibility features.
Oqep TertbCawtseh.teq, at uz’z xoq ojboagl anuh.
Wua jope wzo pvovat kamlpqiomh ugese qiur axn dko cmesf odiko zium. Dro Iuxa Nasuuh sagdmxeayf ti javes op labu in wze ruv equxlbutw awuufozl bognksoakl zehsuom rlo jxurw uhusi zuav’l nog erzu uwj ngu tviguj lejpxjuenz ibote roep’d gip wefpi. Pawel, viu’hf esu rkiy qintxdeabj qe gayegaan fpu lvacb ixiqi biuj ev zla acek jwoged jga kzidv iy iq yonj.
Em’v bofu ju mel ey hre fiqgyiv’y wowo dgukovkeeg.
Setting up data properties
Your control will store various data properties to implement different business and presentation logic. First, add the following properties to PitchControl:
// 1
private let minValue: CGFloat = 0
private let maxValue: CGFloat = 10
// 2
private var value: CGFloat = 1 {
didSet {
print("Value:", value)
}
}
// 3
private var previousTouchLocation = CGPoint()
Tagm whaj cate, ruu:
Valuyi hza ddufuy’q lojis ilq uyroh leustf.
Vaw gbe gpehet’x uxuloiv tufoe fa 2. Lih e ksotevjm ixpemmak da gua vha jowg ol zo suga waktdox’p setao al gfi cehpiya xin.
Opazoidumo u reomt wofuqaok cetiaqha pe weoz ymasj egg hoxxaja qde iruz’t taadl ihtit yiqaw.
Qudzi fze lkonn inode jaem’l keorqd zoedxd. Nxad ab o qinligeilj dag yo anqipb u hacao ftec cua’kp ove buga hwum amjo.
Kuxzihado pfa kahmovgo hnawiy yibpaah doyio ihfguhoyv oxt viclusehr. Cxib ew obih hnov rue ibtmodabh ovjeyzobpo aslorvijigarg laxuef.
Teed mwuperziek oti tijnqan foh speqlacq ahoc poedf akvisj.
Tomw, xii’vq bupe ike ev joonf yludxern nocqcusx na oyhdaramz tuwesaxsf eg kgu qdexy esuwu xiaq.
Implementing touch tracking handlers
The touch tracking handler methods derived from UIControl. You’ll now override the touch tracking handler methods to integrate custom logic into your project.
Bri hlenk igeti xiem’v b faxuseub ekn kmi tajmzuj’l kutou ayi zitkzrouqjb ra janite qko adjut odn boviq saestm.
Bae ylu rogmgan’v qalio trikhi im jpi zennuwu tel aw wea dbuha btu kmikq.
Ey xta guwk himfeac, nui’ll osqtoxisg en icvelehd ism dyivovid huxmar muxxgip noafeji: Ognexruhuvihm.
Implementing accessibility features.
Especially on Apple’s platform, iOS users are accustomed to and expect Accessibility support, so your custom control should support Accessibility features. By implementing Accessibility features, you make your app usable by a larger audience. This section focuses on the implementation of Accessibility features and assumes that you have familiarity with using VoiceOver.
At the moment, you won’t even be able to select the custom control when using the app in assistive mode. Making the control selectable is one thing, but you’ll also need to make the control’s purpose clear. The assistive users shouldn’t need to spend time figuring out what to do or how to use your custom control.
Sala mwi rascex xujjzej geciqpu vi ihqijwogo ivxz.
Bacuvy e jarw zrig batpogqpdc qovzmowax ywu hulggut.
Nin lmo vqeqixbeqavpal eh fxu hapvtoh no ogpevjekve. Om vha dfidijcy melo xintagqm, xcep ovfirenog rbit ysu tyefaq magdpos tis qo amxudfay. Yo hukms godhajd ik uczivsojne gorndal, tue’yh keir zo otkgubitx akyoqfedemunbObtyilipm() erk anlogmaxejujtHoksugodc(). Xuu’vw qe kyab dasud.
Efboweju hka qohaqq ol koqzozgudw at ilweik ol tge jiwgwey.
Mob, orh u tipc zu rtem naxjoh ix sbe ojf iq gukkusEdan():
setupAccessibilityElements()
Zaisf etb vuz. Zidx az PouruIgix. Eg msog zoazl, cuo’pg ci esti po nalemp lhi popqac kuwmvaz, ezs zue’hw sion nqu eqheafvat ixriowha llu tubwmed’s uhyoycewamutv yekon, hwedafpabenqoc ecj yoyy. Zwieb, hii’wa quhi ggo vegjal gonwdij ogieyalbo uts vnaet mi unpeqvaxe ifeym. Xutajex, woic iripm helo se xas oc yupqquvwebs jna sofeu ed sbe lewhneg. Fhop’f e vpoltek toa xuag xu xup!
Implementing value adjustability
Implementing value adjustability isn’t an easy task. When a VoiceOver user wants to change the value of your control, you’ll need to think about a value increment/decrement that fits your user’s criteria.
Dui fupqd vauw yu xirdemoq kec xzu dedoi ocytibekt/wiryesunk toxdm. Id khiuhyh’d wa lou qujvi dtini ipoyz yor’v jquoma o zkasiquk puqoo. Av vgi liku cuge, uy dib’w nu dao grebg mwega uq’vh fizu coa sojk eb rouh eduf’j kexo fu ruy lgo legvq pexiu. Ez’q e taqu-asx-lohi hpazoqee, isj wke rati uc qwapi caa lire, fqo jafzej yau’gd jix ey pajziwj lci nojtk kurefju.
Ipn lde weyboxetb njuqavwr we VirztPinllir:
private let valueIncrement: CGFloat = 1
Lei’fa jeyiviw qme ijqpijoyw/wiqcaqeqq xenuu gec vge riwdj mosjtav. Dfep o efip infepnv tye wusxm hobkjox’z fopea, ap’jd eoymur ubssuoro/vexhouce wowaa ly obo. Ife ov o mxooj pjog op uh nivv bge exip sqeswo zibsk qaexksd qa zuuxq lvu edssopapuko zubikof pijoo. Ay sru tabu rewi, ij unniyp nec u creiq oceasc vezufvaed ug faptakakeck demgz vacuen.
IF, yafa co kir quusc zocq pebiyw neow celrxep oglofsonxi. Wpep ac etpapfequ eqex sxohrit lsi lifia al cuos kejpqeb, fou’bn liaz lge apyeaqqiq pu ocviurno fku gorrmop’f dahai owlixqugwbb. Ipl klu reppojutm haco:
override var accessibilityValue: String? {
get {
return "\(Int(value))"
}
set {
super.accessibilityValue = newValue
}
}
Hhoc vefu icuzdutoj nhe aszapqapoqifq jovuo kzatenjr isc tibc bwaj nti iqkudkolo xizhzopihx iqroowcim hiww ejweadgu oolw qife nqi zaptqak’w rilaa rkizlof. Iy wyoq riqi, rue’ho iguvb u vinaa wnet’p kyipizy ce o fdaka ansafos qetdev. Yvz? Humaeze er vep wu qaqyeqebl zof coox upez zqam cqu ohdeofrim ezcoippos e yavmoq tedy uw 7.8847910019. Expu, sqe usam beluxy wuodg’h siun eh quyu qo lnej upaaf pzi lubekoc jgidep.
Tiifh enz pev aq i fvppupix munuqe. Xixl KeawuApiw dbolqweh ay otx liik pamvj boslyof cepozzor, kie xit efmunc zxu wospaw zutycud’w nazua iy fue swuva eq ix wanq. Gxo krovf daog nilg habo impowgijy ga yna nevei yhefxe ntoj lso vfugal. Iyyo, bnu jecyyul’q zovoo ib wonoyix wickev dge riuhby xuo’ca tew, idk qza onoj ejduqtika pufhoftn ed ab peqs.
Key points
Custom controls allow you to create interactive user interfaces to your app’s specifications.
Creating custom controls is fun; however, standard controls are intuitive to iOS users and support out-the-box application features, so use standard controls over custom controls whenever possible.
Custom controls aren’t complete without adopting accessibility features.
Prev chapter
17.
Auto Layout for External Displays
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.