استخدام موارد SVG في Xamarin

عند تطوير تطبيق جوال ، هناك الكثير من النقاط التي يجب الانتباه إليها. هذا هو اختيار التقنية التي ستكتب عليها ، وتطوير بنية التطبيق ، وفي الواقع ، كتابة الكود. عاجلاً أم آجلاً ، تأتي لحظة عندما يكون العمود الفقري للتطبيق موجودًا ، ويتم كتابة كل المنطق والتطبيق ، بشكل عام ، يعمل ، ولكن ... لا يوجد مظهر. هنا يجدر التفكير في الموارد الرسومية التي سيتم استخدامها ، لأن الرسومات تشكل نصيب الأسد من حجم التجميع النهائي ، سواء كان ذلك على Android أو .ipa على iOS. يُتوقع من حيث المبدأ تجميعات ضخمة للألعاب المحمولة ، حتى الآن من PlayMarket ، يتعين عليك أحيانًا تنزيل أحجام بيانات تصل إلى 2 جيجابايت ، ومن الجيد إذا كان بإمكانك الاتصال بشبكة Wi-Fi أثناء التنزيل أو يوفر مشغل الهاتف المحمول اتصالاً غير محدود عالي السرعة.لكن هذا متوقع بالنسبة للألعاب ، ويثير تطبيق تجاري بهذا الحجم السؤال "من أين يأتي هذا؟" يمكن أن يكون أحد أسباب الحجم الكبير لتجميع تطبيق الأعمال هو وجود عدد كبير من الرموز والصور التي يجب عرضها فيه. وأيضًا لا تنس أن كمية كبيرة من الرسومات تؤثر بشكل متناسب على أداء التطبيق.



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



سنخبرك بما يمكنك فعله لتجنب الوقوع في مثل هذا الموقف في هذه المقالة.



مقارنة بين تنسيقات PNG و SVG



يتمثل الاختلاف الرئيسي بين تنسيقات PNG و SVG في أن PNG تنسيق نقطي و SVG تنسيق متجه.



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



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


ومع ذلك ، هناك أيضًا جوانب سلبية.



على سبيل المثال ، لا يمكن تحجيم الصورة النقطية بشكل مثالي. عندما تقوم بتكبير صورة صغيرة ، فإن الصورة "تتراكم" ويمكنك رؤية وحدات البكسل التي تتكون منها.







كما أن الصور البسيطة التي تتكون من عدد كبير من النقاط كبيرة. لذلك ، يوصى بتخزين الرسومات البسيطة بتنسيق متجه. كل ما سبق صحيح لكل من تنسيق PNG وأي تنسيق رسومات نقطية آخر.

تنسيق SVG ، بدوره ، ليس في الحقيقة صورة. وفقًا لمقال ويكيبيديا ، تعد SVG لغة ترميز رسومات متجهة قابلة للتطوير تتيح لك قراءة ملف وتحريره حسب الحاجة.



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



بالإضافة إلى ما سبق ، يحتوي تنسيق SVG على عدد من المزايا الأخرى:



  1. كتنسيق متجه ، يسمح لك SVG بقياس أي جزء من الصورة دون فقدان الجودة ؛
  2. يمكن إدراج الرسومات النقطية في مستند SVG ؛
  3. يتكامل بسهولة مع مستندات HTML و XHTML.


ومع ذلك ، هناك أيضًا عيوب في هذا التنسيق:



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


هناك عيب آخر في حالة تطوير تطبيقات الهاتف على منصة Xamarin.



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



العمل بتنسيق SVG بتنسيق Xamarin.Android



كما ذكرنا أعلاه ، لا يدعم Xamarin SVG خارج الصندوق. لحل هذه المشكلة - يمكنك استخدام مكتبات الطرف الثالث أو VectorDrawable. في الآونة الأخيرة ، يفضل المطورون بشكل متزايد الخيار الأخير ، نظرًا لأن معظم المكتبات الخاصة بـ Xamarin تركز على الاستخدام عبر الأنظمة الأساسية في Xamarin. لم تعد النماذج والحلول لنظام Android الأصلي مدعومة من قِبل مطوريها وقد أصبحت قديمة ، أو توجد مشكلات خطيرة عند محاولة البناء على أساسها مكتبة Xamarin. في هذا الصدد ، سننظر هنا في استخدام VectorDrawable.



