Kivy. Xamarin React Native. Trois cadres - une expérience


Salutations à tous! Dès que la fumée de la discussion animée dans les commentaires de mon article, Kivy est un cadre d'âne pour le développement multiplateforme n ° 1 , et entre autres un commentaire digne d'attention l'a fait , nous ( Mirimon , SeOd ) avons pensé qu'il serait intéressant pour nous et les lecteurs de comparer Kivy, Xamarin.Forms et React Native, en écrivant la même application sur eux, l'accompagnez de l'article correspondant sur Habré, tournez sur GitHub et dites honnêtement qui a rencontré quelles difficultés lors de la mise en œuvre. Après nous être réunis dans le télégramme et avoir discuté des détails, nous nous sommes mis au travail.

Pour cette comparaison, nous avons décidé d'écrire un planificateur de tâches simple avec trois écrans. Découper l'état de ces trois plateformes aujourd'hui, en utilisant l'exemple de quelque chose de plus volumineux que l'exemple que nous avons choisi, car tout le monde est occupé dans ses projets / au travail / à la maison, prend trop de temps. Malgré la simplicité de notre application, elle vous permettra de démontrer clairement les principes de développement d'applications dans chaque environnement, de travailler avec des données, l'interface utilisateur, etc.

Trois cadres - une expérience. Xamarin.Forms. 2e partie
Trois cadres - une expérience. React Native. 3e partie

Cet article est le premier du cycle, je veux donc commencer par les TdR, que nous avons esquissés pour nous-mêmes, afin que le résultat soit similaire.

Option TK:


  • Les notes doivent être structurées par projet.
  • Les notes peuvent être ajoutées par différentes personnes, donc l'auteur de la note doit être indiqué
  • Les notes à l'intérieur du projet doivent être ajoutées / supprimées / modifiées.
  • Les notes doivent être de la taille du contenu, mais pas plus de 150 pixels
  • La suppression des notes doit se faire à la fois via le menu contextuel de la note elle-même et par balayage

Un exemple d'interface utilisateur devrait ressembler à ceci:



Avant de commencer, un peu d'aide sur Kivy:
Kivy est un cadre graphique multiplateforme écrit dans le langage de programmation Python / Cython, basé sur OpenGL ES 2, visant à créer des interfaces utilisateur modernes, plus axées sur le travail avec des appareils tactiles. Les applications Kivy s'exécutent sur des plateformes telles que Linux, OS X, Windows, Android, iOS et Rapberry Pi. En cours de développement, vous avez accès à un large éventail de bibliothèques Python allant des requêtes à NumPy et OpenCV. Kivy a accès à presque toutes les API mobiles natives (GPS, appareil photo, accéléromètre, API Google pour Android), via PyJNIus (Android) et PyOBJus (iOS), qui enveloppent automatiquement le code Java / Objective-C en Python .

Kivy est rapide. Cela s'applique à la fois au développement d'applications et à la vitesse d'exécution des applications. Toutes les fonctions critiques sont implémentées au niveau C. Kivy utilise également le GPU partout où cela a du sens. Le GPU fait la plupart du travail, augmentant considérablement les performances.

Kivy est très flexible. Cela signifie que le développement rapide de Kivy vous permet de vous adapter instantanément aux nouvelles technologies. Les développeurs de Kivy ont ajouté à plusieurs reprises la prise en charge de nouveaux périphériques externes et protocoles logiciels, parfois même avant leur sortie. Kivy peut être utilisé conjointement avec de nombreuses solutions tierces différentes. Par exemple, sous Windows, Kivy prend en charge WM_TOUCH, ce qui signifie que tout appareil doté de pilotes Windows 7 Pen & Touch fonctionnera avec Kivy. Sous OS X, vous pouvez utiliser des appareils Apple avec prise en charge Multi-Touch, tels que des trackpads et des souris. Sous Linux, vous pouvez utiliser des événements d'entrée d'entrée HID. De plus, Kivy prend en charge TUIO (Tangible User Interface Objects) et un certain nombre d'autres sources d'entrée.

Vous pouvez écrire une application simple avec quelques lignes de code. Les programmes Kivy sont créés en utilisant le langage de programmation Python, qui est incroyablement polyvalent et puissant, mais facile à utiliser. De plus, les développeurs de Kivy ont créé leur propre langage de balisage graphique pour créer des interfaces graphiques personnalisées sophistiquées. Cette langue vous permet de configurer, connecter et organiser rapidement les éléments de l'application.

