إنشاء عناصر واجهة برمجياً باستخدام PureLayout (الجزء 1)

مرحبا يا هبر! أقدم إليكم ترجمة المقال " إنشاء قيود UIViews برمجياً باستخدام PureLayout" بواسطة علي ياكا.

صورة

سأوجهك اليوم من خلال إنشاء واجهة مستخدم بسيطة لتطبيقات الهاتف المحمول مع رمز ، دون استخدام لوحات القصة أو NIBs. لن أخوض في المناقشات حول أيهما أفضل ، لأن كل شيء له إيجابيات وسلبيات ، لذلك سأترك فقط رابطًا يتناول هذه المسألة .

في الجزء الثاني من هذا الدليل ، سننشئ بعض عناصر واجهة مستخدم تطبيقات الهاتف الأكثر استخدامًا مع رمز ، بما في ذلك شريط التنقل وعرض الجدول والخلايا ذات الحجم الديناميكي.

نظرة عامة


تمت كتابة هذا البرنامج التعليمي باستخدام Xcode 9 و Swift 4. وأفترض أيضًا أنك معتاد على Xcode و Swift و CocoaPods.

دون مزيد من التأخير ، لنبدأ في إنشاء مشروعنا: تطبيق بسيط لبطاقة الاتصال. الغرض من هذه المقالة هو تعليمك كيفية إنشاء واجهة المستخدم للتطبيق الخاص بك في التعليمات البرمجية ، وبالتالي لن يحتوي على أي منطق يتعلق بوظيفة التطبيق ، إلا إذا كان ذلك ضروريًا لأغراض هذا الدليل.

إنشاء قيود برمجياً باستخدام PureLayout


إعداد المشروع


ابدأ بتشغيل Xcode -> "إنشاء مشروع Xcode جديد". حدد "تطبيق عرض واحد" وانقر فوق "التالي".

صورة

اسم المشروع كما تريد ، قررت أن أسميها ContactCard. امسح الخيارات الثلاثة أدناه وحدد Swift كلغة برمجة ، ثم انقر فوق التالي.

صورة

حدد موقعًا على جهاز الكمبيوتر الخاص بك لحفظ المشروع. قم بإلغاء تحديد "إنشاء مستودع Git على نظام التشغيل Mac الخاص بي."

نظرًا لأننا لن نستخدم Twitter أو NIBs في هذا المشروع ، فاحذف "Main.storyboard" ، والذي يمكن العثور عليه في Project Navigator:

صورة

بعد ذلك ، انقر فوق المشروع في متصفح المشروع وعلى علامة التبويب "عام" ، ابحث عن القسم الذي يحتوي على معلومات النشر وحذف كل ما هو مكتوب في "الواجهة الرئيسية". هذا هو ما يخبر Xcode أي ملف Storyboard يتم تحميله عند بدء تشغيل التطبيق ، ولكن بما أننا حذفنا للتو "Main.storyboard" ، فلن يعثر Xcode على هذا الملف ، مما يؤدي إلى تعطل التطبيق.

صورة

إنشاء ViewController


إذا قمت بتشغيل التطبيق الآن ، فستظهر شاشة سوداء ، لأن التطبيق لم يعد لديه مصدر واجهة مستخدم ، لذلك سنقوم بإنشائه في الجزء التالي. افتح "AppDelegate.swift" وداخل application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) ، الصق جزء الشفرة هذا:

 self.window = UIWindow(frame: UIScreen.main.bounds) let viewController = ViewController() self.window?.rootViewController = viewController self.window?.makeKeyAndVisible() 

يوفر هذا الرمز نافذة لتفاعل المستخدم مع التطبيق ، والذي يمكن العثور عليه عادة في "ViewController.swift". للتحقق بسرعة من أن كل شيء يعمل ، انتقل إلى "ViewController.swift" وفي طريقة viewDidLoad() ، أدخل السطر التالي:

 self.view.backgroundColor = .blue 

الآن قم بتشغيل التطبيق.

للتنقل بين الملفات في Xcode ، استخدم مفاتيح الاختصار "⇧⌘O" ، ثم أدخل اسم الملف أو حتى جزء الشفرة الذي تبحث عنه ، وستظهر قائمة بالملفات التي يمكنك الاختيار منها على الشاشة.