لتنفيذ هذا النهج ، ستحتاج إلى استخدام Vector Asset Studio. العثور عليه سهل بما فيه الكفاية ، تحتاج فقط إلى Android Studio. لذلك ، لنبدأ:



  1. Android Studio File -> New -> New Project;

    , — Vector Asset Studio, .
  2. drawable -> New -> Vector Asset;



    Asset Studio. Material Design, SVG PSD, xml-. .
  3. Asset Studio



    ,  , .
  4. Next 



    Xamarin.Android.



يكفي العمل التحضيري الذي يتطلب تثبيت Android Studio. لسوء الحظ ، في وقت كتابة هذا التقرير ، لم نتمكن من العثور على محولات تعمل بشكل صحيح عبر الإنترنت. أخطأ البعض عند محاولة تحويل ملف SVG المقدم ، وأشار البعض إلى أنه من الأفضل استخدام Vector Asset Studio.



مهما كان الأمر ، فقد تلقينا الملف المطلوب والآن يمكننا استخدامه في مشروعنا. لن نصف عملية إنشاء Xamarin.Android مشروع ، دعنا ننتقل مباشرة إلى هذه النقطة.

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



كود هنا
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	xmlns:android        ="http://schemas.android.com/apk/res/android"
	xmlns:app            ="http://schemas.android.com/apk/res-auto"
	android:layout_width ="match_parent"
	android:layout_height="match_parent"
	android:minWidth="25px"
	android:minHeight="25px">
	<ImageView
		android:layout_width="150dp"
		android:layout_height="150dp"
		android:layout_alignParentLeft="true"
		android:id="@+id/imageView1"
		android:adjustViewBounds="true"
		app:srcCompat="@drawable/question_svg"
		android:background="@android:color/holo_red_dark"/>
	<ImageView
		android:layout_width="150dp"
		android:layout_height="150dp"
		android:layout_alignParentRight="true"
		android:id="@+id/imageView2"
		android:adjustViewBounds="true"
		app:src="@drawable/question"
		android:background="@android:color/holo_red_dark"/>
	<ImageView
		android:layout_width="150dp"
		android:layout_height="150dp"
		android:id="@+id/imageView3"
		android:adjustViewBounds="true"
		android:layout_marginTop="30dp"
		app:srcCompat="@drawable/question"
		android:layout_below="@id/imageView1"/>
</RelativeLayout>




في ImageView الأول ، حاولنا تعيين ملف SVG الأصلي في خاصية android: src ، وفي الثانية ، ملف XML المحول في نفس الخاصية ، وفي الثالثة ، في التطبيق: srcCompat property (لاحظ أنه يجب تحديد مساحة الاسم هذه على النحو المحدد في الكود ).

كانت النتائج ملحوظة بالفعل في المصمم ، قبل إطلاق التطبيق - الطريقة الوحيدة المؤكدة لعرض ملفنا بشكل صحيح موجودة في ImageView الثالث.





أنت الآن بحاجة إلى التأكد من عرض الصورة بشكل صحيح على أجهزة مختلفة. للمقارنة ، اخترنا Huawei Honor 20 Pro و Nexus 5. وأيضًا ، بدلاً من طرق العرض غير الصحيحة ، حددنا الطريقة المطلوبة وقمنا بتغيير حجم ImageView إلى 150x150 dp و 200 x200 dp و 300x300 dp.



نتائج العمل

Huawei Honor 20 Pro





Nexus 5







كما ترى جودة الصور هي نفسها ، مما يعني أننا حققنا النتيجة المرجوة.



يتم استخدام الملف الناتج من الكود بنفس الطريقة المعتادة

image.SetImageResource(Resource.Drawable.< >);



العمل مع تنسيق SVG في Xamarin.iOS



في حالة Xamarin.iOS ، فإن الوضع هو نفسه مع Xamarin.Android ، بمعنى أن العمل مع ملفات SVG غير مدعوم خارج الصندوق. ومع ذلك ، فإن تنفيذه لا يتطلب الكثير من الجهد. في حالة تطوير iOS الأصلي ، يتطلب SVG اتصال SVGKit. يسمح لك بمعالجة مثل هذه الملفات دون اللجوء إلى حلول الطرف الثالث. في حالة Xamarin.iOS ، يمكننا استخدام مكتبة SVGKit.Binding . هذا غلاف C # فوق SVGKit الأصلي.



كل ما نحتاجه هو توصيل حزمة NuGet بمشروعنا. في وقت كتابة هذا التقرير ، أحدث إصدار هو 1.0.4.





لسوء الحظ ، على ما يبدو ، لم تعد هذه المكتبة مدعومة ، لكنها مناسبة تمامًا للاستخدام في المشروع.