Et, oui, Kivy est totalement gratuit. Vous pouvez l'utiliser partout! Dans un produit commercial ou en Open Source.

Je donnerai tout le code de l'application et montrerai suffisamment en détail comment ces ou ces éléments sont implémentés lors du développement pour les plateformes mobiles. En tant qu'IDE , j'utilise toujours PyCharm , qui prend parfaitement en charge la syntaxe du langage Kv - un langage DSL spécial dans lequel la représentation de l'interface utilisateur de votre application est écrite. Le squelette de l'application a été créé à l'aide de l' utilitaire de console CreatorKivyProject , qui fournit des écrans de base à l'aide du modèle MVVM.


Le dossier baseclass contient la logique des widgets et des contrôles implémentés dans le langage de programmation Python, dans les fichiers de description d'interface kv dans le langage Kv . Le répertoire applibs est utilisé pour les bibliothèques tierces, dans le dossier de données , il y a du contenu multimédia, des bases de données et d'autres données. Le fichier main.py est le point d'entrée de l'application. Il ne fait rien d'autre que lancer l'interface utilisateur TodoList (). Run () rend, capte une erreur si elle se produit et affiche une fenêtre pour envoyer un rapport de bogue, créé automatiquement par l'utilitaire CreatorKivyProject , n'a rien à voir avec l'écriture de notre application, et n'est donc pas considéré.

Le fichier todolist.py avec le code du programme implémente la classe TodoList , qui charge les dispositions d'interface, initialise leurs instances, surveille les événements des touches de fonction de l'appareil et renvoie notre premier écran, qui sont répertoriés dans le gestionnaire d'activité. Après TodoList (). Run () , la fonction de génération est appelée et renvoie le widget qui sera affiché à l'écran.

Par exemple, le code d'un programme simple qui affiche un seul écran avec une image ressemblera à ceci:


Et voici le schéma de notre classe d'application:


todolist.py:
# -*- coding: utf-8 -*- import os from kivy.app import App from kivy.lang import Builder from kivy.core.window import Window from kivy.factory import Factory from libs.applibs.kivymd.theming import ThemeManager from libs.dataBase import DataBase class TodoList(App, DataBase): title = 'Todo List' icon = 'icon.png' theme_cls = ThemeManager() theme_cls.primary_palette = 'BlueGrey' def __init__(self, **kvargs): super(TodoList, self).__init__(**kvargs) Window.bind(on_keyboard=self.eventsProgram) Window.softinput_mode = 'below_target' self.Window = Window self.pathToBase = '%s/data/dataProjects.json' % self.directory self.nameAuthor = u' ' def build(self): self.setDataProjects() self.loadAllKvFiles(os.path.join(self.directory, 'libs', 'uix', 'kv')) self.rootScreen = Factory.RootScreen() #    #  Activity. self.activityManager = self.rootScreen.ids.activityManager self.listProjectsActivity = self.rootScreen.ids.listProjectsActivity self.listNotesActivity = self.rootScreen.ids.listNotesActivity self.addNewNoteActivity = self.rootScreen.ids.addNewNoteActivity return self.rootScreen def loadAllKvFiles(self, directory_kv_files): for kv_file in os.listdir(directory_kv_files): kv_file = os.path.join(directory_kv_files, kv_file) if os.path.isfile(kv_file): Builder.load_file(kv_file) def on_start(self): self.listProjectsActivity.setListProjects(self) def eventsProgram(self, instance, keyboard, keycode, text, modifiers): if keyboard in (1001, 27): if self.activityManager.current == 'add new note activity': self.activityManager.backActivity( 'list notes activity', self.addNewNoteActivity.ids.floatingButton) if self.activityManager.current == 'list notes activity': self.activityManager.current = 'list project activity' return True 


Notre application se compose de seulement trois activités , le gestionnaire d'écran ( ScreenMenager ), que nous avons renvoyé aux fonctions de construction , est responsable de la commutation :

 #:import ListProjectsActivity libs.uix.baseclass.ListProjectsActivity.ListProjectsActivity #:import ListNotesActivity libs.uix.baseclass.ListNotesActivity.ListNotesActivity #:import AddNewNoteActivity libs.uix.baseclass.AddNewNoteActivity.AddNewNoteActivity #:import ActivityManager libs.uix.baseclass.ActivityManager.ActivityManager <RootScreen@BoxLayout>: orientation: 'vertical' spacing: dp(2) ActivityManager: id: activityManager ListProjectsActivity: id: listProjectsActivity ListNotesActivity: id: listNotesActivity AddNewNoteActivity: id: addNewNoteActivity 

