Kivy Xamarin Reaccionar nativo. Tres marcos: un experimento


Un saludo a todos! Tan pronto como el humo de la acalorada discusión en los comentarios a mi artículo, Kivy es un marco burro para el desarrollo multiplataforma No. 1 , y entre otros lo hizo un comentario digno de atención , nosotros ( Mirimon , SeOd ) pensamos que sería interesante para nosotros y los lectores comparar Kivy, Xamarin.Forms y React Native, escribiendo la misma aplicación en ellos, lo acompañan con el artículo correspondiente sobre Habré, activa GitHub y te dice honestamente quién enfrentó las dificultades durante la implementación. Después de reunirnos en el Telegram y haber discutido los detalles, nos pusimos a trabajar.

Para esta comparación, decidimos escribir un programador de tareas simple con tres pantallas. Hacer un corte del estado de estas tres plataformas hoy, usando el ejemplo de algo más voluminoso que el ejemplo que hemos elegido, porque todos están ocupados en sus proyectos / en el trabajo / en casa, lleva demasiado tiempo. A pesar de la simplicidad de nuestra aplicación, le permitirá demostrar claramente los principios del desarrollo de aplicaciones en cada entorno, trabajar con datos, IU, etc.

Tres marcos: un experimento. Xamarin.Forms. Parte 2
Tres marcos: un experimento. Reaccionar nativo. Parte 3

Este artículo es el primero en el ciclo, por lo que quiero comenzar con los ToR, que esbozamos para nosotros, para que el resultado sea similar.

Opción TK:


  • Las notas deben estar estructuradas por proyecto.
  • Las notas pueden ser agregadas por diferentes personas, por lo que se debe indicar el autor de la nota
  • Las notas dentro del proyecto se deben agregar / eliminar / editar.
  • Las notas deben ser del tamaño del contenido, pero no más de 150 píxeles.
  • La eliminación de notas debe realizarse tanto a través del menú contextual de la nota como a través de deslizar

Un ejemplo de interfaz de usuario debería verse así:



Antes de comenzar, un poco de ayuda en Kivy:
Kivy es un marco de gráficos multiplataforma escrito en el lenguaje de programación Python / Cython, basado en OpenGL ES 2, destinado a crear interfaces de usuario modernas, más enfocadas en trabajar con dispositivos táctiles. Las aplicaciones Kivy se ejecutan en plataformas como Linux, OS X, Windows, Android, iOS y Rapberry Pi. En desarrollo, tiene acceso a una amplia gama de bibliotecas de Python que van desde Solicitudes hasta NumPy y OpenCV. Kivy tiene acceso a casi todas las API móviles nativas (GPS, cámara, acelerómetro, API de Google para Android), a través de PyJNIus (Android) y PyOBJus (iOS), que envuelven automáticamente el código Java / Objective-C en Python .

Kivy es rápido. Esto se aplica tanto al desarrollo de la aplicación como a la velocidad de ejecución de la aplicación. Todas las funciones críticas se implementan en el nivel C. Kivy también usa la GPU donde sea que tenga sentido. La GPU hace la mayor parte del trabajo, aumentando considerablemente el rendimiento.

Kivy es muy flexible. Esto significa que el rápido desarrollo de Kivy le permite adaptarse instantáneamente a las nuevas tecnologías. Los desarrolladores de Kivy han agregado repetidamente soporte para nuevos dispositivos externos y protocolos de software, a veces incluso antes de su lanzamiento. Kivy se puede usar junto con muchas soluciones de terceros diferentes. Por ejemplo, en Windows, Kivy admite WM_TOUCH, lo que significa que cualquier dispositivo con controladores Windows 7 Pen & Touch funcionará con Kivy. En OS X, puede usar dispositivos Apple con soporte Multi-Touch, como trackpads y mouse. En Linux, puede usar eventos de entrada de entrada HID. Además, Kivy admite TUIO (objetos tangibles de interfaz de usuario) y una serie de otras fuentes de entrada.

Puede escribir una aplicación simple con unas pocas líneas de código. Los programas Kivy se crean utilizando el lenguaje de programación Python, que es increíblemente versátil y potente, pero fácil de usar. Además, los desarrolladores de Kivy han creado su propio lenguaje de marcado GUI para crear sofisticadas GUI personalizadas. Este lenguaje le permite configurar, conectar y organizar rápidamente los elementos de la aplicación.

Y sí, Kivy es completamente gratis. ¡Puedes usarlo en todas partes! En un producto comercial o en Código Abierto.

Daré todo el código de la aplicación y mostraré con suficiente detalle cómo se implementan estos o esos elementos cuando se desarrollen para plataformas móviles. Como IDE, siempre uso PyCharm , que admite perfectamente la sintaxis del lenguaje Kv , un lenguaje DSL especial en el que se escribe la representación de la interfaz de usuario de su aplicación. El esqueleto de la aplicación se creó con la utilidad de consola CreatorKivyProject , que proporciona pantallas básicas con la plantilla MVVM.