هنا يتم تنفيذ فئة SVGKImage (صورة SVG نفسها) و SVGKFastImageView (عنصر التحكم لعرض مثل هذه الصور).



رمز للاستخدام
void CreateControls()
{
	var image_bundle_resource = new SVGKImage("SVGImages/question.svg");
	img1 = new SVGKFastImageView(image_bundle_resource);
	Add(img1);
	img1.Frame = new CGRect(View.Frame.Width / 4, 50, View.Frame.Width / 2, View.Frame.Width / 2);

	var image_content = new SVGKImage(Path.Combine(NSBundle.MainBundle.BundlePath, "SVGImages/question1.svg"));
	img2 = new SVGKFastImageView(image_content);
	Add(img2);
	img2.Frame = new CGRect(5, img1.Frame.Bottom + 5, View.Frame.Width - 5, View.Frame.Width - 5);
}


لإنشاء SVGKImage ، تنفذ المكتبة خيارين اعتمادًا على BuildAction للملف - BundleResource (يُشار إليه بواسطة image_bundle_resource في الكود) والمحتوى (يُشار إليه بواسطة image_content في الكود).

للأسف المكتبة بها عدد من العيوب:



  1. لا يدعم SVGKFastImageView التهيئة بدون توفير SVGKImage - تم طرح خطأ يشير إلى الحاجة إلى استخدام المُنشئ المقدم في الكود ؛
  2. لا توجد طريقة لاستخدام ملفات SVG في عناصر التحكم الأخرى. ومع ذلك ، إذا لم يكن ذلك ضروريًا ، فيمكنك استخدامه.


نتيجة البرنامج




إذا كان التطبيق مهمًا لاستخدام ملفات SVG ليس فقط في ImageView ، يمكنك استخدام مكتبات أخرى. على سبيل المثال ، FFImageLoading . إنها مكتبة قوية لا تسمح لك فقط بتفريغ صور SVG في Xamarin.iOS UIImage الأصلي ، ولكن أيضًا للقيام بذلك مباشرة في عنصر التحكم المطلوب ، مما يوفر وقت التطوير. هناك أيضًا وظيفة لتنزيل الصور من الإنترنت ، لكننا لن نأخذها في الاعتبار في هذه المقالة.



لاستخدام المكتبة ، تحتاج إلى توصيل حزمتي NuGet بالمشروع - Xamarin.FFImageLoading و Xamarin.FFImageLoading.SVG.





في تطبيق الاختبار ، استخدمنا طريقة تقوم بتحميل صورة SVG في UIImageView مباشرةً وتفريغ الصورة في صورة UIImage الأصلية.



عينة من الرموز
private async Task CreateControls()
{
    img1 = new UIImageView();
    Add(img1);
    img1.Frame = new CGRect(View.Frame.Width / 4, 50, View.Frame.Width/2, View.Frame.Width/2);

    ImageService.Instance
                .LoadFile("SVGImages/question.svg")
                .WithCustomDataResolver(new SvgDataResolver((int)img1.Frame.Width, 0, true))
                .Into(img1);

    var button = new UIButton() { BackgroundColor = UIColor.Red};
    Add(button);
    button.Frame = new CGRect(View.Frame.Width/2 - 25, img1.Frame.Bottom + 20, 50, 50);

    UIImage imageSVG = await ImageService.Instance
                .LoadFile("SVGImages/question.svg")
                .WithCustomDataResolver(new SvgDataResolver((int)View.Frame.Width, 0, true))
                .AsUIImageAsync();
    if(imageSVG != null)
        button.SetBackgroundImage(imageSVG, UIControlState.Normal);
}




توجد أيضًا طريقة في هذه المكتبة لتجاوز تمثيل سلسلة SVG في UIImage ، ولكنها مفيدة فقط للملفات الصغيرة.



عينة من الرموز
    var svgString = @"<svg><rect width=""30"" height=""30"" style=""fill:blue"" /></svg>";

    UIImage img = await ImageService.Instance
		.LoadString(svgString)
		.WithCustomDataResolver(new SvgDataResolver(64, 0, true))
		.AsUIImageAsync();




تحتوي المكتبة أيضًا على عدد من الوظائف ، لكننا لن نعتبرها هنا. الشيء الوحيد الجدير بالذكر حقًا هو أنه يمكن استخدام هذه المكتبة في Xamarin.Android أيضًا. للاستخدام في مشاريع Xamarin.Forms ، هناك نظائر لهذه المكتبة ، والتي سنناقشها أدناه.



