تطوير تطبيقات الجوال في بيثون. مكتبة KivyMD


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

في اليوم الآخر قمت بتنزيل التطبيق التجريبي Flutter UIKit من Google Play:


والآن سنحاول تكرار شاشة واحدة من هذا التطبيق. دعونا نلقي نظرة على النتائج على الفور: رفرفة على اليسار ، Kivy و KivyMD على اليمين.

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

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


بشكل تخطيطي ، ستبدو شاشتنا كما يلي:


تصميم هذه الشاشة بسيط للغاية:


لماذا أتحدث عن FloatLayout إذا كانت شاشتنا موروثة من الشاشة؟

<ProductScreen@Screen>: ... 

فقط لأن الشاشة -> RelativeLayout -> FloatLayout.

يتم وضع جميع الأدوات المصغّرة في FloatLayout من الركن الأيسر السفلي ، أي على الشاشة يتم تعيين الموضع تلقائيًا لها (0 ، 0). في الترميز ، ليس من الصعب تتبع ترتيب إضافة عناصر إلى الشاشة من الأعلى إلى الأسفل:


إذا قام شخص ما بالاهتمام ، فقد أشرنا إلى موضع أداة واحدة فقط:

 MDToolbar: ... pos_hint: {"top": 1} 

بالإضافة إلى الإحداثيات المحددة (س ، ص) ، يمكن إعطاء كل أداة في Kivy تلميحًا للموضع:

 pos_hint: {"top": 1} #    pos_hint: {"bottom": 1} #    pos_hint: {"right": 1} #    pos_hint: {"center_y": .5} #     pos_hint: {"center_x": .2} #   20 %       ... ... 

لذلك ، صورة الخلفية السفلية ...

  BoxLayout: size_hint_y: None height: root.height - toolbar.height FitImage: source: "smokestackheather.jpeg" 

... بفضل تطبيق FitImage (مكتبة KivyMD) ، يتم تمديده تلقائيًا إلى جميع المساحة المخصصة له مع الحفاظ على نسب الصورة:



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

 from kivy.app import App from kivy.lang import Builder KV = """ Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run() 

واحصل على النتيجة:


استغرق الزر حتى 100 ٪ من المساحة. لوضع زر في وسط الشاشة ، تحتاج أولاً إلى تعيين الحجم المطلوب له ، وثانياً ، للإشارة إلى موقعه:

 from kivy.app import App from kivy.lang import Builder KV = """ Button: text: "Button" size_hint: None, None size: 100, 50 pos_hint: {"center_y": .5, "center_x": .5} """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run() 

الآن تغيرت الصورة:


يمكنك أيضًا تحديد خاصية size_hint ، من 0 إلى 1 ، (أي ما يعادل 0-100٪) ، أي تلميح الحجم:

 from kivy.app import App from kivy.lang import Builder KV = """ BoxLayout: Button: text: "Button" size_hint_y: .2 Button: text: "Button" size_hint_y: .1 Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run() 