La carpeta baseclass contiene la lógica de widgets y controles implementados en el lenguaje de programación Python, en kv - archivos de descripción de interfaz en el lenguaje Kv . El directorio applibs se utiliza para bibliotecas de terceros, en la carpeta de datos hay contenido multimedia, bases de datos y otros datos. El archivo main.py es el punto de entrada de la aplicación. Él no hace nada más que iniciar la UI TodoList (). Ejecutar () render, detectar un error si ocurre y mostrar una ventana para enviar un informe de error, creado automáticamente por la utilidad CreatorKivyProject , no tiene nada que ver con escribir nuestra aplicación, y por lo tanto no se considera.

El archivo todolist.py con el código del programa implementa la clase TodoList , que carga los diseños de la interfaz, inicializa sus instancias, monitorea los eventos de las teclas físicas del dispositivo y devuelve nuestra primera pantalla, que se enumera en el Administrador de actividades. Después de TodoList (). Run () , se llama a la función de compilación y devuelve el widget que se mostrará en la pantalla.

Por ejemplo, el código para un programa simple que muestra una sola pantalla con una imagen se verá así:


Y aquí está el diagrama de nuestra clase de aplicación:


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 


Nuestra aplicación consta de solo tres actividades , el administrador de pantalla ( ScreenMenager ), que volvimos a las funciones de compilación , es responsable de cambiar :

 #: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 

Cuando se inicia la aplicación, se instalará primero la Actividad que se especifica en el ActivityManager. En nuestro caso, es ListProjectsActivity . En la aplicación para listas de proyectos y tareas, utilicé ScrollView . Aunque fue más correcto: RecycleView . Porque el primero, si hay más de cien publicaciones y proyectos, no puede hacerlo. Más precisamente, tomará mucho tiempo renderizar listas. RecycleView le permite mostrar listas de cualquier longitud casi al instante. Pero dado que, en cualquier caso, con listas grandes, tendría que usar la carga de datos dinámicos en una lista o paginación, pero esto no se discutió en los TOR, utilicé ScrollView . La segunda razón es que era demasiado vago para rehacer las listas en RecycleView (y es fundamentalmente diferente en uso de ScrollView ), y no hubo mucho tiempo, porque toda la aplicación se escribió en cuatro horas en pausas para fumar y pausas para el café.

La pantalla de inicio con una lista de proyectos (ListProjectsActivity.kv y ListProjectsActivity.py) se ve así:


Dado que el diseño de la pantalla ListProjectsActivity ya se muestra en la pantalla, mostraré cómo se ve su clase de control:

 # -*- 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() 

Llamada al cuadro de diálogo:


En el trabajo, llamar a la ventana y crear un nuevo proyecto se verá así:

No me detendré en la pregunta sobre los datos de la aplicación, porque los datos son un diccionario regular del formulario

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

y que se almacena en el directorio de datos como un simple archivo json.

Veamos cuál es el elemento con el nombre del proyecto y cómo usar Kivy para eliminar un elemento de la lista deslizando el dedo. Para hacer esto, debemos heredar el comportamiento del widget en la lista de la clase SwipeBehavior de la biblioteca 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) 

Y la descripción del elemento del proyecto en el marcado 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 general, cada widget en Kivy tiene un método on_touch con el que puede capturar cualquier evento que ocurra en la pantalla. Aquí hay una pequeña parte de la lista de eventos 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'] 


Implementando el menú contextual para Android ...

Tampoco hubo problemas aquí, ya que este es solo un widget DropDown estándar. Gracias al hecho de que puede personalizar todos los widgets y controles en Kivy tanto como lo permita su imaginación, obtuve fácilmente un bonito menú. A la izquierda está la base DropDown, a la derecha está la mía:

Diseño de la lista del menú contextual:

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 parte del software del menú contextual:

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) 

A continuación, importamos el botón MenuDropDown de la biblioteca animdropdown , le pasamos el objeto de nuestro menú contextual como parámetro, y luego agregamos este botón a la pantalla que necesitamos. En nuestra aplicación, este es el botón a la derecha en la tarjeta de notas:


Notas de la tarjeta de actividad de marcado:


Clase 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 


Implementación de software 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) 

¿Cómo gestionar la actividad de la aplicación? Para cambiar de una Actividad a otra, debemos indicar al administrador de pantalla el nombre de la nueva Actividad:

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

... donde 'agregar nueva actividad de nota' es el nombre de la Actividad para agregar una nueva nota.

Pantalla y diseño de la actividad AddNewNoteActivity :


Clase 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 

Para animar el botón, utilicé el evento on_enter , que se genera cuando la Actividad se instala en la pantalla:

En el marcado:

 <AddNewNoteActivity> on_enter: root.animationButton() 

En código Python:

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