العمل مع تنسيق SVG في Xamarin.Forms



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



Xamarin.FFImageLoading Xamarin.FFImageLoading.SVG, Xamarin.Forms (Xamarin.FFImageLoading.Forms Xamarin.FFImageLoading.SVG.Forms). Xamarin.Forms , , :



  1. (PCL ) NuGet- — Xamarin.FFImageLoading.Forms Xamarin.FFImageLoading.SVG.Forms;
  2. AppDelegate.cs iOS-:

    public override bool FinishedLaunching( UIApplication app, NSDictionary options )
    {
        global::Xamarin.Forms.Forms.Init();
        FFImageLoading.Forms.Platform.CachedImageRenderer.Init();
        CachedImageRenderer.InitImageSourceHandler();
        var ignore = typeof(SvgCachedImage);
        LoadApplication(new App());
        return base.FinishedLaunching(app, options);
    }
  3. MainActivity.cs Android-:

    protected override void OnCreate( Bundle savedInstanceState )
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
        base.OnCreate(savedInstanceState);
    
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);
        CachedImageRenderer.InitImageViewHandler();
        var ignore = typeof(SvgCachedImage);
        LoadApplication(new App());
    }
    
بعد ذلك يمكن استخدام المكتبة.

تنفذ المكتبة استدعاءات لموارد SVG الموجودة في مشاريع النظام الأساسي ومشاريع EmbeddedResouce PCL. يتم استخدام SvgCachedImage لعرض صور SVG. على عكس عنصر تحكم الصورة الأصلي المستخدم في Xamarin.Forms وقبول ImageSource ، يعمل SvgCachedImage مع SvgImageSource.



مهم!
svg, , :



xmlns:svg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"




يمكنك توفيره بعدة طرق:



  1. حدد في ملف XAML اسم ملف SVG الموجود في موارد مشروع النظام الأساسي:

    <svg:SvgCachedImage
                Source="question.svg"
                WidthRequest="100"
                HeightRequest="100"/>
    
  2. حدد في ملف XAML المسار الكامل لملف SVG الذي يعد موردًا مضمنًا في مشروع PCL:



    <svg:SvgCachedImage
                Source="resource://SVGFormsTest.SVG.question1.svg"
                WidthRequest="100"
                HeightRequest="100"/>
    


    عند التحميل من الموارد المضمنة ، يمكنك تحديد اسم تجميع آخر:



    resource://SVGFormsTest.SVG.question1.svg?assembly=[ASSEMBLY FULL NAME]
    
  3. عند العمل من التعليمات البرمجية ، قم أولاً بتسمية عناصر التحكم:



    <svg:SvgCachedImage
                x:Name="image"
                WidthRequest="100"
                HeightRequest="100"/>
    


    بعد ذلك ، بناءً على المورد الذي يتم استخدامه ، نختار أحد الخيارات:



    • لاستخدام الموارد المضمنة

      image.Source = SvgImageSource.FromResource("SVGFormsTest.SVG.question1.svg");






    • image.Source = SvgImageSource.FromFile("question.svg");


  4. Binding 2 :



    • , SvgImageSource. , XAML- :



      <svg:SvgCachedImage
                  Source="{Binding Source}"
                  WidthRequest="100"
                  HeightRequest="100"/>
      
    • . , . :



      <ContentPage.Resources>
              <ResourceDictionary>
                  <svg:SvgImageSourceConverter
                      x:Key="SourceConverter"/>
              </ResourceDictionary>
          </ContentPage.Resources>
      


      :



      <svg:SvgCachedImage
                  Source="{Binding Source1, Converter={StaticResource SourceConverter}}"
                  WidthRequest="100"
                  HeightRequest="100"/>
      


      :



      public MainVM()
      {
          source1 = "question.svg";
      }
      
      string source1;
      public string Source1
      {
          get => source1;
          set
          {
              source1 = value;
          }
      }
      


      :



      public MainVM()
      {
          source1 = "resource://SVGFormsTest.SVG.question1.svg";
      }
      
      string source1;
      public string Source1
      {
          get => source1;
          set
          {
              source1 = value;
          }
      }
      


      , . , , .




SVG- , . , , , , , , SVG- . , PNG- , SVG, .



موارد SVG لها أيضًا عيب بسيط. لا يمكن توفيرها كأيقونة للتطبيق ، حيث يمكن استخدام ملفات PNG و JPEG فقط كأيقونة وفقًا لإرشادات Google و Apple.




All Articles