Lorsque l'application démarre, l'activité qui est spécifiée dans ActivityManager en premier sera installée. Dans notre cas, c'est ListProjectsActivity . Dans l'application pour les listes de projets et de tâches, j'ai utilisé ScrollView . Bien que ce soit plus correct - RecycleView . Parce que le premier, s'il y a plus d'une centaine d'articles et de projets, ne peut pas le faire. Plus précisément, le rendu des listes prendra très longtemps. RecycleView vous permet d'afficher des listes de n'importe quelle longueur presque instantanément. Mais comme dans tous les cas, avec de grandes listes, vous devrez utiliser soit le chargement dynamique des données dans une liste, soit la pagination, mais cela n'a pas été discuté dans le TOR, j'ai utilisé ScrollView . La deuxième raison est que j'étais trop paresseux pour refaire les listes sous RecycleView (et son utilisation est fondamentalement différente de ScrollView ), et il n'y avait pas beaucoup de temps, car toute l'application a été écrite en quatre heures dans des pauses fumeurs et des pauses café.

L'écran de démarrage avec une liste de projets (ListProjectsActivity.kv et ListProjectsActivity.py) ressemble à ceci:


Étant donné que la disposition de l'écran ListProjectsActivity est déjà affichée à l'écran, je vais montrer à quoi ressemble sa classe de contrôle:

 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.screenmanager import Screen as Activity from libs.uix.baseclass.InputDialog import InputDialog from . ProjectItem import ProjectItem class ListProjectsActivity(Activity): objApp = App.get_running_app() def setListProjects(self, objApp): for nameProject in objApp.dataProjects.keys(): self.ids.layoutContainer.add_widget(ProjectItem(projectName=nameProject)) def createNewProject(self, projectName): if projectName and not projectName.isspace(): self.ids.layoutContainer.add_widget(ProjectItem(projectName=projectName)) self.objApp.addProjectInBase(projectName) def deleteProject(self, instance): for projectName in self.objApp.dataProjects: if instance.projectName == projectName: self.objApp.deleteProjectFromBase(projectName) break def showDialogCreateProject(self, *args): InputDialog( title=' ', hintText=' ', textButtonCancel='', textTuttonOk='', eventsCallback=self.createNewProject).show() 

Appel de la boîte de dialogue:


Dans le travail, appeler la fenêtre et créer un nouveau projet ressemblera à ceci:

Je ne m'attarderai pas sur la question des données d'application, car les données sont un dictionnaire régulier du formulaire

 {"Name Project": [{"pathToAvatar": "", "nameDate": "", "nameAuthor": "", "textNote": ""}]} 

et qui est stocké dans le répertoire de données sous la forme d'un simple fichier json.

Voyons ce qu'est l'élément avec le nom du projet et comment utiliser Kivy pour supprimer un élément de la liste par balayage? Pour ce faire, nous devons hériter du comportement du widget dans la liste de la classe SwipeBehavior de la bibliothèque SwipeToDelete :

ProjectItemActivity.py
 from kivy.properties import StringProperty from kivy.uix.boxlayout import BoxLayout from libs.applibs.swipetodelete import SwipeBehavior class ProjectItemActivity(SwipeBehavior, BoxLayout): projectName = StringProperty() def on_touch_down(self, touch): if self.collide_point(touch.x, touch.y): self.move_to = self.x, self.y return super(ProjectItemActivity, self).on_touch_down(touch) def on_touch_move(self, touch): if self.collide_point(touch.x, touch.y): self.reduce_opacity() return super(ProjectItemActivity, self).on_touch_move(touch) def on_touch_up(self, touch): if self.collide_point(touch.x, touch.y): self.check_for_left() self.check_for_right() return super(ProjectItemActivity, self).on_touch_up(touch) 

Et la description de l'élément de projet dans le balisage Kv:

ProjectItemActivity.kv
 <ProjectItemActivity>: swipe_rectangle: self.x, self.y , self.width, self.height swipe_timeout: 1000000 swipe_distance: 1 event_after_swipe: app.listActivity.deleteProject OneLineListItem: text: root.projectName on_press: app.listActivity.setNotesProject(root.projectName) 

En général, chaque widget dans Kivy a une méthode on_touch avec laquelle vous pouvez capturer tous les événements qui se produisent à l'écran. Voici une petite partie de la liste des événements disponibles:

 ['double_tap_time', 'grab_state', 'is_double_tap', 'is_mouse_scrolling', 'is_touch', 'is_triple_tap', 'move', 'push', 'push_attrs', 'push_attrs_stack', 'scale_for_screen', 'time_end', 'time_start', 'time_update', 'triple_tap_time', 'ungrab', 'update_time_end'] 


Implémentation du menu contextuel pour Android ...

Il n'y a eu aucun problème ici non plus, car il s'agit simplement d'un widget DropDown standard. Grâce au fait que vous pouvez personnaliser tous les widgets et contrôles dans Kivy autant que votre imagination le permet, j'ai facilement obtenu un joli menu. A gauche se trouve la base DropDown, à droite est la mienne:

Présentation de la liste du menu contextuel:

ContextMenuAndroidActivity.kv
 #:import MDSeparator libs.applibs.kivymd.card.MDSeparator #:import MenuItem libs.applibs.animdropdown.MenuItem <ContextMenuAndroidActivity>: MenuItem: text: '' menu: root on_press: root.tapOnItem(self.text) MDSeparator: MenuItem: text: '' menu: root on_press: root.tapOnItem(self.text) 

La partie logicielle du menu contextuel:

ContextMenuAndroidActivity.kv
 from kivy.app import App from kivy.clock import Clock from libs.applibs.animdropdown import AnimMenuDropDown class ContextMenuAndroidActivity(AnimMenuDropDown): def tapOnItem(self, textItem): objApp = App.get_running_app() if textItem == '': objApp.listActivity.deletePost() else: objApp.activityManager.current = 'add new note activity' Clock.schedule_once(objApp.addNewNoteActivity.editNote, .5) 

Ensuite, nous importons le bouton MenuDropDown de la bibliothèque animdropdown , lui passons l'objet de notre menu contextuel en tant que paramètre, puis nous ajoutons ce bouton à l'écran dont nous avons besoin. Dans notre application, voici le bouton à droite de la fiche:


Remarques sur la carte d'activité de balisage:


Classe de base NoteActivity :
 from kivy.app import App from kivy.properties import StringProperty from kivy.uix.boxlayout import BoxLayout from libs.applibs.animdropdown import MenuButton from libs.applibs.swipetodelete import SwipeBehavior from . ContextMenu import ContextMenu class NoteActivity(SwipeBehavior, BoxLayout): nameDate = StringProperty() textNote = StringProperty() pathToAvatar = StringProperty() def __init__(self, **kwargs): super(NoteActivity, self).__init__(**kwargs) self.objApp = App.get_running_app() menuButton = MenuButton( dropdown_cls=ContextMenu, icon='dots-vertical', _on_dropdown_fnc=self.setCurrentPost) self.ids.titleBox.add_widget(menuButton) def setCurrentPost(self, *args): self.objApp.listNotesActivity.checkCurentPost = self 


Implémentation logicielle de ListNotesActivity :
 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.screenmanager import Screen as Activity from kivy.properties import ObjectProperty from . NoteActivity import NoteActivity class ListNotesActivity(Activity): checkCurentPost = ObjectProperty() objApp = App.get_running_app() def clearList(self): if self.objApp.activityManager.current == 'list project activity': self.ids.layoutContainer.clear_widgets() def addNewNote(self, objApp): objApp.activityManager.current = 'add new note activity' def setDefaultcheckCurentPost(self): self.checkCurentPost = lambda x: None def setNotesProject(self, nameProject): self.ids.toolBar.title = nameProject for dataProject in self.objApp.dataProjects[nameProject][1]: self.ids.layoutContainer.add_widget(NoteActivity( textNote=dataProject['textNote'], nameDate=dataProject['nameDate'], pathToAvatar=dataProject['pathToAvatar'])) def deletePost(self, instance=None): #  . if not self.checkCurentPost: checkCurentPost = instance else: checkCurentPost = self.checkCurentPost self.ids.layoutContainer.remove_widget(self.checkCurentPost) nameProject = self.ids.toolBar.title self.objApp.deleteNoteFromBase(nameProject, checkCurentPost.textNote) def checkScroll(self): if self.checkCurentPost and type(self.checkCurentPost) is not NoteActivity: self.checkCurentPost(self) 