A diferencia de Xamarin.Forms, la interfaz de usuario en Kivy se verá igual en todas partes. Por lo tanto, si está escribiendo una aplicación para dos plataformas (Android e iOS), debe tener esto en cuenta al marcar la interfaz y especificar las propiedades de los widgets. O haga dos marcas para dos plataformas (la lógica permanece sin cambios). Esto es una ventaja, ya que la representación y los eventos de la interfaz de usuario son independientes de las características de la plataforma, no utiliza API nativas para controlar estas acciones, lo que permite que su aplicación se ejecute sin problemas en casi cualquier plataforma. Todos los gráficos se representan utilizando llamadas nativas de OpenGL y SDL2 en la GPU, lo que le permite dibujar rápidamente menús, botones y otros encantos de la interfaz gráfica, incluidos gráficos 2D y 3D.

Esta aplicación utiliza la interfaz de usuario de Android MaterialDesign. Por ejemplo, mi último proyecto tenía una interfaz adaptativa:



Aquí hay una demostración de las posibilidades en el estilo de Diseño de materiales:



Como dije, Kivy no usa API nativas para renderizar la interfaz de usuario, por lo tanto, le permite emular varios modelos de dispositivos y plataformas utilizando el módulo de pantalla . Es suficiente ejecutar su proyecto con los parámetros necesarios para que la ventana de la aplicación probada se abra en la computadora como si se estuviera ejecutando en un dispositivo real. Suena extraño, pero dado que Kivy extrae de la plataforma al procesar la interfaz de usuario, esto elimina la necesidad de emuladores pesados ​​y lentos para las pruebas. Esto solo se aplica a la interfaz de usuario. Por ejemplo, la aplicación de prueba descrita en este artículo se probó con los parámetros -m screen: droid2, portrait, scale = .75 that one to one corresponde a mi dispositivo real.

Lista completa de parámetros del módulo de pantalla:
 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() } 


¿Qué se puede decir en conclusión? ¿Kivy es bueno? Sin duda bueno! Si conoce el maravilloso lenguaje de programación Python, puede crear fácilmente aplicaciones para plataformas móviles (y no solo) con el marco no menos maravilloso de Kivy.

Ventajas de desarrollar aplicaciones usando el framework Kivy:

  • Como estamos tratando con Python, la velocidad de desarrollo de las aplicaciones es varias veces más rápida que la velocidad de desarrollo en cualquier otro lenguaje o marco de programación.
  • Megatones de bibliotecas Python listas para usar que puede usar en sus proyectos: OpenCV, Django, Flask, NumPy, ffmpeg, sqlite3, lxml y miles de otras.
  • Dado que Kivy usa OpenGL y GPU para renderizar gráficos, así como sus propios widgets y controles, la velocidad de renderización de la interfaz de usuario es muy alta y está completamente aliviado del dolor de cabeza, que está presente en otros marcos que necesitan ingresar a la parte nativa para implementar algunas partes de la interfaz.
  • Utiliza el nativo solo cuando necesita acceso a funciones específicas de la plataforma que simplemente no pueden existir en un marco verdaderamente multiplataforma: por ejemplo, acceso a geolocalización, acceso a la cámara, tecnología BlueTooth ...

    Implementando acceso a la API nativa de Android para obtener IMEI y modelo de dispositivo usando 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()) 


Por ejemplo, una implementación de dispositivos IMEI receptores nativos 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; } } 

  • Puede usar bibliotecas jar de terceros en sus proyectos cuando se trata de Android.
  • Usted es completamente propietario de todos los eventos que ocurren en la pantalla: toque, multitáctil, deslizar, golpear y otros eventos sin ir al nativo, por lo que es una parte integral de Kivy.

Características de Kivy en dispositivos táctiles:





A pesar de todas las ventajas, Kivy tiene varias desventajas:

  • La velocidad del "arranque en frío", es decir, el primer lanzamiento de la aplicación desde el momento en que se implementan todas las bibliotecas, es bastante larga. Los siguientes son ordinarios, pero más largos que los nativos, dependiendo de la carga del procesador del dispositivo móvil.
  • Trabaja con listas. Puede mostrar una lista con un tamaño de 100,000 artículos en medio segundo (por ejemplo, tarjetas de usuario, escaparate, citas), pero con una condición: todas las tarjetas deben tener la misma altura. Si muestra una lista de, por ejemplo, citas, con una cantidad desconocida de texto por adelantado, pero en su totalidad, en un momento dado no se pueden mostrar más de diez puntos, ya que esto tomará entre 10 y 15 segundos. En este caso, tendrá que cargar 10-15 elementos cada uno mientras se desplaza por la lista.
  • Es imposible mostrar texto que exceda los 6500 caracteres (3.5 páginas de texto impreso): obtenemos una pantalla en negro. Esto se resuelve rompiendo el texto y luego pegándolo, lo que todavía parece ser una muleta. Sin embargo, no está claro a quién se le ocurriría enviar una cantidad de texto a la vez. Especialmente cuando se trata de plataformas móviles.

Más artículos sobre Kivy

Una máquina virtual (la primera publicación de ZenCODE) de los desarrolladores de Kivy está lista y configurada para construir proyectos para ambas ramas de Python.

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


All Articles