المحتوى عن 'xamarin'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • ASP.NET
    • ASP.NET Core
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 6 نتائج

  1. سنتناول في هذا الدرس من سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms تطبيقًا عمليًا آخرًا وهو تطبيق قارئ الخلاصات من موقع أكاديمية حسوب. تندرج مثل هذه التطبيقات تحت النوع rss feed reader ولها مزايا كثيرة ومتنوّعة. سيكون تطبيقنا بسيطًا وعمليًّا ويوضّح مبدأ العمل كما جرت العادة. سننفّذ التطبيق على مرحلتين: المرحلة الأولى سيكون تطبيق لعرض الخلاصات الموجودة ضمن أحد أقسام الموقع، مع إمكانية اختيار أيّ خلاصة وعرض تفاصيل حولها، وهذا هو محتوى هذا الدرس. أمّا المرحلة الثانية فستكون تحسين للتطبيق المنجز في هذا الدرس حيث سنضيف إمكانيّة قراءة الخلاصات من جميع أقسام الموقع مع إضافة بعض التحسينات على أسلوب العرض بشكل عام، وسيكون ذلك في درس منفصل. ماهي الخلاصات؟ خلاصات موقع تكون عادةً عبارة عن مستند XML يحتوي على بيانات تمثّل آخر الأخبار التي يوفّرها الموقع. لا تمتلك جميع المواقع خلاصات بالطبع، ولكنّ من الجيّد دومًا أن يوفّر الموقع مثل هذه الخلاصات في حال كان يمتلك محتوىً متجدّدًا كما هو الحال في موقع أكاديميّة حسوب. بما أنّ الخلاصة تكون ضمن ملف XML فمن البديهي أن تكون البيانات منسّقة بتنسيق XML، أي على شكل عقد آباء وأبناء. انظر مثلًا إلى جزء من خلاصات قسم مقالات البرمجة في أكاديميّة حسوب كما ظهرت لي عند كتابة هذا المقال: لاحظ أنّني أستعرض هذه الخلاصات عن طريق متصفّح Chrome عن طريق الرابط: https://academy.hsoub.com/programming/?rss=1 وهو الرابط الذي توفّره الأكاديميّة للحصول على خلاصات مقالات البرمجة. من الواضح أنّ هذا الأسلوب غير عملي في الحصول على آخر الخلاصات، لذلك يلجأ المستخدمون عادةً إلى تطبيقات متنوّعة لعرض هذه الخلاصات بشكل مريح ومقروء. تطبيق قارئ الخلاصات سنبني في هذا الدرس تطبيق قارئ خلاصات وظيفته قراءة الخلاصات الموجودة في قسم مقالات البرمجة في موقع أكاديميّة حسّوب. وسنعمل في الدرس التالي على تحسين هذا التطبيق بإتاحة الإمكانيّة لتصفّح الخلاصات من جميع الأقسام. أنشئ مشروعًا جديدًا من النوع Blank App (Xamarin.Forms Portable) وسمّه BasicFeedReader ثم أبق فقط على المشروعين BasicFeedReader (Portable) و BasicFeedReader.Droid كما وسبق أن فعلنا في هذا الدرس. الصنف FeedItem من نافذة مستكشف الحل Solution Explorer انقر بزر الفأرة الأيمن على المشروع BasicFeedReader واختر من القائمة التي ستظهر الخيار Add ثم من القائمة الفرعية الخيار New Folder لإضافة مجلّد جديد. سمّ هذا المجلّد بالاسم Entities، وبعد أن يظهر في نافذة الحل Solution Explore انقر عليه بزر الفأرة الأيمن واختر الخيار Add ومن القائمة الفرعية اختر Class. ستظهر نافذة تسمح لك بتعيين اسم لهذا الصنف. اختر الاسم FeedItem له. هذا الصنف هو حجر البناء الأساسي لهذا البرنامج. احرص على جعل محتويات الملف FeedItem.cs كما يلي: namespace BasicFeedReader.Entities { public class FeedItem { public string Link { get; set; } public string Title { get; set; } public string Description { get; set; } public override string ToString() { return Title; } } } الخصائص Link و Title و Description في هذا الصنف تقابل العناصر link و title و description في مستند XML. أمّا التابع ToString فهو للحصول على تمثيل نصّي لأي كائن من النوع FeedItem. الواجهات أضف مجلّدًا جديدًا للمشروع BasicFeedReader كما فعلنا قبل قليل، وسمّه Pages. ثم أضف إليه صفحتي محتوى تعتمدان رماز XAML بحيث يكون اسم الصفحة الأولى هو FeedDetailsPage وهي الواجهة الرئيسيّة، واسم الصفحة الثانية SectionFeedsPage وهي واجهة التفاصيل. الصفحة SectionFeedsPage هي الواجهة التي ستعرض خلاصات قسم مقالات البرمجة في أكاديمّية حسوب. أمّا الواجهة FeedDetailsPage فهي لعرض الخلاصة التي يتم اختيارها من الواجهة SectionFeedsPage. الواجهة SectionFeedsPage انتقل إلى الملف SectionFeedsPage.xaml واحرص على أن تكون محتوياته على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="BasicFeedReader.Pages.SectionFeedsPage"> <StackLayout> <ListView x:Name="lsvFeeds" ItemTapped="lsvFeeds_ItemTapped"/> </StackLayout> </ContentPage> لاحظ كم هو بسيط هذا الرماز، فهو لا يحتوي سوى عنصر قائمة lsvFeeds لعرض خلاصات قسم مقالات البرمجة، حيث سنربط الحدث ItemTapped الخاص بها بالمعالج lsvFeeds_ItemTapped. انتقل الآن إلى ملف الشيفرة البرمجيّة الموافق SectionFeedsPage.xaml.cs واحرص على أن تكون محتوياته على الشكل التالي: using BasicFeedReader.Entities; using System.Linq; using System.Xml.Linq; using Xamarin.Forms; namespace BasicFeedReader.Pages { public partial class SectionFeedsPage : ContentPage { public SectionFeedsPage() { InitializeComponent(); LoadFeeds("https://academy.hsoub.com/programming/?rss=1"); Title = "مقالات البرمجة"; } private async void lsvFeeds_ItemTapped(object sender, ItemTappedEventArgs e) { FeedItem selectedFeed = (FeedItem)e.Item; FeedDetailsPage feedDetailsPage = new FeedDetailsPage(selectedFeed); await Navigation.PushAsync(feedDetailsPage); } private void LoadFeeds(string resource) { XDocument doc = XDocument.Load(resource); var feeds = from newsItem in doc.Descendants("item") select new FeedItem { Title = newsItem.Element("title").Value, Description = newsItem.Element("description").Value, Link = newsItem.Element("link").Value }; lsvFeeds.ItemsSource = feeds; } } } عند يتم إنشاء كائن من هذه الصفحة لعرضها للمستخدم، يتم تنفيذ بانيتها. حيث يعمل التطبيق على استدعاء التابع LoadFeeds والذي يتطلّب وسيطًا واحدًا من النوع string ويمثّل عنوان المصدر المزوّد للخلاصات. في الحقيقة ما فعلناه هنا هو أمر غير جيّد من الناحية العمليّة، فلا ينبغي وضع مثل هذا الاستدعاء هنا في البانية، سيما وأنّ التابع LoadFeeds لا يستخدم تقنية البرمجة غير المتزامنة، مما سيسبب جمودًا مزعجًا في التطبيق عند أوّل تشغيله. سنحل هذه المشكلة لاحقًا في الجزء الثاني. انظر الآن إلى تعريف التابع LoadFeeds من الشيفرة السابقة. ستلاحظ أنّه يستخدم تقنيّة ممتازة يوفرها إطار العمل .NET من خلال الصنف XDocument الذي يمثّل مستند XML بشكل كائني، حيث يعمل السطر الأوّل من هذا التابع على إنشاء كائن جديد من الصنف XDocument من خلال تحميل مستند XML مباشرةً من الانترنت عن طريق التابع الساكن Load. بعد ذلك يتم إعراب مستند XML المحمّل من الإنترنت بسرعة وفعاليّة عاليتين. حيث تحتاج إلى عدد قليل من الأسطر البرمجيّة على شكل استعلام LINQ to XML لكي تقوم بالمطلوب. لقد اطلعنا على تقنيّة شبيهة في درس سابق حيث استخدمنا LINQ to Objects. يمكنك معرفة المزيد حول هذا الموضوع بقراءة هذا المقال. بعد استخلاص المعلومات من مستند XML المُحمّل، وإنشاء كائن من النوع FeedItem لكل خلاصة موجودة في هذا المستند، يتم إسناد المجموعة المنشأة من هذه الكائنات إلى الخاصيّة ItemsSource من القائمة lsvFeeds ليتم عرضها للمستخدم. أمّا بالنسبة لمعالج الحدث lsvFeeds_ItemTapped من الشيفرة السابقة. فوظيفته بسيطة، وهي تنحصر في الحصول على كائن FeedsItem الموجود ضمن العنصر الذي تمّ نقره (لمسه) ضمن القائمة lsvFeeds ومن ثمّ الانتقال إلى الصفحة FeedDetailsPage لعرض محتوى هذه الخلاصة. الواجهة FeedDetailsPage انتقل إلى الملف FeedDetailsPage.xaml واحرص على أن تكون محتوياته على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="BasicFeedReader.Pages.FeedDetailsPage"> <StackLayout Orientation="Vertical"> <WebView x:Name="wvDescription" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/> </StackLayout> </ContentPage> لاحظ مرّة أخرى كم هو بسيط هذا الرماز. حيث يقتصر على استخدام عنصر واحد، هو العنصر WebView ويُستخدم لعرض محتوى مستند HTML. وسبب استخدامي لهذا العنصر، هو أنّ الخلاصات التي ترد من موقع أكاديميّة حسّوب تحتوي على المحتوى كاملًا وهو منسّق بتنسيق HTML. وهذا أمر لا تجده في كثير من مزوّدات خدمة الخلاصات. لذلك فوجدت أنّ أفضل طريقة هو عرض هذا المحتوى مباشرةً ضمن عنصر WebView. انتقل الآن إلى ملف الشيفرة البرمجيّة الموافق FeedDetailsPage.xaml.cs واحرص على أن يكون كما في الشكل التالي: using Xamarin.Forms; using BasicFeedReader.Entities; namespace BasicFeedReader.Pages { public partial class FeedDetailsPage : ContentPage { public FeedDetailsPage(FeedItem feedItem) { InitializeComponent(); this.Title = feedItem.Title; var descriptionHtmlSource = new HtmlWebViewSource(); descriptionHtmlSource.Html = @"<html dir='rtl'><body>" + feedItem.Description + "</body></html>"; wvDescription.Source = descriptionHtmlSource; } } } كل الشيفرة البرمجيّة موجودة ضمن البانية التي تتطلّب وسيطًا واحدًا من النوع FeedItem الذي يحتوي على بيانات الخلاصة المراد عرض تفاصيلها. نعمل على وضع عنوان هذه الصفحة ليكون مطابقًا لعنوان الخلاصة، ثمّ ننشئ كائنًا من النوع HtmlWebViewSource نسنده ضمن المتغيّر descriptionHtmlSource الذي سيمثّل الكائن المحتوى للعنصر wvDescription (عنصر WebView الذي صرّحنا ضمن ملف الرماز). لاحظ كيف أسندنا للخاصيّة Html لهذا المتغيّر محتوى الخاصيّة Description لكائن الخلاصة، وهو كما أشرنا قبل قليل عبارة عن مستند HTML ينقصه فقط الوسمين و اللذان أضفناهما يدويًّا. ثمّ نُسند المتغيّر descriptionHtmlSource بدوره إلى الخاصيّة Source للعنصر wvDescription مما يؤدّي إلى ظهور مستند HTML كما هو مخطّط له. ملف التطبيق App.cs انتقل إلى ملف التطبيق App.cs واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = MainPage = new NavigationPage(new SectionFeedsPage()); } احرص على استخدام فضاء الاسم Pages لكي تستطيع الوصول إلى الصفحة SectionFeedsPage كما يلي: using BasicFeedReader.Pages; ستضع السطر السابق أوّل الملف App.cs كما هو معلوم. نفّذ البرنامج، ستحصل على شكل شبيه بما يلي: وهي الواجهة التي تحتوي على الخلاصات الموجودة ضمن قسم مقالات البرمجة. جرّب اختيار أحد هذه الخلاصات لتحصل على شكل شبيه بما يلي: لاحظ كيف تظهر الخلاصة كما لو أنّه يتم عرضها ضمن متصفّح الويب العادي. جرّب سحب الصفحة إلى الأسفل ليؤكّد ذلك هذه الملاحظة. الخلاصة تناولنا في هذا الدرس الجزء الأوّل من تطبيق قارئ الخلاصات الخاص بموقع أكاديميّة حسّوب. حيث نفّذنا بعض المهام الأساسيّة، والتي سنبني عليها في الجزء الثاني الذي سيتناول تطبيقًا محسّنًا لهذا التطبيق. حيث سنعمل على دعم عرض جميع الأقسام المتاحة في الأكاديميّة وليس قسم مقالات البرمجة فحسب.
  2. يُعتبر التعامل مع النصوص من المهام البرمجيّة الأساسيّة في جميع أنواع التطبيقات بما فيها تطبيقات الأجهزة المحمولة. توفّر Xamarin تقنيّات جيّدة للتعامل مع النصوص، سنتناول العديد منها من خلال هذا الدرس، وأيضًا من خلال دروس لاحقة في هذه السلسلة. سنعالج في هذا الدرس بعضًا من الحالات التي قد تواجه المطوّر عند التعامل مع النصوص في التطبيقات التي يُنشئها. التعامل مع المقاطع النصية نحتاج في الكثير من الأحيان أن نعرض نصًّا طويلًا بعض الشيء على الشاشة. قد يأتي هذا النص من مستند أو من خدمة ويب web service أو من غيرها من المصادر. المتنوّعة، وينبغي أن يتمكّن التطبيق من التعامل مع نصوص بمثل هذا الحجم. كما فعلنا من الدرس السابق، أنشأ مشروعًا جديدًا من النوع (Blank App (Xamarin.Forms Portable وسمّه TextManipulationApp. أبق فقط على المشروعين (TextManipulationApp (Portable و TextManipulationApp.Droid. سنضيف الآن صفحة محتوى content page جديدة ولكن بطريقة مختلفة ومختصرة عما فعلناه في الدرس السابق. انقر بزر الفأرة الأيمن على المشروع (TextManipulationApp (Portable واختر Add ثم من القائمة الفرعية التي ستظهر اختر New Item. اختر من الجهة اليسرى للنافذة التي ستظهر العقدة Cross-Platform، وبعد تحديث محتويات القسم الأوسط من النافذة، اختر نوع الملف Forms ContentPage وامنحه الاسم ParagraphPage من مريع الاسم Name في الأسفل، وبعد ذلك انقر Add. كما في الشكل التالي: بعد أن يضيف Visual Studio هذا الملف، ستكون محتوياته على الشكل التالي: using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using System.Text; using Xamarin.Forms; namespace TextManipulationApp { public class ParagraphPage : ContentPage { public ParagraphPage() { Content = new StackLayout { Children = { new Label { Text = "Hello ContentPage" } } }; } } } توجد نطاقات أسماء غير ضرورية هنا ولكن لا بأس بها حاليًا. لاحظ أنّ الصنف ParagraphPage يرث من الصنف ContentPage بشكل افتراضي، كما لاحظ أنّ بانية الصنف ParagraphPage جاهزة، وتحتوي على مثال بسيط جاهز. احذف محتويات هذه البانية، لنبدأ العمل على تطبيقنا. سننشئ لصيقة Label تحتوي على مقطع نصيّ مكتوب باللغة العربية. اكتب الشيفرة التالية ضمن بانية الصنف ParagraphPage: Content = new Label { VerticalOptions = LayoutOptions.Center, Text = "تُعتبر منصّة Xamarin في الوقت الحالي، من أهمّ منصّات تطوير تطبيقات الأجهزة المحمولة المتوفّرة،" + " والتي يبدو أنّها ستبقى على الواجهة لوقت ليس بالقليل، " + "خصوصًا بعد استحواذ شركة مايكروسوفت على الشركة المنتجة لها والتي تحمل أيضًا نفس الاسم." + "سنتعلّم من خلال هذه السلسلة كتابة تطبيقات عمليّة من خلال استخدام هذه التقنيّة الواعدة." }; انتقل إلى الملف App.cs ضمن المشروع (TextManipulationApp (Portal واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new ParagraphPage(); } نفّذ البرنامج باستخدام F5 لتحصل على شكل شبيه بما يلي: تجدر الملاحظة أنّه تتم مُحاذاة كامل النص رأسيًّا في منتصف الشاشة. سبب ذلك هو إسناد القيمة LayoutOptions.Center إلى الخاصيّة VerticalOptions (خيارات التموضع الرأسيّة) للصيقة Label. لاحظ أيضًأ أنّ النص في الشكل السابق تمّت مُحاذاته نحو اليسار، وليس إلى اليمين كما هو متوقّع بالنسبة للنصوص العربيّة. يعود سبب ذلك إلى أنّ الخاصيّة HorizontalTextAlignment من الصنف Label والمسؤولة عن المحاذاة الأفقيّة للنص ضمن اللصيقة سيكون لها القيمة الافتراضيّة TextAlignment.Start عند تشغيل البرنامج. و TextAlignment عبارة عن معدودة enum تحتوي على ثلاثة قيم هي: Start و Center و End. وبما أنّ شاشة الجهاز المحمول تُقسم إلى ثلاثة مناطق أساسيّة أفقيًا: Start للمنطقة اليسرى و Center للمنطقة الوسطى (المركزية) و End للمنطقة اليمنى من الشاشة لذلك ستتم محاذاة النص إلى اليسار بدلًا من اليمين. إذا أردنا أن تمم مُحاذاة النص إلى اليمين، فكل ما عليك فعله هو إسناد القيمة TextAlignment.End للخاصية HorizontalTextAlignment، وهذا ما سنفعله بعد قليل. وهناك أمر آخر نلاحظه أيضًا من الشكل السابق، وهو أنّ النص يقترب كثيرًا من حواف الشاشة حتى يكاد يلتصق بها. حلّ هذا الموضوع بسيط ويتمثّل في إضافة حشوة padding على حواف الشاشة، وهي عبارة عن مساحة صغيرة يمكن تعيينها برمجيًا للشاشة، نستطيع من خلالها التحكم بمساحة الهامش على الأطراف الأربعة لها. انظر الآن إلى بانية الصنف ParagraphPage بعد التعديلات المطلوبة: public ParagraphPage() { Content = new Label { VerticalOptions = LayoutOptions.Center, Text = "تُعتبر منصّة Xamarin في الوقت الحالي، من أهمّ منصّات تطوير تطبيقات الأجهزة المحمولة المتوفّرة،" + " والتي يبدو أنّها ستبقى على الواجهة لوقت ليس بالقليل، " + "خصوصًا بعد استحواذ شركة مايكروسوفت على الشركة المنتجة لها والتي تحمل أيضًا نفس الاسم." + "سنتعلّم من خلال هذه السلسلة كتابة تطبيقات عمليّة من خلال استخدام هذه التقنيّة الواعدة.", HorizontalTextAlignment = TextAlignment.End }; Padding = new Thickness(5, 5, 5, 5); } أضفنا أولًا الخاصيّة HorizontalTextAlignment إلى اللصيقة Label وأسندنا إليها القيمة TextAlignment.End لمحاذاة النص ضمن اللصيقة نحو اليمين (لاحظ أنّ الفاصلة العادية تفصل بين الخصائص). كما أضفنا الخاصية Padding (من الصنف ParagraphPage) وأسندنا إليها كائنًا جديدًا من الصنف Thickness (السماكة). تخضع بانية الصنف Thickness لزيادة التحميل حيث لها أكثر من شكل. استخدمت الشكل الأخير الذي يقبل أربعة وسائط تمثّل مقادير الحشوة padding من اليسار left والأعلى top واليمين right والأسفل bottom على الترتيب. قد تتساءل عن واحدة القياس المستخدمة هنا، ولكنني سنؤجل النقاش حولها إلى درس لاحق. عند تنفيذ البرنامج ستحصل على شكل شبيه بما يلي: لاحظ الآن كيف تمّت مُحاذاة النص نحو اليمين (ضمن اللصيقة Label)، ولاحظ أيضًا كيف ابتعد النص عن حواف الشاشة بعد تعيين الخاصية Padding لصفحة المحتوى ParagraphPage. ملاحظة: أرجو التمييز بين الخاصيتين HorizontalOptions و HorizontalTextAlignment للصيقة Label. فالأولى تمثّل خيارات التموضع الأفقية للصيقة ضمن الشاشة. أمّا الثانية فتمثّل محاذاة النص الأفقية ضمن اللصيقة. وبنفس الأسلوب، يجب التمييز بين الخاصيتين VerticalOptions و VerticalTextAlignment للصيقة Label ولكن من الناحية الرأسية بدلًا من الأفقية. تنسيق النص ضمن اللصيقة يمكن تنسيق النص الموجود ضمن لصيقة Label بالشكل الذي نرغبه عن طريق استخدام خاصيّة أخرى من خصائص اللصيقة وهي FormattedText. الخاصية FormattedText هي من الصنف FormattedString، والذي يحتوي بدوره على خاصية اسمها Spans من النوع <IList<Span فهي عبارة عن مجموعة (قائمة) من كائنات من النوع Span. أيُّ كائن من الصنف Span ينسّق جزءًا محدّدًا من النص الكلي، ويتم التحكم بهذا التنسيق من خلال ست خصائص من الصنف Span هي: جزء النص المراد تنسيقه Text واسم الخط FontFamily وحجم الخط FontSize وسمات الخط FontAttributes ولون النص ForegroundColor ولون الخلفية BackgroundColor. إذا شعرت ببعض الارتباك من الكلام السابق فلا بأس! سنوضّح هذه الأمور من خلال مثال بسيط يعمل على إضافة بعض التأثيرات على النص الذي يظهر على الشاشة. انظر أولًا إلى الشكل الذي أود الحصول عليه ثم لنوضّح كيفيّة فعل ذلك برمجيًّا: قد لا يبدو التنسيق السابق جميلًا، ولكنّه كفيل بتوضيح الفكرة. لاحظ في البداية أنّ كلمة "المجد" قد لوّنت باللون الأزرق مع خلفية صفراء. أمّا عبارة "لن تبلغ المجد حتى تلعق الصبر" فتم تلوينها باللون Aqua مع ملاحظة أنّ هذه العبارة ذات حجم نص أكبر من حجم النص للعبارة التي قبلها. لقد أضفت صنف محتوى جديد Forms ContentPage سميته FormattedParagraphPage إلى نفس المشروع (TextManipulationApp (Portable السابق، وبأسلوب مماثل للأسلوب الذي أضفنا فيه الصنف ParagraphPage في بداية هذا الدرس. انظر إلى محتويات الملف FormattedParagraphPage.cs: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection.Emit; 5 using System.Text; 6 7 using Xamarin.Forms; 8 9 namespace TextManipulationApp 10 { 11 public class FormattedParagraphPage : ContentPage 12 { 13 public FormattedParagraphPage() 14 { 15 FormattedString formattedString = new FormattedString(); 16 17 formattedString.Spans.Add(new Span 18 { 19 Text = "لا تحسبنّ ", 20 }); 21 22 formattedString.Spans.Add(new Span 23 { 24 Text = "المجد ", 25 BackgroundColor = Color.Yellow, 26 ForegroundColor = Color.Blue, 27 }); 28 29 formattedString.Spans.Add(new Span 30 { 31 Text = "تمرًا أنت آكله ", 32 }); 33 34 formattedString.Spans.Add(new Span 35 { 36 Text = "لن تبلغ المجد حتى تلعق الصبر.", 37 ForegroundColor = Color.Aqua, 38 FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) 39 }); 40 41 Content = new Label 42 { 43 VerticalOptions = LayoutOptions.Center, 44 FormattedText = formattedString, 45 HorizontalTextAlignment = TextAlignment.End, 46 FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)) 47 }; 48 49 Padding = new Thickness(5, 5, 5, 5); 50 } 51 } 52 } بدأنا في البانية (السطر 15) بإنشاء كائن من الصنف FormattedString وإسناده إلى المتغيّر formattedString. بعد ذلك بدأنا بإضافة النصوص المنسّقة إلى القائمة Spans باعتماد الأسلوب البسيط التالي (الأسطر من 17 حتى 20): formattedString.Spans.Add(new Span { Text = "لا تحسبنّ " }); استخدمنا التابع Add من القائمة Spans لإضافة كائن من النوع Span حيث أنشأنا هذا الكائن وأسندنا الخاصية Text له مباشرة عند الإنشاء. النص في الشيفرة السابقة لا يحمل أي تنسيق خاص. في الحقيقة لقد كرّرنا هذا الأسلوب من أجل كل جزء من النص الكامل. ولكنّنا اعتمدنا بعض التنسيقات النصيّة المختلفة أحيانًا. انظر مثلًا إلى الشيفرة الموجودة في الأسطر من 22 حتى 27: formattedString.Spans.Add(new Span { Text = "المجد ", BackgroundColor = Color.Yellow, ForegroundColor = Color.Blue, }); هذه المرّة نسّقنا النص "المجد" بحيث أسندنا اللون الأصفر كلون للخلفية BackgroundColor، واللون الأزرق للون النص ForegroundColor. انظر أيضًا إلى جزء النص الذي أضفناه في الأسطر من 34 حتى 39: formattedString.Spans.Add(new Span { Text = "لن تبلغ المجد حتى تلعق الصبر.", ForegroundColor = Color.Aqua, FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) }); هذه المرّة سيكون لون الخط Aqua وحجم الخط كبير Large. لاحظ كيف أسندنا قيمة حجم الخط إلى الخاصية FontSize. استخدمت لهذا الغرض التعبير التالي: Device.GetNamedSize(NamedSize.Large, typeof(Label)) الصنف Device يمثّل الجهاز الحالي الذي يعمل عليه تطبيقنا، ويحتوي على العديد من التوابع الساكنة المفيدة. من هذه التوابع استخدمنا التابع GetNamedSize الذي يُرجع حجم الخط المطلوب حسب الوسائط الممرّرة له. الوسيط الأول هو NamedSize.Large أي أنّنا نريد حجم كبير للخط (NamedSize هي معدودة)، والوسيط الثاني هو نوع العنصر المراد تطبيق هذا الخط عليه. في حالتنا نريد تطبيق هذا الخط على لصيقة Label لذلك مرّرنا (typeof(Label كوسيط ثانٍ حيث يُرجع النوع الخاص Type باللصيقة Label. هذا هو الأسلوب المفضّل في تعيين القياسات المناسبة لأيّ شيء يخطر ببالك، وذلك لأنّ الأجهزة التي نعمل عليها ستكون شاشاتها مختلفة القياسات بكلّ تأكيد، لذلك فنرغب أن نترك للتابع GetNamedSize مهمة القيام بالعمليات الحسابية المناسبة لإرجاع حجم الخط المناسب بالنسبة لحجم الشاشة التي يعمل عليها البرنامج حاليًا، وللحجم المراد الحصول عليه (في مثالنا هذا أردنا الحصول على حجم خط كبير NamedSize.Large وتوجد بالتأكيد قياسات أخرى). ما تبقى من البرنامج سهل للغاية، حيث نقوم في السطر 44 بإسناد المتغيّر formattedString إلى الخاصية FormattedText للصيقة. يكفل ذلك بعرض النص منسّقًا على الشاشة، مع الانتباه إلى أنّنا لم نستخدم في هذه الحالة الخاصية Text للصيقة. هناك أمر أخير يجب الانتباه إليه. لاحظ أنّنا في السطر 46 نُسند حجم خط جديد إلى الخاصية FontSize الخاصة باللصيقة. سيكون هذا الخط متوسّط الحجم (لاحظ الوسيط الأوّل NamedSize.Medium). الفكرة هنا هو أنّ هذا الخط سيطبّق على كل جزء من النص (موجود ضمن كائن Span) في حال لم تُعيّن الخاصية FontSize الخاصة بهذا الجزء. فمثلًا لن يطبّق هذا الحجم على جزء النص المعيّن في الأسطر بين 34 و 39. وذلك لأنّ هذا الجزء قد عيّن حجم خط خاص به (NamedSize.Large) كما رأينا قبل قليل. ملاحظة: ستحتاج لتجربة هذا البرنامج إلى تعديل بسيط ضمن بانية الصنف App ضمن الملف App.cs. احرص على أن تكون البانية على الشكل التالي لتستخدم صنفنا الجديد FormattedParagraphPage: public App() { // The root page of your application MainPage = new FormattedParagraphPage(); } الخلاصة تعرّفنا في هذا الدرس على مبادئ التعامل مع النصوص في Xamarin وبنينا للمرّة الأولى تطبيقين بسيطين يعرضان بعض المعلومات على المستخدم. تعلّمنا كيفيّة محاذاة النصوص وإجراء بعض عمليّات التنسيق عليها مثل تغيير لون النص ولون الخلفية لأيّ كلمة أو عبارة. لم يتناول هذا الدرس كيفيّة معالجة الحالة التي يكون فيها النص كبيرًا ويحتاج إلى وسيلة لتمريره لعرض محتوياته كاملة. سنعالج هذه المسألة في درس لاحق.
  3. سنبدأ في هذا الدرس من سلسلة برمجة تطبيقات الأجهزة المحمولة باستخدام Xamarin بالتعرّف على بنية التطبيق ضمن الحل Solution في Visual Studio 2015، بالإضافة إلى إنشائنا لتطبيق بسيط نتعرّف من خلاله على آلية عمل التطبيقات المبنية بواسطة Xamarin والتي تشبه في العديد من الجوانب مثيلاتها المنشأة باستخدام التقنيّات الأساسيّة المعتمدة في إنشاء تطبيقات أندرويد (لغة جافا مع Android Studio). بنية التطبيق المنشأ باستخدام Xamarin شغّل برنامج Visual Studio 2015، وبعد ظهور النافذة الرئيسيّة انتقل إلى القائمة File ومنها إلى New ثم اختر من القائمة الفرعيّة التي ستظهر الخيار Project. وكما فعلنا في الدرس السابق، اختر من الجهة اليسرى للنافذة التي ستظهر Cross-Platform، ثمّ اختر المشروع (Blank App (Xamarin.Forms Portable من القسم الأوسط للنافذة. امنح هذا المشروع الاسم SimpleTextApp ثم انقر الزر OK. سنبني تطبيقًا بسيطًا يوضّح كيفيّة استخدام لُصيقة Label وحيدة في إظهار النص في التطبيقات المبنيّة باستخدام Xamarin. من مستكشف الحل Solution Explorer الذي يوجد عادةً في الجهة اليمنى لنافذة بيئة التطوير Visual Studio، أبقِ فقط على المشروعين SimpleTextApp.Droid و (SimpleTextApp (Portable لأنّنا سنتعامل مع تطبيقات أندرويد فحسب (كما اتفقنا أيضًا من الدرس السابق). احذف باقي المشاريع الإضافيّة، يجب أن تحصل على شكل شبيه بما يلي: يحتوي المشروع (SimpleTextApp (Portable على معظم الشيفرة البرمجيّة، وهذا سلوك عام في المشاريع ذات النمط PCL. حيث تُعتبر الشيفرة الموجودة ضمن المشروع (الذي يحمل المقطع Portable بالإضافة لاسمه) مشتركة لجميع أنواع التطبيقات العاملة على أيّ نظام تشغيل بما فيه أندرويد. نلاحظ الملف App.cs الأساسي الذي سيكون موجودًا في أيّ تطبيق Xamarin وقد تحدثنا عنه في الدرس السابق ورأينا كيف يحتوي على الصنف App الذي يرث من الصنف Application، وكيف أنّ بانية هذا الصنف هي المسؤولة عن إنشاء الصفحة الرئيسيّة للتطبيق. انشر العقدة References لترى المراجع الخاصّة بهذا المشروع. ستلاحظ وجود عدّة مكتبات يهمّنا منها: Xamarin.Forms.Core و Xamarin.Forms.Platform و Xamarin.Forms.Xaml هذه هي المكتبات الرئيسيّة المشكّلة لـ Xamarin.Forms. بالنسبة للمشروع SimpleTextApp.Droid فهو يحتوي على مجلّدين هما: Assets و Resources. بالنسبة للمجلّد Resources فيحتوي على ملفات الصور وملفات معلومات التخطيطات layouts descriptions وغيرها من الملفات التي تُعتبر بمثابة المصادر resources لتطبيقك. انشر المجلّد Resources لترى بنيته. أمّا بالنسبة للمجلّد Assets فتُوضَع ضمنه الملفات العامّة الأخرى التي ترغب بتضمينها مع تطبيقك. يحتوي هذا المشروع أيضًا على الملف MainActivity.cs الذي يحوي ضمنه صنف له نفس الاسم MainActivity وهو يمثّل الفعاليّة Activity الأساسيّة لتطبيق أندرويد. افتح هذا الملف لتجد أنّ هذا الصنف يحتوي على التابع OnCreate الذي يُنفَّذ عند بدء تشغيل تطبيق أندرويد. لاحظ العبارة البرمجيّة التالية ضمن هذا التابع: LoadApplication(new App()); من الواضح أنّها تنشئ كائنًا جديدًا من الصنف App الموجود ضمن المشروع (SimpleTextApp (Portable، ثم تمرّره إلى التابع LoadApplication مباشرةً ليعمل على تحميل التطبيق وإظهاره للمستخدم. إذًا فعند تشغيل تطبيق أندرويد، سينفّذ التابع OnCreate الموجود في الصنف MainActivity أولًا، حيث يعمل هذا التابع على إنشاء كائن جديد من الصنف App فينفّذ بانيته وهي المسؤولة عن إنشاء الصفحة الرئيسيّة للتطبيق كما أشرنا. على أيّة حال ستتوضّح الفكرة بشكل جيّد بعد أن نبدأ بكتابة الشيفرة البرمجيّة. كتابة الشيفرة البرمجية انقر بزر الفأرة الأيمن على اسم المشروع (SimpleTextApp (Portable في مستكشف الحل Solution Explorer لتظهر قائمة سياق، اختر منها Add ثمّ من القائمة الفرعيّة اختر Class. ستظهر النافذة الخاصّة بإضافة صنف جديد. من حقل الاسم Name من الأسفل اكتب الاسم التالي لهذا الصنف الجديد وهو MainPage، ثم انقر Add. سيعمل Visual Studio على إضافة ملف جديد إلى المشروع اسمه MainPage.cs يحتوي على صنف بنفس اسمه ومحتواه شبيه بما يلي: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleTextApp { class MainPage { } } لن نحتاج إلى معظم نطاقات الأسماء الموجودة في الشيفرة السابقة في هذا البرنامج، سنحتاج حاليًا إلى نطاق الاسم Xamarin.Forms. وسنجعل الصنف MainPage يرث من الصنف ContentPage كما سنضيف البانية إليه. عدّل الشيفرة السابقة لتصبح على الشكل التالي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { } } } لاحظ أنّني تخلصت من جميع نطاقات الأسماء غير الضرورية (على أية حال سيظهر أي نطاق اسم غير مُستَخدَم في الشيفرة البرمجيّة بلون باهت في بيئة التطوير Visual Studio 2015). سيلعب الصنف MainPage دور صفحة محتوى content page رئيسيّة للتطبيق SimpleTextApp. سنضع ضمن بانية هذا الصنف الشيفرة البرمجيّة اللازمة لإنشاء لُصيقة واحدة Label تحوي نصًّا بسيطًا. ثم سنجري بعض التجارب البسيطة على هذه اللُّصيقة. يُعتبر هذا البرنامج بسيطًا في الواقع، ومهمته جعلك أكثر تآلفًا مع Xamarin. سنبدأ بإنشاء لُصيقة من الصنف Label وذلك ضمن بانية الصنف MainPage. تُستخدم اللُصيقات عادةً لعرض النصوص إلى المستخدم. انظر إلى الشيفرة البسيطة التالية: Label lblMain = new Label(); lblMain.Text = "Welcome to Hsoub Academy!"; ننشئ لُصيقة كما ننشئ أيّ كائن من صنف ما. أنشأنا في الشيفرة السابقة كائنًا جديدًا من الصنف Label وأسندناه إلى المتغيّر lblMain. ثم أسندنا النص "!Welcome to Hsoub Academy" إلى الخاصيّة Text من المتغيّر lblMain. تُستَخدم الخاصية Text لضبط وقراءة المحتوى النصيّ للُّصيقة. كي نستطيع عرض اللُّصيقة السابقة على الصفحة الرئيسيّة للتطبيق، علينا إسناد المتغيّر lblMain إلى الخاصيّة Content من الصنف ContentPage. وبما أنّ الصنف MainPage يرث من ContentPage فستكون الخاصيّة Content موجودة تلقائيًّا ضمنه أيضًا. ستكون عمليّة الإسناد على الشكل التالي: this.Content = lblMain; تكون عمليّة الإسناد السابقة ممكنة لأنّ الصنف Label يرث من الصنف View الذي يمثّل واجهة عرض view بمفهومها العام. وبما أنّ الخاصيّة Content هي من النوع View أيضًا فتكون عمليّة الإسناد هذه ممكنة. ستكون محتويات الملف MainPage.cs شبيهة بما يلي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage:ContentPage { public MainPage() { Label lblMain = new Label(); lblMain.Text = "Welcome to Hsoub Academy!"; this.Content = lblMain; } } } هذا كلّ شيء! علينا الآن القيام بخطوة صغيرة أخيرة، وهي في جعل تطبيقنا يُنشئ كائن من صنفنا الجديد MainPage وذلك ضمن الملف App.cs. انتقل إلى هذا الملف (موجود ضمن المشروع (SimpleTextApp (Portable واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new MainPage(); } اضغط الآن المفتاح F5 لتنفيذ التطبيق، لتحصل على شكل شبيه بما يلي: ملاحظة يمكنك وصل جهازك المحمول الذي يعمل بنظام أندرويد إلى الحاسوب لتجريب تشغيل التطبيق عليه مباشرةً. ولكن في هذه الحالة ينبغي أن تتوفّر واجهة برمجيّة API منصّبة على حاسوبك مناسبة لنسخة أندرويد الموجودة على الجهاز المحمول. على أية حال يمكنك تنصيب هذه الواجهة في حال عدم وجودها من خلال Android SDK Manager كما أشرنا في الدرس السابق. كما أنصح بوصل الجوال قبل تشغيل بيئة التطوير Visual Studio، أو أن تعيد تشغيلها إذا كانت تعمل من قبل. تنسيق الشيفرة البرمجية بشكل أفضل في الحقيقة لا تُعتبر الشيفرة البرمجيّة الموجودة ضمن الملف MainPage.cs مثاليّةً رغم بساطتها. ربما لا تشعر بمشكلة الآن، ولكن عندما تصبح برامجك أكبر، ستقع في مشاكل حقيقيّة لأنّ الأسلوب السابق بكتابة الشيفرة يجعلها كبيرة جدًّا. سأستخدم ميّزة الإسناد المباشر للخصائص أثناء إنشاء الكائنات. تفيد هذه الميزة في الاستغناء عن معظم المتغيّرات في البرنامج، التي ينحصر دورها في لعب دور الوسيط المؤقّت. سنعيد صياغة الشيفرة الموجودة في الملف MainPage.cs بشكل أنيق وعمليّ أكثر: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { this.Content = new Label{ Text = "Welcome to Hsoub Academy!" }; } } } لاحظ أنّني استغنيت عن المتغيّر lblMain لأنّنا أسندنا كائن اللُّصيقة مباشرةً إلى الخاصيّة Content. مزايا إضافية على التطبيق ستلاحظ من التطبيق السابق أنّ اللُّصيقة تظهر في الزاوية اليسرى العليا من النافذة. سنجعلها تظهر في مركز الشاشة. ينبغي ضبط خاصيّتين من خصائص اللُّصيقة لهذا الغرض، وهما HorizontalOptions (لخيارات المحاذاة الأفقيّة) و VerticalOptions (لخيارات المحاذاة الرأسيّة). كل من هاتين الخاصيّتين من النوع LayoutOptions، وهي بنية struct موجودة ضمن نطاق الاسم Xamarin.Forms. تحتوي هذه البنية على عدّة حقول جاهزة تُفيد في خيارات التموضع الأفقيّة والرأسيّة للُّصيقة، وهي خيارات مهمّة للغاية كما سنرى لاحقًا في هذه السلسلة. لنجري الآن التعديل المطلوب على اللُّصيقة الموجودة ضمن بانية الصنف MainPage. ستصبح محتويات الملف MainPage.cs على الشكل التالي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { this.Content = new Label{ Text = "Welcome to Hsoub Academy!", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; } } } لاحظ إسناد القيمة LayoutOptions.Center لكل من الخاصّتين HorizontalOptions و VerticalOptions وذلك للتوسيط الأفقي والرأسي على الترتيب. نفّذ البرنامج مرّة أخرى ستلاحظ أنّ اللُّصيقة أصبحت في مركز الشاشة كما هو واضح من الشكل التالي: أمّا إذا أحببت أن يكون النص ضمن اللُّصيقة بلون آخر، وليكن الأحمر مثلًا، فعليك في هذه الحالة إسناد القيمة Color.Red للخاصيّة TextColor لكائن اللُّصيقة، علمًا أنّ Color هو بنية موجودة ضمن نطاق الاسم Xamarin.Forms أيضًا. انظر كيف نفعل ذلك في الشيفرة: this.Content = new Label{ Text = "Welcome to Hsoub Academy!", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, TextColor = Color.Red }; نفّذ البرنامج مرّة أخرى، لترى النص وقد أصبح لونه أحمر. الخلاصة تعرّفنا في هذا الدرس على البنية العامة لتطبيق Xamarin ضمن بيئة التطوير Visual Studio 2015. كما قمنا ببناء تطبيق بسيط للغاية أسميناه SimpleTextApp. تنحصر وظيفة هذا التطبيق في التّعرف أكثر على Xamarin. سنبدأ اعتبارًا من الدرس القادم ببناء تطبيقات متدرّجة في الصعوبة، وذات مزايا إضافيّة من الممكن أن تستفيد منها كمبرمج تطبيقات محمولة في حياتك العمليّة.
  4. سنتابع العمل في سلسلة برمجة تطبيقات الأجهزة المحمولة باستخدام Xamarin، حيث سنعمل في هذا الدرس على تنزيل وتنصيب برنامج Visual Studio 2015 Community الذي يأتي بشكل مجّاني من مايكروسوفت. حيث أنّ منصّة Xamarin أصبحت تأتي مع Visual Studio كميّزة من المزايا الاختياريّة التي من الممكن اختيارها أثناء تنصيب Visual Studio، وذلك بعد استحواذ مايكروسوفت على شركة Xamarin. تنزيل وتنصيب Visual Studio 2015 Community أنصح أن يكون التنصيب على ويندوز 10 أو ويندوز 8.1. انتقل إلى صفحة تنزيل بيئة التطوير Visual Studio 2015. كما في الشكل التالي: سنختار الإصدار Community من اليسار، لذلك فانقر الزر Download Community Free. سيعمل المتصفّح على تحميل ملف تنفيذي صغير اسمه vs_community.exe وهو برنامج الإعداد الذي سيعمل على تنصيب Visual Studio Community. سيشّغل المتصفّح هذا البرنامج بعد تنزيله فورًا، لذلك سيعطيك ويندوز تحذير أمان أنّه برنامج تنفيذي، ويعرض عليك تشغيله أو إلغاء العمليّة. اقبل تشغيله من خلال نقر الزر Run كما في الشكل التالي: سيعمل برنامج الإعداد ويبدأ بجلب بيانات التنصيب من الإنترنت. قد يستغرق ذلك القليل من الوقت قبل أن تحصل على النافذة في الشكل التالي، التي تخيّرنا بين خيارين للتنصيب: افتراضي Default ومخصّص Custom: انقر الخيار المخصّص Custom ثمّ انقر Next. لينتقل برنامج الإعداد إلى نافذة المزايا المطلوب تنصيبها. انتقل إلى العقدة Cross Platform Mobile Development وانشرها لتصل إلى الميّزة (C#/.NET (Xamarin v4.0.4 وهو الإصدار الحالي لمنصّة Xamarin حين كتابة هذا الدرس. قد يختلف هذا الإصدار بالنسبة إليك. انقر صندوق الاختيار بجوار هذه الميّزة، سيؤدّي ذلك إلى اختيار مزايا أخرى بشكل تلقائي. في الحقيقة سيكون حجم حزمة البيانات التي ستُنزّل من الإنترنت كبيرة نسبيًّا. بالنسبة لهذه السلسلة لن نحتاج إلى جميع هذه المزايا، لذلك انتقل إلى العقدة Programming Languages وانشرها، وأزل الإشارة من صندوق الاختيار الموجود بجانب ++Visual C. انقر الزر Next لنصل إلى المرحلة النهائيّة قبل البدء بعمليّة التنصيب، وهي المرحلة التي تلخّص ما سيقوم به برنامج الإعداد. انقر الزر Install لتبدأ عمليّة التنصيب التي ستأخذ بعض الوقت بحسب سرعة الإنترنت لديك. ستتضمّن عملية التنصيب تحميل حزمة التطوير البرمجيّة SDK الخاصة بأندرويد، بالإضافة إلى تثبيت واجهتين برمجيّتين أو أكثر افتراضيًّا مثل API 19 و API 21. على العموم يمكن تثبيت الواجهات البرمجيّة التي ترغبها بعد انتهاء التنصيب وذلك من خلال مدير الحزم والواجهات في أندرويد Android SDK Manager الذي يأتي مع حزمة التطوير البرمجيّة SDK. اقرأ هذا المقال هنا على أكاديميّة حسّوب للمزيد من المعلومات حول الواجهات البرمجيّة API ودعمها للأجهزة المشغّلة لأندرويد. التشغيل الأول لبيئة التطوير Visual Studio عند تشغيل بيئة التطوير Visual Studio 2015 للمرّة الأولى، سيطلب منك Visual Studio تسجيل الدخول باستخدام حساب بريد إلكتروني من مايكروسوفت (كحساب بريد إلكتروني على Hotmail مثلًا) كما في الشكل التالي: انقر الزر Sign in لتسجيل الدخول، لتحصل على النافذة الخاصّة بإدخال البريد الإلكتروني. أدخل البريد الإلكتروني ثم انقر Continue وإذا طلب منك Visual Studio أن تحدّد نوع البريد الإلكتروني، فاختر شخصيّ Personal Email. بعد ذلك ستصل إلى نافذة تطلب منك كلمة المرور لحساب البريد الإلكتروني الذي أدخلته قبل قليل. أدخل كلمة المرور، ثم انقر Sign in، لتصل إلى النافذة الرئيسيّة لتطبيق Visual Studio كما في الشكل التالي: إنشاء مشروع جديد من النافذة الرئيسيّة لبيئة التطوير Visual Studio، انقر القائمة File من الأعلى، واختر منها New ثم Project لإنشاء مشروع جديد، ستحصل على النافذة التالية: اختر من الشجرة التي تظهر على الجانب الأيسر الخيار: Cross-Platform (قد تحتاج لنشر بعض العقد لتصل إليه). ثم اختر نوع المشروع Blank App Xamarin.Forms) Portable) من القسم الأوسط للنافذة وذلك من أجل اختيار مكتبة الأصناف المحمولة PCL مع هذا التطبيق. ثمّ أدخل الاسم HelloWorld في حقل الاسم Name من الأسفل، ثم انقر OK. سيستغرق الأمر وقتًا قليلًا ليعمل Visual Studio على إنشاء عدّة مشاريع ضمن الحل Solution الحالي. بالنسبة إليّ (أستخدم نظام التشغيل Windows 10) فقد حصلت على خمسة مشاريع ضمن هذا الحل وهي: (HelloWorld (Portable HelloWorld.Droid HelloWorld.iOS (HelloWorld.Windows (Windows 8.1 (HelloWorld.WinPhone (Windows Phone 8.1 تظهر هذه المشاريع ضمن مستكشف الحل Solution Explorer في الجانب الأيمن من النافذة (إذا لم يكن ظاهرًا فيمكنك إظهاره من القائمة View ثم اختيار Solution Explorer). انظر الشكل التالي: في الحقيقة لن نهتم في هذه السلسلة سوى بالتطبيقات التي تعمل على أندرويد، لذلك سنحتفظ بالمشروعين (HellowWorld (Portable و HellowWorld.Droid ونحذف باقي المشاريع. انقر بزر الفأرة الأيمن على المشروع HelloWorld.iOS ثم اختر Remove لإزالته. كرّر نفس العمليّة بالنسبة للمشروعين (HelloWorld.Windows (Windows 8.1 و (HelloWorld.WinPhone (Windows Phone 8.1. ملاحظة: قد تختلف المشاريع التي تظهر عندك بشكل طفيف. على أيّة حال احرص على وجود مشروعين فقط وهما HelloWorld.Droid و (HelloWorld (Portable. تشغيل تطبيق أندرويد الأول لتشغيل تطبيقات أندرويد فإنّنا نحتاج إلى جهاز ذكي يشغّل أندرويد (بصرف النظر عن الإصدار) أو أن يتوفّر لدينا محاكي Emulator يعمل على محاكاة عمل هذا الجهاز ولكن على حاسوبنا الشخصي. توفّر مايكروسوفت محاكٍ Emulator خاص بها: Visual Studio Emulator For Android، وذلك لمحاكاة عمل تطبيقات أندرويد على جهاز الحاسوب بدون الحاجة إلى وجود جهاز فيزيائي متصل بالحاسوب. يُعتبر هذا المحاكي برأيي أفضل من المحاكي الافتراضي الذي يأتي مع حزمة التطوير الخاصّة بأندرويد من حيث الأداء. وعلى أية حال، فستحتاج إلى تفعيل ميزة HAXM التي تأتي مع معالجات Intel، والتي يحتاجها المحاكي الافتراضي لتسريع أدائه. انظر إلى هذا الرابط لتعرف المزيد عن هذا الموضوع. لنشغّل تطبيقنا الأوّل ضمن المحاكي الخاص بمايكروسوفت، سيظهر لك أعلى نافذة بيئة التطوير شريط صغير يحتوي على اسم المحاكي الذي سيتم تشغيله. انظر إلى الشكل التالي: لاحظ بأنّ المحاكي الذي لديّ يدعم الواجهة البرمجيّة API 19 ولا بأس في ذلك. يمكنك دعم أي واجهة برمجيّة ترغبها، باستخدام Android SDK Manager. كلّ ما فعلته أنّني تركت الإعدادات الافتراضيّة كما هي. انقر السهم الأخضر الصغير للتشغيل في وضع التنقيح debugging mode (أو يمكنك اختيار الأمر Start Debugging من القائمة Debug أو اضغط F5). سيستغرق الأمر قليلًا من الوقت حتى تحصل على شكل شبيه بما يلي: لاحظ الرسالة الترحيبيّة !Welcome to Xamarin Forms في وسط الشاشة. مبروك لقد حصلت على برنامجك الأوّل! أوقف الآن تشغيل البرنامج باختيار الأمر Stop Debugging من القائمة Debug (أو اضغط Shift+F5). انتقل إلى مستكشف الحل Solution Explorer وانشر المشروع (HelloWorld (Portable ثمّ انقر على الملف App.cs وهو الملف الأساسيّ في أيّ تطبيق من تطبيقات Xamarin. ستجد ضمنه الشيفرة التالية: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using Xamarin.Forms; 7 8 namespace HelloWorld 9 { 10 public class App : Application 11 { 12 public App() 13 { 14 // The root page of your application 15 MainPage = new ContentPage 16 { 17 Content = new StackLayout 18 { 19 VerticalOptions = LayoutOptions.Center, 20 Children = { 21 new Label { 22 XAlign = TextAlignment.Center, 23 Text = "Welcome to Xamarin Forms!" 24 } 25 } 26 } 27 }; 28 } 29 30 protected override void OnStart() 31 { 32 // Handle when your app starts 33 } 34 35 protected override void OnSleep() 36 { 37 // Handle when your app sleeps 38 } 39 40 protected override void OnResume() 41 { 42 // Handle when your app resumes 43 } 44 } 45 } لاحظ الصنف App في السطر 10. يرث هذا الصنف من الصنف Application الذي يمثّل التطبيق في Xamarin.Forms. أيّ تطبيق ننشئه في Xamarin.Forms يجب أن يرث من هذا الصنف. تقع بانية الصنف App في الأسطر من 12 حتى 28 وفيها يتمّ تعيين الصفحة الرئيسيّة التي سيظهرها التطبيق عند تشغيله. أيّ صفحة من صفحات التطبيق ستكون عبارة عن كائن من صنف يرث من الصنف ContentPage (صفحة محتوى). يمكن أن تحتوي هذه الصفحة على أيّ شيء يخطر ببالك من مربّعات النص والأزرار وأشرطة التمرير وغيرها من الأدوات. لاحظ أنّنا في السطر 15 (ضمن بانية الصنف App) قد أسندنا كائنًا جديدًا من الصنف ContentPage إلى الخاصيّة MainPage وهي خاصيّة تتبع الصنف Application (الذي يرث منه الصنف App). تستخدم الشيفرة الموجود هنا أسلوب الإنشاء المختصر للكائنات، فكلّ شيء يتمّ هنا من خلال عبارة برمجيّة واحدة. حيث نسند الخصائص للكائنات الجديدة المُنشأة مباشرةً عند إنشاء هذه الكائنات. فمن خلال الشيفرة الموجودة في الأسطر بين 15 و 27 كرّرنا هذا الأسلوب ثلاث مرّات، وذلك من أجل كائنات جديدة من الأصناف ContentPage و StackLayout و Children. ملاحظة يُعتبر الإسناد المختصر للخصائص عند إنشاء كائنات جديدة، من التقنيّات المهمّة التي تبسّط الشيفرة البرمجيّة إلى حدّ كبير. وكيف تنعش ذاكرتك، إليك المثال البسيط التالي. بفرض أنّه لدينا الصنف Student الذي يحتوي على الخصائص التالية: FirstName و LastName و Age. عند إنشاء كائن جديد من الصنف Student يمكننا استخدام العبارة البرمجيّة التالية: Student student = new Student { FirstName = "Ahmad", LastName = "Shareef", Age = 16 }; ففي هذه الحالة ننشئ كائن جديد من الصنف Student وبنفس الوقت نُسند القيم المناسبة لخصائصه. سنؤجّل الحديث عن التوابع OnStart و OnSleep و OnResume لنتحدّث عنها لاحقًا في هذه السلسلة، رغم أنّ أسمائها توحي بوظائفها التي تُعتبر مفيدة ومهمّة في عمل التطبيق. الخلاصة تعلّمنا في هذا الدرس كيفيّة تنزيل وتنصيب Visual Studio 2015 Community مع إضافة قابليّة تطوير تطبيقات لأندرويد باستخدام Xamarin. لاحظ أنّني قد تركت الأمور تسير بشكلها الافتراضيّ قدر المستطاع، لأنّه كما هو واضح هناك العديد من الإجراءات كي تصبح بيئة التطوير جاهزة للعمل، وللبدء بتطوير تطبيقات تعمل على أندرويد وغيره من أنظمة التشغيل باستخدام سي شارب #C و Xamarin.
  5. تعاملنا في الدروس السابقة مع عنصر واحد فقط يظهر على الشاشة. كان هذا العنصر عبارة عن لصيقة Label نُسندها إلى الخاصيّة Content لصفحة محتوى content page. في البرامج الحقيقية كما هو معروف، سنحتاج بالتأكيد إلى العديد من العناصر التي ستظهر على الشاشة لتلبية متطلّبات البرنامج. المشكلة التي تصادفنا هنا أنّ الخاصية Content لصفحة المحتوى لا تقبل سوى عنصر واحد يرث من الصنف View. أوجدت Xamarin حلًا بسيطًا لهذه المشكلة يتمثّل في استخدام المخطّطات layouts. يمكن لأيّ مخطّط أن يستوعب أي عدد من العناصر التي يرث كل منها من الصنف View. في الحقيقة يُعتبر المخطّط بحدّ ذاته يرث من الصنف Layout<View> وهذا الصنف بدوره يرث بشكل غير مباشر من الصنف View. لذلك يمكن إسناد أيّ مخطط للخاصية Content مباشرةً. تدعم Xamarin أربعة أنواع من المخطّطات وهي: المخطّط المطلق AbsoluteLayout مخطّط الشبكة GridLayout المخطّط النسبي RelativeLayout مخطّط المكدّس StackLayout. سنتناول ثلاثة مخطّطات في هذه السلسلة وهي: المطلق والشبكي والمكدّس. وسنبدأ في هذا المقال بمخطّط المكدّس StackLayout. مخطّط المكدّس StackLayout يمكن إضافة أي عدد من العناصر إلى هذا المخطّط. وسبب تسميته بهذا الاسم هو أنّه يرتّب العناصر المضافة إليه بشكل متكدّس stacked. يمتلك الصنف StackLayout خاصيتين إضافيتين عن باقي المخطّطات هما: Orientation وتُعبّر عن الاتجاه (أفقي أو رأسي) وSpacing وتمثّل التباعد بين العناصر المُضافة إلى المخطّط ولها القيمة الافتراضيّة 6.0. لنتناول الآن مثال بسيط يوضّح آلية التعامل مع هذا المخطّط المفيد. تطبيق ColorsApp لعرض بعض الألوان أنشئ تطبيقًا جديدًا كما تعلّمنا من الدروس السابقة بحيث يكون من النوع Blank App (Xamarin.Forms Portable) وسمّه ColorsApp. بعد إنشاء التطبيق في Visual Studio أبق فقط على المشروعين ColorsApp (Portable) و ColorsApp.Droid. أضف إلى المشروع ColorsApp (Portable) صفحة محتوى سمّها ColorsListPage (انقر بزر الفأرة الأيمن على المشروع واختر Add ثم اختر New Item. وبعد ظهور النافذة، اختر من الجهة اليسرى Cross-Platform، ومن وسط الشاشة اختر Forms ContentPage). بعد إنشاء هذه الصفحة سنلاحظ أنّها تحتوي بالفعل على مخطّط مكدّس جاهز. انظر إلى محتويات هذه الصفحة: using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using System.Text; using Xamarin.Forms; namespace ColorsApp { public class ColorsListPage : ContentPage { public ColorsListPage() { Content = new StackLayout { Children = { new Label { Text = "Hello ContentPage" } }, }; } } } لاحظ كيف أنّنا نُسند كائنًا جديدًا من الصنف StackLayout إلى الخاصيّة Content ضمن البانية ColorsListPage. لاحظ أيضّا كيف أنّ المخطّط StackLayout يحتوي على خاصيّة اسمها Children تُعبّر عن العناصر الأبناء (كلّ منها يرث من الصنف View) التي نرغب بإضافتها إلى المكدّس. استبدل محتويات الملف ColorsListPage.cs بالشيفرة التالية: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection.Emit; 5 using System.Text; 6 7 using Xamarin.Forms; 8 9 namespace ColorsApp 10 { 11 public class ColorInfo 12 { 13 public Color Color { get; set; } 14 public string Name { get; set; } 15 } 16 17 public class ColorsListPage : ContentPage 18 { 19 public ColorsListPage() 20 { 21 ColorInfo[] colors = new ColorInfo[] 22 { 23 new ColorInfo {Color= Color.Aqua,Name = "Aqua" }, 24 new ColorInfo {Color=Color.Blue,Name ="Blue" }, 25 new ColorInfo {Color=Color.Gray,Name ="Gray" }, 26 new ColorInfo {Color=Color.Black,Name ="Black" }, 27 new ColorInfo {Color=Color.Silver,Name ="Silver" }, 28 new ColorInfo {Color=Color.Red,Name ="Red" }, 29 new ColorInfo {Color=Color.Maroon,Name ="Maroon" }, 30 new ColorInfo {Color=Color.Yellow,Name ="Yellow" }, 31 new ColorInfo {Color=Color.Olive,Name ="Olive" }, 32 new ColorInfo {Color=Color.Lime,Name ="Lime" }, 33 new ColorInfo {Color=Color.Green,Name ="Green" }, 34 new ColorInfo {Color=Color.Navy,Name ="Navy" }, 35 new ColorInfo {Color=Color.Teal,Name ="Teal" }, 36 new ColorInfo {Color=Color.Pink,Name ="Pink" }, 37 new ColorInfo {Color=Color.Fuchsia,Name ="Fuchsia" }, 38 new ColorInfo {Color=Color.Purple,Name ="Purple" } 39 }; 40 41 StackLayout stackLayout = new StackLayout(); 42 43 for (int i = 0; i < colors.Length; i++) 44 { 45 stackLayout.Children.Add(new Label 46 { 47 Text = colors[i].Name, 48 TextColor = colors[i].Color, 49 FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) 50 }); 51 } 52 53 Padding = new Thickness(5, 5, 5, 5); 54 55 Content = stackLayout; 56 } 57 } 58 } لقد أضفنا صنفًا بسيطًا جديدًا اسمه ColorInfo إلى هذا الملف (الأسطر من 11 حتى 15). ورغم أنّ وجود صنفين في نفس الملف هو عادة برمجيّة سيئة، إلّا أنّني آثرت ذلك طلبًا للتبسيط. تنحصر وظيفة هذا الصنف في الاحتفاظ بمعلومات بسيطة عن أيّ: قيمة اللون Color واسمه Name. أنشأنا في السطر 21 مصفوفة من الصنف ColorInfo وأسندناها إلى المتغيّر colors. ستحتوي هذه المصفوفة كما هو واضح على 16 لون. ننشئ بعد ذلك كائن جديد من الصنف StackLayout ونسنده إلى المتغيّر stackLayout (السطر 41)، ثم ندخل حلقة for (السطر 43) وظيفتها المرور على عناصر المصفوفة colors، وبحيث تُنشئ في كل دورة لصيقة Label جديدة وتُعيّن لها النص ولونه وحجمه، وتضيف هذه اللصيقة مباشرةً إلى مخطّط المكدّس stackLayout عن طريق التابع Add للخاصيّة Children منه. بعد ذلك نُحدّد مقدار الحشوة padding للصفحة (السطر 53) وفي النهاية نُسند المتغيّر stackLayout إلى الخاصية Content للصفحة (السطر 55). لتجربة هذا التطبيق، انتقل أولًا إلى الملف App.cs واحرص أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new ColorsListPage(); } نفّذ البرنامج باستخدام F5 لتحصل على شكل شبيه بما يلي: نلاحظ هنا أمرين مهمّين. الأوّل أنّ بعض الألوان لا تظهر بشكل جيّد على الخلفية السوداء (وهي الخلفية الافتراضية لتطبيقات Xamarin في أندرويد) لأنّ التباين اللوني ليس جيّدًا، بل إنّ الكلمة Black لن تظهر لأنّ لونها يماثل لون الخلفية الأسود. أمّا الأمر الثاني، فلدينا بالأساس 16 لون إلّا أنّه ظهر 12 لون منها فقط. من الممكن أن يختلف عدد الألوان الظاهرة عندك بحسب الشاشة التي تستخدمها، فقد تظهر جميعها مثلًا، ولكن على كلّ الأحوال ستواجه بالتأكيد تطبيقات في المستقبل لن تظهر فيها جميع العناصر دفعةً واحدة على الشاشة. في الواقع نحتاج إلى آلية لتمرير المحتويات scrolling مثل أيّ تطبيق أندرويد آخر. سنعالج الآن كلًّا من الأمرين السابقين. تطبيق ColorsApp المحسّن سنعالج في البداية مسألة التباين اللوني التي من الممكن حلّها بإضافة تابع جديد إلى الصنف ColorsListPage واسمه GetSuitableBackground. تنحصر وظيفة هذا التابع بحساب مقدار الإنارة luminance وفق ثوابت عدديّة متعارف عليها على أنّها مثالية. فإذا كانت الإنارة للّون المراد إظهاره أكبر من 0.5 فستكون الخلفية سوداء، أمّا إذا كانت أقل من أو تساوي 0.5 فستكون الخلفية بيضاء. مما يمنح تباينًا مناسبًا لعرض الألوان على الشاشة. انظر الشيفرة البرمجيّة الخاصّة بهذا التابع: private Color GetSuitableBackground(Color color) { double luminance = 0.30 * color.R + 0.59 * color.G + 0.11 * color.B; return luminance > 0.5 ? Color.Black : Color.White; } تُعبّر الخصائص color.R و color.G و color.B عن المكوّنات الأحمر والأخضر والأزرق على الترتيب للّون الممرّر لهذا التابع والمراد إيجاد لون الخلفية المناسب له. أمّا الثوابت 0.30 و 0.59 و 0.11 فهي ثوابت تُعتبر مثالية لإيجاد إنارة اللون ويمكنك تغييرها إذا أحببت. أمّا بالنسبة لمسألة تمرير محتويات الشاشة فحلّها بسيط، ويتمثّل في استخدام الصنف ScrollView حيث نُنشئ كائن جديد منه، ونُسند المتغيّر stackLayout إلى الخاصيّة Content من ذلك الكائن، ثم نُسند ذلك الكائن الجديد إلى الخاصيّة Content لصفحة المحتوى ColorsListPage بدلًا من إسناد stackLayout مباشرةً إليها كما كنّا نفعل في البرنامج السابق. انظر إلى الشيفرة التالية: Content = new ScrollView { Content = stackLayout }; انظر الآن إلى الشيفرة الكاملة بعد إجراء التعديلات السابقة عليها: using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using System.Text; using Xamarin.Forms; namespace ColorsApp { public class ColorInfo { public Color Color { get; set; } public string Name { get; set; } } public class ColorsListPage : ContentPage { public ColorsListPage() { ColorInfo[] colors = new ColorInfo[] { new ColorInfo {Color= Color.Aqua,Name = "Aqua" }, new ColorInfo {Color=Color.Blue,Name ="Blue" }, new ColorInfo {Color=Color.Gray,Name ="Gray" }, new ColorInfo {Color=Color.Black,Name ="Black" }, new ColorInfo {Color=Color.Silver,Name ="Silver" }, new ColorInfo {Color=Color.Red,Name ="Red" }, new ColorInfo {Color=Color.Maroon,Name ="Maroon" }, new ColorInfo {Color=Color.Yellow,Name ="Yellow" }, new ColorInfo {Color=Color.Olive,Name ="Olive" }, new ColorInfo {Color=Color.Lime,Name ="Lime" }, new ColorInfo {Color=Color.Green,Name ="Green" }, new ColorInfo {Color=Color.Navy,Name ="Navy" }, new ColorInfo {Color=Color.Teal,Name ="Teal" }, new ColorInfo {Color=Color.Pink,Name ="Pink" }, new ColorInfo {Color=Color.Fuchsia,Name ="Fuchsia" }, new ColorInfo {Color=Color.Purple,Name ="Purple" } }; StackLayout stackLayout = new StackLayout(); for (int i = 0; i < colors.Length; i++) { stackLayout.Children.Add(new Label { Text = colors[i].Name, TextColor = colors[i].Color, BackgroundColor = GetSuitableBackground(colors[i].Color), FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) }); } Padding = new Thickness(5, 5, 5, 5); Content = new ScrollView { Content = stackLayout }; } private Color GetSuitableBackground(Color color) { double luminance = 0.30 * color.R + 0.59 * color.G + 0.11 * color.B; return luminance > 0.5 ? Color.Black : Color.White; } } } تأمّل الشيفرة السابقة، وتأكّد من فهمها بشكل جيّد. ثم نفّذ البرنامج باستخدام F5 لتحصل على شكل شبيه بما يلي، علمًا أنّني قد استخدمت ميزة التمرير الجديدة لإظهار بقية العناصر التي لم تكن تظهر معنا من قبل: ستلاحظ أنّ كلّ لون يظهر في هذه القائمة، له لون خلفيّة مناسب له لإظهاره بالشكل الأمثل. ملاحظة يمكنك استخدام الخاصيّة Spacing لمخطّط المكدّس لزيادة أو إنقاص مقدار التباعد بين اللصائق labels التي تظهر على الشاشة. للخاصيّة Spacing القيمة الافتراضيّة 6.0 كما أسلفنا، جرّب أن تعيّن القيمة 0 لها مثلًا وانظر على ماذا ستحصل. يمكنك تعيين هذه الخاصيّة بالنسبة للبرنامج السابق بأن تضيف السطر التالي: stackLayout.Spacing = 0; بعد السطر التالي مباشرةً: StackLayout stackLayout = new StackLayout(); الخلاصة تعرّفنا في هذا الدرس على مبادئ التعامل مع مخطّط المكدّس StackLayout الذي يُستخدَم في تطبيقات Xamarin على نحو واسع لترتيب العناصر المرئية على الشاشة بشكل متكدّس. تعرّفنا أيضًا على كيفيّة إكساب مخطّط المكدّس ميزة التمرير لكي نستطيع عرض العناصر التي لا تظهر على الشاشة. سنتابع عملنا مع مخطّط المكدّس في الدرس التالي، حيث سنتحدّث عن المزيد من المزايا المهمّة التي يتمتّع بها هذا المخطّط.
  6. تُعتبر منصّة Xamarin في الوقت الحالي، من أهمّ منصّات تطوير تطبيقات الأجهزة المحمولة المتوفّرة، والتي يبدو أنّها ستبقى على الواجهة لوقت ليس بالقليل، خصوصًا بعد استحواذ شركة مايكروسوفت على الشركة المنتجة لها والتي تحمل أيضًا نفس الاسم (Xamarin). قد تكون متحفّزًا للدخول في عالم تطوير تطبيقات الأجهزة المحمولة (كما كنت عندما تعرّفت للمرّة الأولى على Xamarin) ومستعدًّا لكتابة الشيفرة مباشرةً، ولكن لنصبر قليلًا، ولنفهم بدايات الأمور، ومبدأ عمل Xamarin بشكل أفضل ضمن هذا المقال، الذي يُعدّ الأوّل في سلسلة مقالات سترشدك إلى كيفيّة تطوير تطبيقات باستخدام منصّة Xamarin مع إنشاء تطبيقات عمليّة من خلالها. مقدمة تمّ تأسيس شركة Xamarin (وتُقرأ زامارين) في عام 2011، من قِبَل نفس المهندسين الذين صمّموا مشروع Mono. ومشروع Mono وإخوانه مثل Mono for android و Mono Touch، هي عبارة عن منصّات لتشغيل تطبيقات مكتوبة بلغة سي شارب C# على أنظمة التشغيل: Linux و Android و iOS على الترتيب. يمكن باستخدام Xamarin إنشاء تطبيقات أصليّة Native Apps لأجهزة Android و iOS و Mac وويندوز بلغة برمجة ليست معتمدة رسميًا بالنسبة إليها. سنركّز في هذه السلسلة على بناء تطبيقات تعمل على نظام التشغيل Android. لمن هذه السلسلة؟ إذا كان لديك إلمام جيّد بلغة سي شارب ومكتبة الأصناف الأساسيّة BCL ضمن إطار العمل دوت نت بالإضافة إلى معرفة أوليّة بطريقة استخدام بيئة التطوير Visual Studio 2015، وتمتلك الشغف والصبر لتعلّم كيفيّة برمجة تطبيقات للأجهزة المحمولة باستخدام Xamarin فإنّ هذه السلسلة هي بالتأكيد لك. لدينا هنا في أكاديميّة حسوب سلسلة تعليميّة خاصّة بلغة سي شارب يمكن الاستفادة منها. الحاجة إلى Xamarin برزت الحاجة إلى Xamarin بسبب طبيعة تطبيقات الأجهزة المحمولة وعملها على أنظمة تشغيل مختلفة تعود إلى شركات متنافسة. توجد في الوقت الحالي ثلاثة أنظمة تشغيل مسيطرة على السوق بصورة متفاوتة وهي: iOS لشركة Apple وAndroid لشركة Google وWindows Phone لشركة Microsoft. تختلف هذه الأنظمة في العديد من النواحي، التي سنناقشها فيما يلي. تجربة المستخدم بالنسبة إلى تجربة المستخدم يوجد تشابه في هذه الأنظمة من ناحية تقديم الواجهات الرسوميّة للمستخدم والتفاعل مع الجهاز من خلال اللمس أو اللمس المتعدّد، ولكنّ هناك اختلافات في التفاصيل. فلكلّ نظام تشغيل وسائل مختلفة في التنقّل بين صفحات التطبيق، وفي تقديم البيانات، وفي العمل مع القوائم، وغيرها من التفاصيل الأخرى التي تتطلّب أن يسلك المطوّر developer منحىً مختلفًا من أجل كلّ نظام تشغيل. بيئات تطوير ولغات برمجة مختلفة أمّا بالنسبة للغات البرمجة وبيئات التطوير، فهذا أمر آخر. فلكلّ نظام تشغيل متطلّباته الخاصّة التي ألخّصها بشكل سريع فيما يلي: لإنشاء تطبيقات على أنظمة iOS فأنت تحتاج إلى إتقان لغة البرمجة Objective-C أو لغة البرمجة Swift. وأن تمتلك حاسوب MacBook (أي إصدار) مع بيئة التطوير Xcode. لإنشاء تطبيقات على أنظمة Android فستحتاج إلى لغة جافا Java مع بيئة التطوير Android Studio التي تعمل على العديد من أنظمة التشغيل. أمّا لإنشاء تطبيقات تعمل على Windows Phone أو Windows 10 Mobile فأنت بحاجة إلى لغة البرمجة سي شارب C# مع حاسوب يشغّل ويندوز، وإلى بيئة التطوير Visual Studio. واجهات برمجية مختلفة تعتمد جميع أنظمة التشغيل السابقة على واجهات تطبيق برمجيّة API مختلفة. مع أنّه يوجد بعض الشبه بالنسبة للكائنات المتعلّقة بواجهة المستخدم user-interface. فعلى سبيل المثال، جميع الأنظمة السابقة توفّر وسيلة للمستخدم لاختيار حالة منطقيّة Boolean والتي يمكن تمثيلها بـ True أو False ففي iOS يصنّف هذا الكائن على أنّه view اسمه UISwitch، أمّا في أندرويد فهو widget اسمها Switch، وفي ويندوز فهو control ويسمّى ToggleSwitch. الحل الذي توفره Xamarin يمكن تجاوز جميع النقاط السابقة من خلال Xamarin لأنّها توفّر لغة برمجة وحيدة وهي سي شارب يمكن استخدامها لكتابة تطبيقات على أيّ نظام تشغيل. كما أنّها توفّر بيئة تطوير متقدّمة ووحيدة وهي Visual Studio 2015 لكتابة هذه التطبيقات (يمكن استخدام بيئة التطوير Xamarin Studio أيضًا بالنسبة لنظام Mac). بالإضافة إلى أنّها وحّدت الواجهات البرمجيّة المختلفة API ضمن واجهة برمجيّة وحيدة يتعامل معها المطوّر. لغة سي شارب غنيّة عن التعريف. فهي لغة قويّة ومرنة وغنيّة جدًا ودائمة التطوير. لقد أصبحت بحق من أكثر لغات البرمجة تطوّرًا وحداثةً. ولسنا هنا بصدد تفضيل لغة برمجة على أخرى، ولكن بحسب خبرتي الشخصيّة، واطّلاعي على العديد من لغات البرمجة الأخرى، تستطيع القول بأنّ سي شارب تحتلّ موقعًا مرموقًا بينها. يستطيع المطوّرون من أجل تطبيق محدّد، كتابة شيفرة واحدة مشتركة لجميع أنظمة التشغيل السابقة بدون أيّة تعديلات تُذكر عليها فيما يتعلّق بمنطق العمل business logic داخل التطبيق وبما يتضمنّه من عمليّات برمجيّة لا تتعلّق بنوع الجهاز المحمول أو نظام التشغيل الذي يعمل عليه. نسمّي هذه الشيفرة بالشيفرة المستقلة عن نظام التشغيل platform independent. أمّا إذا تطلّب الأمر من التطبيق أن يتعامل مع العتاد الصلب للجهاز الذي يعمل عليه (مثل الكاميرا أو حسّاس GPS مثلًا)، فيمكن عندها كتابة أجزاء من الشيفرة التي تراعي خصوصيّة كل نظام تشغيل، نسمّي مثل هذه الشيفرة بالشيفرة المرتبطة بنظام التشغيل platform dependent. المكونات الرئيسية لمنصة Xamarin ركّزت شركة Xamarin منذ نشأتها على التكنولوجيا الخاصّة بالمترجمات Compilers. وقد أصدرت الشركة ثلاث مجموعات أساسيّة من مكتبات دوت نت .NET وهي: Xamarin.Mac و Xamarin.iOS و Xamarin.Andorid التي تشكّل بمجموعها منصّة Xamarin. تسمح هذه المكتبات للمطوّرين بكتابة تطبيقات أصليّة native apps لكلّ من أنظمة التشغيل الموافقة. ذكرنا قبل قليل أنّ هناك جزء من شيفرة التطبيق البرمجيّة يتكرّر عادةً من أجل كل نظام تشغيل، يمكن عزل هذا الجزء ووضعه ضمن مشروع منفصل في برنامج Visual Studio. لهذا المشروع نوعين: مشروع الأصول المشتركة Shared Asset Project أو اختصارًا SAP. وهو عبارة عن مجموعة من ملفات الشيفرة بالإضافة إلى ملفّات الأصول assets مثل الصور وغيرها الموجودة ضمن المشروع والتي يمكن مشاركتها مع باقي المشاريع الأخرى ضمن نفس الحل Solution في Visual Studio. مكتبة الأصناف المحمولة Portable Class Library أو اختصارًا PCL. وهي تضمّ الشيفرة التي نرغب بمشاركتها وذلك ضمن مكتبة ربط ديناميكي dynamic link library أو اختصارًا DLL. سنركّز في هذه السلسلة على هذا النوع. أمّا بالنسبة للشيفرة التي تتعلّق بنظام التشغيل، فتوضع ضمن مشروع منفصل ضمن Visual Studio لكلّ نظام تشغيل نرغب بأن ندعمه. ففي الحالة العامّة، يمكن أن يكون لدينا ثلاثة مشاريع منفصلة لكل من Android و iOS و Windows Phone. تستفيد جميعها من الشيفرة المشتركة والمستقلّة عن نظام التشغيل الموجودة في PCL أو SAP. وبالمجمل تكون جميع تلك المشاريع ضمن نفس الحل Solution ضمن Visual Studio. انظر إلى الشكل التالي الذي يوضّح كيفيّة تفاعل التطبيق المكتوب لأنظمة التشغيل المختلفة مع مكوّنات Xamarin: يمثّل الشكل السابق تطبيقًا واحدًا. نلاحظ في السطر الثاني الأشكال المختلفة لهذا التطبيق على أنظمة التشغيل المختلفة. انظر كيف تتفاعل هذه الأشكال المختلفة مع مشروع PCL أو SAP للاستفادة من الشيفرة المشتركة التي لا تتعلّق بنظام تشغيل محدّد. انظر إلى تطبيق iOS مثلًا كيف يتفاعل أيضًا مع المكتبة Xamarin.iOS التي توفّر وسيلة للربط bindings بينه وبين واجهة التطبيقات البرمجيّة API لنظام التشغيل iOS. ينطبق نفس الأمر تماماً بالنسبة لتطبيق أندرويد. الاستثناء الوحيد هو بالنسبة لتطبيق ويندوز الذي لا يحتاج إلى وسيط (وسيلة للربط) في هذه الحالة، حيث يمكنه الاتصال مباشرةً مع واجهة API لنظام التشغيل ويندوز (بصورة أدق Windows Phone). نماذج Xamarin ابتكرت شركة Xamarin في عام 2014 ما يُعرف بنماذج Xamarin أو Xamarin Forms. تسمح هذه المنصّة للمطوّرين بأن يكتبوا شيفرة برمجيّة لواجهة المستخدم user interface بحيث يمكن تحويل هذه الشيفرة مباشرةً إلى تطبيقات تعمل على أجهزة أندرويد و iOS وويندوز. في الحقيقة أصبحت Xamarin Forms تدعم إنشاء تطبيقات عامّة Universal Windows Platform على الأجهزة التي تشغّل نسخ ويندوز المختلفة مثل Windows Phone و Windows 10 و Windows 10 Mobile و Windows 8.1 و Windows 8.1 Phone. بالنسبة لبنية الحل Solution في Visual Studio فلن يتغيّر كثيرًا، باستثناء أنّ المشاريع المنفصلة الخاصّة بأنظمة التشغيل السابقة ستكون صغيرة على نحو ملحوظ بسبب وجود كميّة قليلة من الشيفرة البرمجيّة ضمنها. سيتضمّن مشروع PCL أو SAP في هذه الحالة الشيفرة المشتركة والمستقلّة عن أنظمة التشغيل كما اتفقنا على ذلك من قبل، بالإضافة إلى الشيفرة البرمجيّة المسؤولة عن الإظهار والتعامل مع واجهة المستخدم. أي أنّ منصّة Xamarin Forms تسمح لنا بكتابة شيفرة برمجيّة واحدة تعمل مباشرةً على أنظمة التشغيل المختلفة. انظر الشكل التالي لفهم آليّة عمل التطبيقات التي تعتمد Xamarin Forms. تعتمد التطبيقات المكتوبة لأنظمة التشغيل المختلفة في هذه الحالة على مشروع PCL أو SAP بشكل كليّ في التواصل مع الواجهات البرمجيّة API. وهكذا من الممكن في الكثير من التطبيقات كتابة شيفرة واحدة فقط تعمل على جميع الأجهزة! باستثناء الحالات التي يكون من الضروري فيها كتابة شيفرة مخصّصة لنظام تشغيل محدّد. في المستقبل قد يتغيّر هذا الأمر، فقد يكون من الممكن كتابة شيفرة واحدة فقط تعمل على جميع الأجهزة مهما كان نوع هذه الشيفرة. سنتحدّث في هذه السلسلة عن Xamarin Forms بشكل أساسيّ. كيفية عمل Xamarin بالنسبة لتطبيقات iOS فيعمل مترجم سي شارب الخاص بـ Xamarin على ترجمة الشيفرة البرمجيّة إلى لغة مايكروسوفت الوسيطيّة MSIL، ثمّ يُستخدم مترجم Apple على نظام تشغيل Mac لتوليد رُماز أصليّ native code يعمل على iOS كما لو أنّه تطبيق مكتوب بلغة Objective-C تمامًا. أمّا بالنسبة لتطبيقات Android، فسيولّد المترجم أيضًا لغة MSIL التي ستعمل في هذه الحالة على بيئة تنفيذ مشتركة CLR مخصّصة للعمل على أندرويد. وستكون التطبيقات الناتجة في هذه الحالة تشبه أيضًا إلى حدّ كبير تلك المنشأة باستخدام لغة جافا وبيئة التطوير Android Studio الخاصّة بأندرويد. وأخيرًا بالنسبة للتطبيقات التي تعمل على Windows Phone و Windows 10 Mobile، فالتطبيقات مدعومة بشكل واضح، وستعمل كالتطبيقات الأصليّة المنشأة باستخدام Visual Studio بدون استخدام Xamarin. الخلاصة منصّة Xamarin واعدة، ولها تاريخ عريق وتجارب غنيّة من قبل أن تظهر شركة Xamarin إلى الوجود. ولعلّ مايكروسوفت قد أدركت الأهميّة الكبيرة لها، فتمّت عمليّة الاستحواذ التي كانت متوقعّة. أنصحك بأن تبادر إلى تعلّم Xamarin وخصوصًا في حال كنت مبرمج سي شارب، أو لديك معلومات أوليّة عنها. ولعلّ الأيّام القادمة قد تحمل المزيد من الدعم والمفاجآت لمنصّة Xamarin التي كان أوّلها هو جعلها مجّانيّة للاستخدام الشخصيّ أو للفرق البرمجيّة الصغيرة. سنبدأ اعتبارًا من الدرس القادم في هذه السلسلة التعليميّة، تنصيب برنامج Visual Studio 2015 وبدء العمل مع Xamarin.