Comment gérer l'activité de l'application? Pour passer d'une activité à une autre, nous devons indiquer au gestionnaire d'écran le nom de la nouvelle activité:

 class ListNotesActivity(Activity): ... def addNewNote(self, *args): self.objApp.activityManager.current = 'add new note activity' 

... où 'ajouter une nouvelle activité de note' est le nom de l'activité pour ajouter une nouvelle note.

Écran et présentation de l' activité AddNewNoteActivity :


Classe de base:

 from kivy.app import App from kivy.animation import Animation from kivy.uix.screenmanager import Screen as Activity from kivy.metrics import dp from libs.uix.baseclass.NoteActivity import NoteActivity class AddNewNoteActivity(Activity): objApp = None edit = False oldTextNote = '' def animationButton(self): self.objApp = App.get_running_app() self.ids.toolBar.title = self.objApp.listNotesActivity.ids.toolBar.title Animation(size=(dp(56), dp(56)), d=.5, t='in_out_cubic').start(self.ids.floatingButton) def addNewNotes(self, textNote): if self.edit: nameProject = self.ids.toolBar.title self.objApp.addEditNoteInBase(nameProject, textNote, self.oldTextNote) self.objApp.activityManager.backActivity('list notes activity', self.ids.floatingButton) self.objApp.listNotesActivity.checkCurentPost.textNote = textNote self.edit = False return self.objApp.listNotesActivity.ids.layoutContainer.add_widget( NoteActivity( textNote=textNote, nameDate='%s\n%s' % ( self.objApp.nameAuthor, self.objApp.getDate()), pathToAvatar='data/images/avatar.png')) self.objApp.addNoteInBase(self.ids.toolBar.title, textNote, 'data/images/avatar.png') def editNote(self, interval): self.edit = True self.ids.textInput.text = self.objApp.listNotesActivity.checkCurentPost.textNote self.oldTextNote = self.ids.textInput.text 

Pour animer le bouton, j'ai utilisé l'événement on_enter , qui est déclenché lorsque l'activité est installée à l'écran:

Dans le balisage:

 <AddNewNoteActivity> on_enter: root.animationButton() 

En code Python:

 class AddNewNoteActivity(Activity): def animationButton(self): Animation(size=(dp(56), dp(56)), d=.5, t='in_out_cubic').start(self.ids.floatingButton) 


Contrairement à Xamarin.Forms, l'interface utilisateur de Kivy se ressemblera partout. Donc, si vous écrivez une application pour deux plates-formes (Android et iOS), vous devez en tenir compte lorsque vous balisez l'interface et spécifiez les propriétés des widgets. Ou faites deux annotations pour deux plates-formes (la logique reste inchangée). C'est un plus, puisque le rendu et les événements de l'interface utilisateur sont indépendants des fonctionnalités de la plate-forme, vous n'utilisez pas d'API natives pour contrôler ces actions, ce qui permet à votre application d'être exécutée sans douleur sur presque toutes les plates-formes. Tous les graphiques sont rendus à l'aide d'appels OpenGL et SDL2 natifs sur le GPU, ce qui vous permet de dessiner rapidement des menus, des boutons et d'autres charmes de l'interface graphique, y compris des graphiques 2D et 3D.

Cette application utilise Android UI MaterialDesign. Par exemple, mon dernier projet avait une interface adaptative:



Voici une démonstration des possibilités dans le style de Material Design:



Comme je l'ai dit, Kivy n'utilise pas d'API natives pour le rendu de l'interface utilisateur, il vous permet donc d'émuler différents modèles d'appareils et de plates-formes à l'aide du module d' écran . Il suffit d'exécuter votre projet avec les paramètres nécessaires pour que la fenêtre de l'application testée s'ouvre sur l'ordinateur comme si elle s'exécutait sur un appareil réel. Cela semble étrange, mais puisque Kivy résume la plate-forme lors du rendu de l'interface utilisateur, cela élimine le besoin d'émulateurs lourds et lents pour les tests. Cela ne s'applique qu'à l'interface utilisateur. Par exemple, l'application de test décrite dans cet article a été testée avec les paramètres -m screen: droid2, portrait, scale = .75 que one to one correspond à mon appareil réel.