أو نفس الشيء ، ولكن تلميح العرض ( size_hint_x ):

 from kivy.app import App from kivy.lang import Builder KV = """ BoxLayout: Button: text: "Button" size_hint_x: .2 Button: text: "Button" size_hint_x: .1 Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run() 


يبلغ طول شريط MDToolbar 56 نقطة في الثانية ، ولا يمكنه شغل كل المساحة ، وإذا لم تخبره أن مكانه في المقدمة ، فسيتمسك تلقائيًا بأسفل الشاشة:


قائمة البطاقات - OrderProductLayout (سنتحدث عنها أدناه) - عبارة عن ScrollView مع عناصر MDCard وتحتل كامل طول الشاشة ، لكن بفضل الحشو (قيم المسافة البادئة في أدنى المستويات) يبدو أنها تقع أعلى مركز الشاشة قليلاً. حسنا ، بشكل افتراضي MDBottomAppBar يسقط مرساة إلى الحد السفلي من الشاشة. لذلك ، فقط MDToolbar أشرنا حيث مكانها.

الآن دعونا نرى ما هي القطعة OrderProductLayout:


كما ترون ، فهذه أربع بطاقات مضمنة في ScrillView. على عكس الشاشة الرئيسية ، الموروثة من FloatLayout ، هنا تتم قراءة جميع الأدوات المصغّرة من الأعلى إلى الأسفل.


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


يمكن رؤية ذلك بشكل أكثر وضوحًا من المخطط التالي ، حيث يتم استخدام الاتجاه الأفقي BoxLayout:


نمنع BoxLayout من استخدام 100٪ من المساحة - size_hint_y: لا شيء وقلنا - طولك سيكون بالضبط نفس ارتفاع العنصر الأعلى المتداخل فيك - الارتفاع: self.minimum_height .

قائمة الصور:


إذا أردنا استخدام التمرير العمودي للقائمة ، فسنحتاج إلى تغيير GridLayout على النحو التالي:

  ScrollView: GridLayout: size_hint_y: None height: self.minimum_height cols: 1 

يستعاض عن الصفوف (الأعمدة) بالأعمدة ( cols ) وتشير إلى الحد الأدنى وليس العرض ، ولكن الارتفاع:

 from kivy.app import App from kivy.lang import Builder from kivy.metrics import dp from kivy.uix.button import Button KV = """ ScrollView: GridLayout: id: box size_hint_y: None height: self.minimum_height spacing: "5dp" cols: 1 """ class MyApp(App): def build(self): return Builder.load_string(KV) def on_start(self): for i in range(20): self.root.ids.box.add_widget( Button( text=f"Label {i}", size_hint_y=None, height=dp(40), ) ) MyApp().run() 



البطاقات التالية هي اختيار اللون والحجم (تكاد تكون متطابقة):


لا تتمثل الميزة المميزة للغة الترميز Kv Language في البنية الواضحة لعناصر واجهة المستخدم فحسب ، بل أيضًا في حقيقة أن هذه اللغة تدعم بعض ميزات لغة Python. وهي: طرق الاتصال ، إنشاء / تغيير المتغيرات ، العمليات المنطقية ، I / O والعمليات الرياضية ...


حساب القيمة المعلنة في التصنيف ...

  Label: value: 0 text: str(self.value) 

... يحدث مباشرة في العلامات نفسها:

  MDIconButton: on_release: label_value.value -= 1 if label_value.value > 0 else 0 

ولن أصدق أن هذا (كود الرفرفة) ...



... أكثر منطقية وقراءة من رمز لغة Kv:


بالأمس سئلت كيف يعمل كيفي مع بيئة التطوير ، هل هناك عمليات الإكمال التلقائي ، والأحمال الساخنة وغيرها من المرافق؟ مع عمليات الإكمال التلقائي ، كل شيء على ما يرام إذا كنت تستخدم PyCharm:


أما بالنسبة للحمل الساخن ... بيثون هي لغة مترجمة. كيفى يستخدم بيثون. وفقًا لذلك ، لمعرفة النتيجة ، لا تحتاج إلى ترجمة الشفرة وتشغيلها - انظر / اختبارها. كما قلت ، لا تستخدم Kivy واجهات برمجة التطبيقات الأصلية لتقديم واجهة المستخدم ، وبالتالي فهي تتيح لك محاكاة نماذج مختلفة من الأجهزة والأنظمة الأساسية باستخدام وحدة الشاشة . يكفي تشغيل مشروعك بالمعلمات الضرورية بحيث تفتح نافذة التطبيق المختبر على الكمبيوتر كما لو كانت تعمل على جهاز حقيقي. هذا يبدو غريباً ، لكن نظرًا لأن ملخصات Kivy من المنصة في تقديم واجهة المستخدم ، فإن هذا يلغي الحاجة إلى محاكاة تقليدية وبطيئة للاختبارات. هذا ينطبق فقط على واجهة المستخدم. على سبيل المثال ، تم اختبار تطبيق الاختبار الموضح في هذه المقالة باستخدام خيارات الشاشة -m: droid2 ، عمودي ، scale = .75 .

على اليسار - يعمل على جهاز محمول ، على اليمين - على جهاز كمبيوتر:

قائمة كاملة من المعلمات وحدة الشاشة:
 devices = { # device: (name, width, height, dpi, density) 'onex': ('HTC One X', 1280, 720, 312, 2), 'one': ('HTC One', 1920, 1080, 468, 3), 'onesv': ('HTC One SV', 800, 480, 216, 1.5), 's3': ('Galaxy SIII', 1280, 720, 306, 2), 'note2': ('Galaxy Note II', 1280, 720, 267, 2), 'droid2': ('Motorola Droid 2', 854, 480, 240, 1.5), 'xoom': ('Motorola Xoom', 1280, 800, 149, 1), 'ipad': ('iPad (1 and 2)', 1024, 768, 132, 1), 'ipad3': ('iPad 3', 2048, 1536, 264, 2), 'iphone4': ('iPhone 4', 960, 640, 326, 2), 'iphone5': ('iPhone 5', 1136, 640, 326, 2), 'xperiae': ('Xperia E', 480, 320, 166, 1), 'nexus4': ('Nexus 4', 1280, 768, 320, 2), 'nexus7': ('Nexus 7 (2012 version)', 1280, 800, 216, 1.325), 'nexus7.2': ('Nexus 7 (2013 version)', 1920, 1200, 323, 2), # taken from design.google.com/devices # please consider using another data instead of # a dict for autocompletion to work # these are all in landscape 'phone_android_one': ('Android One', 854, 480, 218, 1.5), 'phone_htc_one_m8': ('HTC One M8', 1920, 1080, 432, 3.0), 'phone_htc_one_m9': ('HTC One M9', 1920, 1080, 432, 3.0), 'phone_iphone': ('iPhone', 480, 320, 168, 1.0), 'phone_iphone_4': ('iPhone 4', 960, 640, 320, 2.0), 'phone_iphone_5': ('iPhone 5', 1136, 640, 320, 2.0), 'phone_iphone_6': ('iPhone 6', 1334, 750, 326, 2.0), 'phone_iphone_6_plus': ('iPhone 6 Plus', 1920, 1080, 400, 3.0), 'phone_lg_g2': ('LG G2', 1920, 1080, 432, 3.0), 'phone_lg_g3': ('LG G3', 2560, 1440, 533, 3.0), 'phone_moto_g': ('Moto G', 1280, 720, 327, 2.0), 'phone_moto_x': ('Moto X', 1280, 720, 313, 2.0), 'phone_moto_x_2nd_gen': ('Moto X 2nd Gen', 1920, 1080, 432, 3.0), 'phone_nexus_4': ('Nexus 4', 1280, 768, 240, 2.0), 'phone_nexus_5': ('Nexus 5', 1920, 1080, 450, 3.0), 'phone_nexus_5x': ('Nexus 5X', 1920, 1080, 432, 2.6), 'phone_nexus_6': ('Nexus 6', 2560, 1440, 496, 3.5), 'phone_nexus_6p': ('Nexus 6P', 2560, 1440, 514, 3.5), 'phone_samsung_galaxy_note_4': ('Samsung Galaxy Note 4', 2560, 1440, 514, 3.0), 'phone_samsung_galaxy_s5': ('Samsung Galaxy S5', 1920, 1080, 372, 3.0), 'phone_samsung_galaxy_s6': ('Samsung Galaxy S6', 2560, 1440, 576, 4.0), 'phone_sony_xperia_c4': ('Sony Xperia C4', 1920, 1080, 400, 2.0), 'phone_sony_xperia_z_ultra': ('Sony Xperia Z Ultra', 1920, 1080, 348, 2.0), 'phone_sony_xperia_z1_compact': ('Sony Xperia Z1 Compact', 1280, 720, 342, 2.0), 'phone_sony_xperia_z2z3': ('Sony Xperia Z2/Z3', 1920, 1080, 432, 3.0), 'phone_sony_xperia_z3_compact': ('Sony Xperia Z3 Compact', 1280, 720, 313, 2.0), 'tablet_dell_venue_8': ('Dell Venue 8', 2560, 1600, 355, 2.0), 'tablet_ipad': ('iPad', 1024, 768, 132, 1.0), 'tablet_ipad_mini': ('iPad Mini', 1024, 768, 163, 1.0), 'tablet_ipad_mini_retina': ('iPad Mini Retina', 2048, 1536, 326, 2.0), 'tablet_ipad_pro': ('iPad Pro', 2732, 2048, 265, 2.0), 'tablet_ipad_retina': ('iPad Retina', 2048, 1536, 264, 2.0), 'tablet_nexus_10': ('Nexus 10', 2560, 1600, 297, 2.0), 'tablet_nexus_7_12': ('Nexus 7 12', 1280, 800, 216, 1.3), 'tablet_nexus_7_13': ('Nexus 7 13', 1920, 1200, 324, 2.0), 'tablet_nexus_9': ('Nexus 9', 2048, 1536, 288, 2.0), 'tablet_samsung_galaxy_tab_10': ('Samsung Galaxy Tab 10', 1280, 800, 148, 1.0), 'tablet_sony_xperia_z3_tablet': ('Sony Xperia Z3 Tablet', 1920, 1200, 282, 2.0), 'tablet_sony_xperia_z4_tablet': ('Sony Xperia Z4 Tablet', 2560, 1600, 297, 2.0)TodoList() app.run() } 


حسنًا ، وأخيرا ، النتيجة النهائية هي الإطلاق على جهاز محمول ...


الشيء الوحيد الذي يزعج هو سرعة الاطلاق. في نفس الرفرفة هي ببساطة هائلة!

آمل أن أكون مفيدة لشخص ما ، أراك قريبًا!

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


All Articles