Autolayout programmatically in Swift
Overview
Apple doc အရ iOS မှာ UI component တွေကို layout လုပ်နိုင်တဲ့နည်း သုံးမျိုးရှိပါတယ်။ ပထမတစ်နည်းကတော့ CGRect(x: y: width: height:) နဲ့ x, y coordinate တွေကို superview ရဲ့ coordinate system အပေါ်မူတည်တွက်ချက်ပြီး layout ချရတာပါ။ ဒီနည်းက သင်္ချာတော်တော်တွက်ရပြီး size class အမျိုးမျိုးမှာ အဆင်ပြေအောင် layout ချဖို့ တော်တော်လက်ဝင်ပါတယ်။ ဟိုးအရင်တုန်းက သုံးကြတဲ့နည်းပါ။ အဲ့ကနေမှ ဒုတိယအနေနဲ့ autoresizing mask ဆိုတာပေါ်လာပါတယ်။ Autoresizing mask ဆိုတာကတော့ ခုနကလို view ရဲ့ frame ကိုတွက်ချက်ပြီး layout ချတဲ့နေရာမှာ superview ရဲ့ frame change သွားရင် sub view ရဲ့ frame တွေကို recalculate လုပ်ပေးတဲ့သဘောပါ။ အထိုက်အလျှောက်တော့ အဆင်ပြေလာတယ်လို့ပြောလို့ရပေမယ့် frame ကိုအမြဲ calculate ပြန်လုပ်ပေးနေရပါသေးတယ်။ Complex ဖြစ်တဲ့ layout တွေအတွက်ဆို အဆင်မပြေနိုင်ပါဘူး။ အဲ့လိုကနေ Apple က autolayout ဆိုတာကို မိတ်ဆက်လိုက်ပါတယ်။ လက်ရှိအချိန်အထိ autolayout ဟာ ui component တွေကို layout ချရာမှာ အသုံးပြုသင့်တဲ့ recomended solution ဖြစ်ပါတယ်။
What is Autolayout
Autolayout က constraint တွေကိုသုံးပြီး view တစ်ခုရဲ့ width, height, x, y coordinate တွေကို တွက်ချက် layout ချပေးပါတယ်။ Constraint ဆိုတာကတော့ view နှစ်ခုကြားက relationship ဖြစ်ပါတယ်။ ဉပမာ view x နဲ့ view y ရဲ့ နှစ်ခုကြားမှာ ဘယ်လောက်ခွာရမယ်ဆိုတာကို constraint နဲ့သတ်မှတ်ပါတယ်။ အဲ့ constraint အပေါ်မူတည်ပြီး view x ရဲ့ x,y coordinate နောက်တစ်ခါ view y ရဲ့ x, y coordinate စတာတွေကို နောက်ကွယ်မှာတွက်ချက်ပြီး render လုပ်တာဖြစ်ပါတယ်။ UIKit မှာဆိုရင် ui component တွေအားလုံးက UIView ရဲ့ subclass တွေဖြစ်ကြပါတယ်။ UIView မှာ ပုံမှန်ကတော့ intrinsic content size မရှိပါဘူး။ Intrinsic content size ဆိုတာ view တစ်ခုရဲ့ size ကဘယ်လောက်ဖြစ်သင့်တယ်ဆိုတာကို သူ့ရဲ့ content အပေါ်မူတည်ပြီး တွက်ချက်ပေးနိုင်တာကိုခေါ်တာပါ။ ဉပမာ UIButton ဆို intrinsic content size ရှိတဲ့အတွက် button title အပေါ်မူတည်ပြီး button ရဲ့ width, height ကို တွက်ချက်နိုင်ပါတယ်။ UILabel ဆိုရင်လည်း သူ့ရဲ့ text အပေါ်မူတည်ပြီး width, height ကို တွက်ချက်နိုင်ပါတယ်။ Intrinsic content size ရှိတဲ့ view တွေဆိုရင်တော့ width, height ကို explicitly သတ်မှတ်ပေးစရာမလိုပေမယ့် intrinsic content size မရှိတဲ့ view တွေမှာတော့ constraint အပေါ်မူတည်ပြီး width, height ကို သတ်မှတ်ပေးရပါတယ်။ အခုကနေစပြီးတော့ autolayout basic တွေကို သိတယ်လို့ယူဆပြီး autolayout ကို programmatically ဘယ်လိုရေးသားမလဲဆိုတဲ့အပိုင်းကို ဆက်လက်လေ့သွားကြပါမယ်။
Why programmatic autolayout?
ပုံမှန်ကတော့ storyboard မှာ autolayout constraint တွေကို သတ်မှတ်ကြလေ့ရှိပါတယ်။ ဒါပေမယ့် storyboard ရဲ့
- View controller တွေများလာတာနဲ့အမျှ loading time ကြာခြင်း
- Git conflict ရှင်းရခက်ခဲခြင်း
- UI မှာ ဘာ properties တွေ သတ်မှတ်ထားလဲဆိုတာ ကြည့်ဖို့မလွယ်ကူခြင်း
စတဲ့အားနည်းချက်တွေကြောင့် developer အများစုက မသုံးကြပါဘူး။ တစ်ချို့ကလည်း storyboard နဲ့ code နှစ်ခုကို mix လုပ်ပြီး hybrid အနေနဲ့ အသုံးပြုကြပါတယ်။ ဒါပေမယ့် UI ကိုတော့ code နဲ့ရေးတာများပါတယ်။ နောက်တစ်ခါ async display kit (အခု texture ဖြစ်သွား) လိုမျိုး asynchronous ui solution တွေကို သုံးမယ်ဆိုရင် programmatic ui နဲ့ ရေးသားရမှာဖြစ်ပါတယ်။ ဒါကြောင့် programmatic autolayout ကို လေ့လာထားသင့်ပါတယ်။
Start writing autolayout codes
View တစ်ခုကို autolayout နဲ့ programmatically ရေးမယ်ဆိုရင် လုပ်ပေးရမှာ သုံးခုရှိပါတယ်။
- ကိုယ် layout လုပ်ချင်တဲ့ view ကို parent view ထဲအရင် add လုပ်ရပါမယ်။
- ကိုယ် layout လုပ်ချင်တဲ့ view ရဲ့ autoresizing mask ကို ဖြုတ်ပေးရပါမယ်။ အဲ့တာမှ autolayout က အလုပ်လုပ်မှာပါ။
- View ကို သူ့ parent view ဒါမှမဟုတ် သူနဲ့ same parent ဖြစ်နေတဲ့ view တစ်ခုခုနဲ့ ကိုယ်လိုချင်တဲ့ပုံစံအတိုင်း constraint သတ်မှတ်ပေးရပါမယ်။ ပြီးရင်တော့ အဲ့ constraint ကို activate လုပ်ပေးရပါမယ်။
- redBox ကိုview.addSubview နဲ့ parent view ရဲ့ hierarchy ထဲကို ထည့်လိုက်ပါတယ်။
- redBox ရဲ့ autoresizing mask ကို disable လုပ်ရပါမယ်။
- ပြီးရင်တော့ ကိုယ်လိုချင်တဲ့ layout ပုံစံအတိုင်း constraint ချိန်ရပါမယ်။ ဒီနေရာမှာ constraint ကို activate လုပ်ပေးဖို့လည်းလိုပါတယ်။ တစ်ကယ်လို့ တစ်ခုချင်းဆီ လိုက်ပြီး active မလုပ်ချင်ဘူးဆိုရင် NSLayoutConstraint.activate([]) ဆိုပြီး [] ထဲမှာ constraint တွေကို ရေးထားလို့လည်းရပါတယ်။ Constraint လုပ်တဲ့အခါမှာ top, leading ကတော့ positive value က screen ရဲ့ top, leading ကနေ constraint ကန်တာဖြစ်တဲ့အတွက် ပြသနာမရှိပါဘူး။ Trailing, bottom တို့ကနေ ခွာချင်တယ်ဆိုရင်တော့ negative value ကို သတ်မှတ်ပေးရပါတယ်။ အောက်မှာ fb profile လိုမျိုး view တစ်ခုရေးပြထားပါတယ်။ အဲ့ code ကို follow up လုပ်ကြည့်ရင်နားလည်သွားပါလိမ့်မယ်။
UIView တစ်ခုမှာ constraint လုပ်နိုင်ဖို့ leading, trailing, top, bottom, centerX, centerY, width, height ဆိုပြီး anchor ရှစ်မျိုးရှိတယ်လို့ အကြမ်းဖျင်းမှတ်ထားနိုင်ပါတယ်။ Apple ရဲ့ recomended practice အရ leftAnchor, rightAnchor ထက် leadingAnchor, trailingAnchor ကိုသုံးပါမယ်။ NSLayoutAnchor တိုင်းမှာ constraint ဆိုတဲ့ function ရှိပါတယ်။ Constraint ဆိုတဲ့ function မှာ anchor point အချင်းချင်း constraint လုပ်တာအပြင် constant value တစ်ခု အသေသတ်မှတ်တာ၊ view တစ်ခုခုရဲ့ width, height အပေါ်မူတည်ပြီး scale ပြန်လုပ်တာ စတာတွေအများကြီး လုပ်လို့ရပါတယ်။ Storyboard ထက်ပိုပြီး flexible ဖြစ်ပါတယ်။ အဲ့အပိုင်းကိုတော့ ကိုယ့်ဘာသာ layout clone လေးတွေရေးပြီးစမ်းကြည့်သင့်ပါတယ်။
Programmatic ui က code ရေးရတာဖောင်းပွပေမယ့် autolayout ကိုနားလည်ထားရင် code အဖြစ်ပြန်ပြောင်းရေးရတာ လွယ်တယ်လို့ပြောလို့ရပါတယ်။ အားသာချက်ကတော့ ပိုပြီး flexible ဖြစ်တဲ့အပြင် တစ်ခုခုပြင်ချင်ပြီဆိုရင် code ကိုဖွင့်ဖတ်လိုက်တာနဲ့ ဘယ်နေရာဘာလုပ်ထားတယ်ဆိုတာ တန်းသိနိုင်ပါတယ်။ Storyboard မှာဆိုရင် layout inspector မှာ သတ်မှတ်ထားတာလည်းဖြစ်နိုင်သလို code ထဲမှာ ရေးထားတာလည်းဖြစ်နိုင်တဲ့အတွက် တစ်ခုခုပြင်ချင်ရင် လက်ရှိ view မှာ ဘာ properties တွေရှိလဲဆိုတာကို ချက်ချင်းသိရဖို့ မလွယ်ပါဘူး။
ရှေ့မှာပြောခဲ့သလို autolayout က code ရေးရတာများတဲ့အတွက် အဲ့တာကိုသက်သာစေဖို့ Autolayout DSL(Domain specific language) တွေ အများကြီးပေါ်ပေါက်လာပါတယ်။ ဒါပေမယ့် စစချင်းမှာတော့ မသုံးသင့်သေးပါဘူး။ ကိုယ့်ဘာသာ code တွေအများကြီးရေးကြည့်ပြီး အသားကျလာမှသာ autolayout dsl တစ်ခုခုကိုကျွမ်းကျင်အောင်လေ့လာပြီး သုံးသင့်ပါတယ်။ အသုံးများတာတွေကတော့
စတာတွေဖြစ်ပါတယ်။ ဒါ့အပြင် Layoutless တို့လို UIKit နဲ့ SwiftUI ဆန်ဆန် stack view တွေနဲ့ layout ချလို့ရတဲ့ dsl တွေလည်း ရှိပါတယ်။ Alex Nagy ရဲ့ SparkUI မှာဆိုရင် layoutless တို့ kingfisher တို့ကို နောက်ကွယ်မှာသုံးထားပြီး ui ရေးဖို့တော်တော်လေးအဆင်ပြေတာကို တွေ့ရပါတယ်။ ဒါပေမယ့် doc မပြည့်စုံတာရယ် SwiftUI ပေါ်လာတာရယ်ကြောင့် SparkUI ကသိပ်မတွင်ကျယ်ဘူးဖြစ်သွားတယ်လို့ထင်ပါတယ်။ အဲ့တာတွေထဲမှာမှ ကျွန်တော့် favorite ကတော့ TinyConstraints နဲ့ Snapkit ဖြစ်ပါတယ်။ TinyConstraints က နာမည်အတိုင်း constraint တွေက tiny ဖြစ်ပါတယ်။ SnapKit ကတော့ closure ပုံစံကိုသုံးထားပြီး syntax က တအားရိုးရှင်း တအား clean ဖြစ်တာကြောင့် လေ့လာရတာ ပိုလွယ်ပါတယ်။
ကျွန်တော်တို့သိထားတာတွေကို အသုံးချပြီး facebook profile clone လေးတစ်ခု ရေးကြည့်ပါမယ်။
အပေါ်မှာ code တွေရေးထားတာဖောင်းပွနေပေမယ့် တစ်ကယ်က ရေးရတာရော ဖတ်ရတာရော တော်တော်လေးလွယ်ကူပါတယ်။ ဒါ့အပြင် တစ်ခုခုပြင်ချင်တယ်ဆိုရင် code ကိုဝင်ဖတ်လိုက်တာနဲ့ သိနိုင်ပါတယ်။ Constraint ဘယ်လိုချိန်ရမလဲဆိုတာကိုတော့ သိထားရပါမယ်။ တစ်ကယ်လို့ ဒီ syntax တွေကို အသားကျသွားပြီဆိုရင်တော့ ကျွန်တော်ရှေ့မှာပြောခဲ့တဲ့ autolayout dsl တစ်ခုခုကို လေ့လာပြီးရေးရင် code တွေလည်းရေးရတာနည်းသွားမှာပါ။
တစ်ခါတစ်လေ layout anchor တွေကို variable တစ်ခုနဲ့ store လုပ်ထားပြီး activate လုပ်ချင်တော့မှ ကောက်လုပ်လို့လည်းရပါတယ်။ Animation တွေအတွက်လည်း တော်တော်လေးလွယ်ကူလာပါတယ်။ Autolayout နဲ့ layout animation လုပ်တာကိုတော့ နောက်ပိုင်းဆက်ပြောပေးသွားပါမယ်။
ကျွန်တော့်ရဲ့ content တွေကို ကြိုက်နှစ်သက်တယ်ဆိုရင် နောက်လာမယ့် content တွေအတွက် follow လုပ်ထားပေးကြပါခင်ဗျာ။