Liste complète des paramètres du module d'écran:
 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() } 


Que dire en conclusion? Est-ce que Kivy est bon? Sans aucun doute bien! Si vous connaissez le merveilleux langage de programmation Python, vous pouvez facilement créer des applications pour des plates-formes mobiles (et pas seulement) avec le cadre non moins merveilleux de Kivy.

Avantages du développement d'applications à l'aide du framework Kivy:

  • Puisque nous avons affaire à Python, la vitesse de développement des applications est plusieurs fois plus rapide que la vitesse de développement dans tout autre langage ou framework de programmation.
  • Mégatonnes de bibliothèques Python prêtes à l'emploi que vous pouvez utiliser dans vos projets: OpenCV, Django, Flask, NumPy, ffmpeg, sqlite3, lxml et des milliers d'autres.
  • Étant donné que Kivy utilise OpenGL et GPU pour le rendu des graphiques, ainsi que ses propres widgets et contrôles, la vitesse de rendu de l'interface utilisateur est très élevée et vous êtes complètement soulagé du mal de tête, qui est présent dans d'autres cadres qui doivent entrer dans la partie native pour implémenter certaines parties de l'interface.
  • Vous n'utilisez le natif que là où vous avez besoin d'accéder à des fonctionnalités de plate-forme spécifiques qui ne peuvent tout simplement pas exister dans un cadre véritablement multiplateforme: par exemple, accès à la géolocalisation, accès à la caméra, technologie BlueTooth ...

    Implémenter l'accès à l'API Android native pour obtenir IMEI et le modèle d'appareil à l'aide de PyJnius:

 def _get_model_android(): from jnius import autoclass Build = autoclass('android.os.Build') return str(Build.DEVICE) def _get_imei_android(): from jnius import autoclass Service = autoclass('org.renpy.android.PythonActivity').mActivity Context = autoclass('android.content.Context') TelephonyManager = Service.getSystemService(Context.TELEPHONY_SERVICE) return str(TelephonyManager.getDeviceId()) 


Par exemple, une implémentation de périphériques IMEI de réception natifs en Java:

 import android.content.Context; import android.telephony.TelephonyManager; public class GetImeiAndroid { public String getImeiAndroid() { TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); String IMEINumber = tm.getDeviceId(); return IMEINumber; } } 

  • Vous pouvez utiliser des bibliothèques de pots tiers dans vos projets en ce qui concerne Android.
  • Vous êtes entièrement propriétaire de tous les événements survenant à l'écran: tactile, multitouch, swipe, punching et autres événements sans passer par le natif, c'est donc une partie intégrante de Kivy.

Fonctionnalités de Kivy dans les appareils tactiles:





Malgré tous les avantages, Kivy présente plusieurs inconvénients:

  • La vitesse du "démarrage à froid", c'est-à-dire le premier lancement de l'application à partir du moment où toutes les bibliothèques sont déployées, est assez longue. Les suivants sont ordinaires, mais plus longs que le natif, en fonction de la charge du processeur de l'appareil mobile.
  • Travaillez avec des listes. Vous pouvez afficher une liste d'une taille de 100 000 éléments en une demi-seconde (par exemple, cartes utilisateur, vitrine, devis), mais à une condition: toutes les cartes doivent avoir la même hauteur. Si vous affichez une liste de citations, par exemple, avec une quantité de texte inconnue à l'avance, mais dans leur intégralité, alors à la fois plus de dix points ne peuvent pas être affichés, car cela prendra environ 10-15 secondes. Dans ce cas, vous devrez charger 10 à 15 éléments chacun en faisant défiler la liste.
  • Il est impossible d'afficher du texte qui dépasse 6500 caractères (3,5 pages de texte imprimé) - nous obtenons un écran noir. Ceci est résolu en cassant le texte puis en le collant ensemble, ce qui semble toujours être une béquille. Cependant, il n'est pas clair à qui il viendrait à l'esprit de produire une telle quantité de texte à la fois. Surtout quand il s'agit de plateformes mobiles.

Plus d'articles sur Kivy

Une machine virtuelle (le premier article de ZenCODE) des développeurs Kivy est prête et configurée pour créer des projets pour les deux branches Python.

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


All Articles