بعد بدء التطبيق ، يجب أن تكون هذه هي النتيجة على شاشة جهاز المحاكاة الخاص بك:

صورة

بالطبع ، لن نستخدم هذا اللون الأزرق .blue للاشمئزاز ، لذا فقط قم بتغيير الخلفية إلى اللون الأبيض عن طريق استبدال .blue بـ .white viewDidLoad () .

تطوير واجهة المستخدم


لإنشاء واجهة المستخدم الخاصة بنا ، سنستخدم مكتبة تجعل حياتنا أسهل بكثير. لتثبيت PureLayout ، يجب أولاً فتح القرص المضغوط الخاص بك وكتابة القرص المضغوط ، ثم مساحة ، واسحب مجلد المشروع إلى المحطة الطرفية ثم اضغط على "إدخال". الآن قم بتشغيل الأوامر التالية داخل الجهاز:

  • جراب الحرف الأول
  • تثبيت جراب

يجب أن يكون هذا ناتج الجهاز بعد الأمر الثاني:

صورة

بعد ذلك ، أغلق Xcode ، افتح المجلد في Finder ، وستجد "<اسم مشروعك> .xcworkspace". هذا هو ما سنفتحه للوصول إلى تطبيقنا إذا كنا بحاجة إلى استخدام CocoaPods. الآن ابحث عن الملف المسمى "PodFile" واكتب السطر التالي تحت عبارة use_frameworks!

 pod “PureLayout 

قم بتشغيل pod install مرة أخرى في الجهاز ، ثم قم ببناء مشروعك بالضغط على "Command + B".

استراحة قهوة


الآن وقد تم إعداد كل شيء ، لنبدأ بالعمل الحقيقي. انتقل إلى "ViewController.swift" وانتزاع فنجانًا من القهوة ، لأن هذا هو الشكل الذي ستبدو عليه النتيجة النهائية:

صورة

إنشاء ImageView


أدخل سطر import PureLayout ضمن import UIKit حتى تتمكن من استخدام المكتبة في هذا الملف. بعد ذلك ، بموجب إعلان الفئة وخارج أي وظيفة ، نبدأ بإنشاء المتغير Avatar ImageView كسول (كسول) كما يلي:

 lazy var avatar: UIImageView = { let imageView = UIImageView(image: UIImage(named: "avatar.jpg")) imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0)) imageView.layer.borderWidth = 3.0 imageView.layer.borderColor = UIColor.lightGray.cgColor imageView.layer.cornerRadius = 64.0 imageView.clipsToBounds = true return imageView }() 

بالنسبة للصورة ، احفظ أي صورة على سطح المكتب ستستخدمها كأفاتار ، واسحبها إلى Xcode في مجلد <اسم مشروعك> ، والذي يسمى في حالتي "ContactCard" ، وحدد مربع "نسخ العناصر إذا لزم الأمر" .

صورة

بعد ذلك ، اكتب اسم هذا الملف مع امتداده في إعلان UIImage بدلاً من "avatar.jpg".

بالنسبة لأولئك منكم الذين لا يعرفون ، تشبه المتغيرات البطيئة المتغيرات العادية ، باستثناء أنه لم تتم تهيئة (أو يتم تخصيص بعض مساحة الذاكرة) حتى يتم الاحتياج إليها أو استدعاؤها للمرة الأولى . هذا يعني أن المتغيرات البطيئة لا تتم تهيئتها عند تهيئة وحدة التحكم في العرض ، ولكن توقع نقطة لاحقة عند الحاجة إليها حقًا ، مما يوفر طاقة المعالجة ومساحة الذاكرة لعمليات أخرى. هذا مفيد بشكل خاص عند تهيئة مكونات واجهة المستخدم.

PureLayout في العمل


كما ترى داخل التهيئة ، فإن خط imageView.autoSetDimensions (to: CGSize (width: 128.0, height: 128.0)) هو PureLayout قيد التنفيذ. في سطر واحد ، وضعنا حدًا لارتفاع وعرض UIImageView ، ويتم إنشاء جميع NSLayoutConstrict اللازمة دون الحاجة إلى استدعاءات الوظائف الضخمة. إذا كنت تتعامل مع إنشاء قيود برمجية ، فمن الأرجح أنك وقعت بالفعل في حب هذه المكتبة الرائعة.

لجعل هذه الصورة مستديرة ، قمنا بتعيين نصف قطرها الزاوي إلى نصف عرضها أو ارتفاعها ، وهو 64.0 نقطة. بالإضافة إلى ذلك ، قمنا بتعيين خاصية clipsToBounds إلى true ، والتي تخبر الصورة أنه يجب عليها قص كل شيء خارج نصف القطر الذي حددناه للتو.

ثم ننتقل إلى إنشاء UIView التي ستكون بمثابة الجزء العلوي من العرض وراء الصورة الرمزية باللون الرمادي. قم بتعريف المتغير البطيء التالي لهذا العرض:

 lazy var upperView: UIView = { let view = UIView() view.autoSetDimension(.height, toSize: 128) view.backgroundColor = .gray return view }() 

إضافة مقابلات فرعية


قبل الانتقال ، دعنا ننشئ وظيفة func addSubviews () التي تضيف المشاهدات التي أنشأناها للتو (وجميع المشاغل الأخرى التي سنقوم بإنشائها) كقوائم فرعية إلى وحدة تحكم العرض:

 func addSubviews() { self.view.addSubview(avatar) self.view.addSubview(upperView) } 

الآن أضف السطر التالي إلى viewDidLoad (): self.addSubviews ()

وضع قيود


للحصول على فكرة عن المدى الذي وصلنا إليه ، دعونا نضع قيودًا على هذين النوعين. قم func setupConstraints() وظيفة أخرى تسمى func setupConstraints() وأدخل القيود التالية:

 func setupConstraints() { avatar.autoAlignAxis(toSuperviewAxis: .vertical) avatar.autoPinEdge(toSuperviewEdge: .top, withInset: 64.0) upperView.autoPinEdge(toSuperviewEdge: .left) upperView.autoPinEdge(toSuperviewEdge: .right) upperView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom) } 

الآن داخل viewDidLoad() استدعاء setupConstraints() ، كما يلي: self.setupConstraints() . أضف هذا بعد استدعاء addSubviews() . يجب أن يكون هذا هو الاستنتاج النهائي:

صورة

جلب الصورة الرمزية إلى الصدارة


لسوء الحظ ، هذا ليس ما أود الحصول عليه. كما ترون ، وضعنا العلوي على قمة الصورة الرمزية. ويرجع ذلك إلى حقيقة أننا أضفنا صورة رمزية subviews قبل العرض upperView ، وبما أن هذه المقاطع الفرعية موجودة في شكل ما في المجموعة ، فإننا نحصل على هذه النتيجة. لإصلاح ذلك ، يمكننا ببساطة استبدال هذين الخطين ببعضهما البعض ، ولكن هناك خدعة أخرى أريد أن self.view.bringSubview (toFront: avatar) ، وهي: self.view.bringSubview (toFront: avatar) .

ستقوم هذه الطريقة بنقل الصورة الرمزية من أسفل الحزمة إلى الأعلى ، لذلك اختر الطريقة التي تفضلها. بطبيعة الحال ، من أجل سهولة القراءة ، من الأفضل إضافة عروض فرعية بترتيب عرضها في حالة تقاطعها ، مع تذكر أن المقابلات الفرعية المضافة الأولى ستكون في أسفل الحزمة ، وبالتالي ستظهر أي طرق عرض متقاطعة أخرى أعلىها.
وهذه هي الطريقة التي ينبغي أن تبدو في الواقع:

صورة

إنشاء تحكم مجزأ


بعد ذلك ، سننشئ عنصر تحكم مجزأ ، وهو شريط رمادي يحتوي على ثلاثة أقسام. في الواقع ، من السهل إنشاء عنصر تحكم مجزأ. قم بما يلي:

 lazy var segmentedControl: UISegmentedControl = { let control = UISegmentedControl(items: ["Personal", "Social", "Resumè"]) control.autoSetDimension(.height, toSize: 32.0) control.selectedSegmentIndex = 0 control.layer.borderColor = UIColor.gray.cgColor control.tintColor = .gray return control }() 

أعتقد أن كل شيء واضح ، والفرق الوحيد هو أنه بعد التهيئة نقدمها مع مجموعة من السلاسل ، كل صف يمثل عنوان أحد الأقسام المطلوبة لدينا. لقد قمنا أيضًا بتعيين selectedSegmentIndex على 0 ، والذي يخبر عنصر التحكم المجزأ بتحديد / تحديد الجزء الأول أثناء التهيئة. الباقي هو مجرد أسلوب للعب به.

دعنا الآن نمضي قدمًا addCubviews(): self.view.addSubview(segmentedControl) كطريقة عرض فرعية بإدراج السطر التالي في نهاية وظيفة addCubviews(): self.view.addSubview(segmentedControl) وستكون حدوده كما يلي:

  segmentedControl.autoPinEdge(toSuperviewEdge: .left, withInset: 8.0) segmentedControl.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) segmentedControl.autoPinEdge(.top, to: .bottom, of: avatar, withOffset: 16.0) 

نقول للتحكم المقسم أننا نريد إرفاقه بالجانب الأيسر من رؤيته الفائقة ، لكننا نريد زيادة الفاصل الزمني قليلاً ، وليس إرفاقه مباشرة على حافة الشاشة. إذا لاحظت ، فأنا أستخدم ما يسمى الشبكة المكونة من ثماني نقاط ، حيث تكون كل المسافات والأحجام مضاعفات ثمانية. أفعل نفس الشيء على الجانب الأيمن من عنصر التحكم المجزأ. أما بالنسبة إلى القيد الأخير ، فيقول إنه يعلق قمة على قاعدة الصورة الرمزية بفاصل 16 نقطة.

بعد إضافة القيود المذكورة أعلاه إلى func setupConstraints() بتشغيل التعليمات البرمجية وتأكد من أنها تبدو كما يلي:

صورة

إضافة زر


سننتقل الآن إلى الجزء الأخير من واجهة مستخدم الكتاب المدرسي ، وهو زر "تحرير". أضف المتغير البطيء التالي:

 lazy var editButton: UIButton = { let button = UIButton() button.setTitle("Edit", for: .normal) button.setTitleColor(.gray, for: .normal) button.layer.cornerRadius = 4.0 button.layer.borderColor = UIColor.gray.cgColor button.layer.borderWidth = 1.0 button.tintColor = .gray button.backgroundColor = .clear button.autoSetDimension(.width, toSize: 96.0) button.autoSetDimension(.height, toSize: 32.0) return button }() 

لا تقلق بشأن حجم التهيئة ، لكن عليك الانتباه إلى كيفية تعيين العنوان ولونه من خلال استدعاء button.setTitleColor و button.setTitleColor . لأسباب معينة ، لا يمكننا تعيين عنوان زر من خلال الوصول مباشرة إلى titleLabel الخاص به ، وهذا بسبب وجود حالات مختلفة للزر ، وسيكون من المناسب بالنسبة للكثيرين أن يكون لديهم رؤوس / ألوان مختلفة لحالات مختلفة.

الآن قم بإضافة الزر كطريقة عرض فرعية ، مثل باقي المكونات ، وقم بإضافة القيود التالية بحيث تظهر في المكان الذي يجب أن تكون فيه:

 editButton.autoPinEdge(.top, to: .bottom, of: upperView, withOffset: 16.0) editButton.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) 

نحن هنا نضع فقط الحد الأيمن والأعلى للزر ، لأننا قدمنا ​​له حجمًا ، فلن يتوسع ولن تكون هناك حاجة إلى أي شيء آخر. قم الآن بتشغيل المشروع لمعرفة النتيجة النهائية:

صورة

بعض الملاحظات الحديثة


الممارسة ، إضافة العديد من عناصر الواجهة كما تريد. إنشاء طرق عرض لأي تطبيق تجد صعوبة. تبدأ بسيطة وزيادة تدريجيا صعوبة. حاول رسم مكونات واجهة المستخدم على قطعة من الورق لتخيل كيف تناسبها معًا.
في الجزء الثاني ، قمت بتوسيع هذا الدليل لإنشاء شريط تنقل وطاولة عرض وخلايا ذات حجم ديناميكي في التعليمات البرمجية.

Source: https://habr.com/ru/post/ar444854/


All Articles