Простые сладкие приложения с Kivy


    После неудачной попытки первой версии статьи, когда материал заминусовали из-за чудовищного дизайна приведенного в статье примера программы (статью пришлось удалить), я учел все минусы и привожу более поздний вариант тестового приложения.


    Возможно, для вас будет новостью, но разрабатывать мобильные приложения с функционалом, который доступен Java разработчикам, под Android с помощью фреймворка Kivy не просто просто, а очень просто! Именно этого правила я придерживаюсь, создавая свои проекты с Python + Kivy — разработка должна быть максимально простой и быстрой. Как щелчок пальцами.


    На новичков подаваемая информация не расчитана, я не буду на пальцах объяснять, что, откуда и куда. Думаю, те, кто читает данную статью, обладают достаточными для понимания материала, знаниями. К тому же, Kivy, как я уже только что написал, очень простой фреймворк и вся документация с примерами использования находится в исходниках!


    В прошлой статье были рассмотрены несколько экранов приложения Clean Master в реализации на Kivy. Сегодня я покажу вам один из черновиков приложения, над которым работаю в свободное время.



    Говорят, что Kivy годится только лишь для наколенных поделок и серьезное приложение сделать с его помощью не получится. Спешу вас обрадовать (или огорчить) — так говорят те, кто не умеет данный фрукт (Kivy) готовить.


    А мы умеем и нам понадобятся: кофе-сигареты, террариум с третьим Python-ом, то ли птица, то ли фрукт — Kivy и немного мозгов. Наличие последних приветствуется! Заходим на github и качаем Мастер создания нового проекта для фреймворка Kivy + Python3 (да, я полностью отказался от использования Python2, что и вам советую). Распаковываем, переходим в папку с мастером и запускаем:


    python3 main.py name_project path_to_project -repo repo_project_on_github

    если у проекта имеется репозиторий на github.


    Или


    python3 main.py name_project path_to_project

    если репозитория не github не имеется.


    В этом случае после создания откройте файл проекта main.py и отредактируйте, функцию отправки баг репорта вручную.



    Итак, в результате мы получаем дефолтный Kivy проект со следующей структурой каталогов:



    Отдельно следует рассмотреть каталог Libs:



    Остальные каталоги проекта в комментариях не нуждаются. Созданный проект будет иметь два экрана — главный и экран настроек:



    Все что нам нужно, это использовать свой главный экран, то есть заменить файл startscreen.py в директории Libs/uix, создать новый файл разметки экрана startscreen.kv в папке Libs/uix/kv, отредактировать базовый класс program.py, ну, и добавить новые импорты и сопутствующие классы, если таковые имеются.


    Давайте начнем с кастомных кнопкок, которые используются в нашем главном экране:



    Да, в самом Kivy нет многих стандартных элементов для построения дизайна интерфейса, которые есть в Java, но зато Kivy позволяет сконструировать и анимировать абсолютно любой виджет, который вам понадобиться самостоятельно. Все зависит от границ вашей фантазии.


    Создадим в директории Libs/uix файл custombutton.py и определим в нем класс нашей кнопки:


    custombutton.py
    import os
    
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button
    from kivy.lang import Builder
    from kivy.properties import StringProperty, ObjectProperty, ListProperty
    
    from . imagebutton import ImageButton
    
    root = os.path.split(__file__)[0]
    Builder.load_file('{}/kv/custombutton.kv'.format(
        root if root != '' else os.getcwd())
    )
    
    class CustomButton(BoxLayout, Button):
        icon = StringProperty('')
        icon_map = StringProperty('')
        icon_people = StringProperty('')
        text = StringProperty('')
        button_color = ListProperty([0, 0, 0, .2])
        text_color = ListProperty([0, 0, 0, .1])
        events_callback = ObjectProperty(None)

    Разметка кнопки в директории Libs/uix/kv — файл custombutton.kv:


    custombutton.kv
    #:kivy 1.9.1 
    
    <CustomButton>: 
        id: root.text 
        padding: 5 
        size_hint_y: None 
        height: 60 
        on_release: root.events_callback(root.text) 
    
        canvas: 
            # Цвет кнопки 
            Color: 
                rgba: root.button_color 
            Rectangle: 
                pos: self.x + 2.5, self.y - 3 
                size: self.size 
            # Тень кнопки 
            Color: 
                rgba: [1, 1, 1, 1] 
            Rectangle: 
                pos: self.pos 
                size: self.size 
    
        Image: 
            source: root.icon 
            size_hint: .2, 1 
        Label: 
            markup: True 
            text: root.text 
            text_size: self.width - 70, None 
            color: root.text_color 
    
        BoxLayout: 
            orientation: 'vertical' 
            size_hint: .1, 1 
            spacing: 6 
            ImageButton: 
                source: root.icon_people 
                on_release: root.events_callback({'people': root.text}) 
            ImageButton: 
                source: root.icon_map 
                on_release: root.events_callback({'map': root.text})

    Кастомная кнопка для экрана локаций:



    custommenu.py
    import os 
    
    from kivy.uix.boxlayout import BoxLayout 
    from kivy.lang import Builder 
    from kivy.properties import ListProperty, StringProperty, ObjectProperty 
    
    root = os.path.split(__file__)[0] 
    Builder.load_file('{}/kv/custommenu.kv'.format( 
        root if root != '' else os.getcwd()) 
    ) 
    
    class CustomMenuItem(BoxLayout): 
        background_item = ListProperty([.1, .1, .1, 1]) 
        text_color = ListProperty([.1, .1, .1, 1]) 
        icon_item = StringProperty('') 
        text_item = StringProperty('') 
        id_item = StringProperty('') 
        events_callback = ObjectProperty(None)

    custommenu.kv
    #:kivy 1.9.1 
    #:import ImageButton Libs.uix.imagebutton.ImageButton 
    
    <CustomMenuItem>: 
        orientation: 'vertical' 
        canvas: 
            Color: 
                rgba: root.background_item 
            Rectangle: 
                pos: self.pos 
                size: self.size 
    
        ImageButton: 
            source: root.icon_item 
            on_release: root.events_callback(root.id_item.split('.')[0]) 
        Label: 
            text: root.text_item 
            color: root.text_color 
            font_size: '19sp'

    Также мы будем использовать класс ImageButton — кнопку с изображением — для баннеров. Поскольку класс относится к UI, я поместил файл imagebutton.py в каталог Libs/uix:


    imagebutton.py
    from kivy.uix.image import Image
    from kivy.uix.behaviors import ButtonBehavior
    
    class ImageButton(ButtonBehavior, Image):
        pass

    Далее нам потребуется класс для смены рекламных баннеров на главном экране программы. Для данного тестого примера приложения плакаты с рекламными баннерами помещены в локальную папку проекта. Создадим файл show_banners.py в директории классов приложения Libs/programclass:


    show_banners.py
    import os 
    
    from kivy.uix.boxlayout import BoxLayout 
    
    from Libs.uix.imagebutton import ImageButton 
    
    class ShowBanners(object): 
        '''Меняет и выводит на главном экране рекламные баннеры.''' 
    
        def __init__(self): 
            self.banner_list = os.listdir( 
                '{}/Data/Images/banners'.format(self.directory) 
            ) 
            # Направление смены слайдов баннеров. 
            self.directions = ('up', 'down', 'left', 'right') 
    
        def show_banners(self, interval): 
            if self.screen.ids.screen_manager.current == '': 
                name_banner = self.choice(self.banner_list) 
    
                box_banner = BoxLayout() 
                new_banner = ImageButton( 
                    id=name_banner.split('.')[0], 
                    source='Data/Images/banners/{}'.format(name_banner), 
                    on_release=self.press_banner 
                ) 
                box_banner.add_widget(new_banner) 
    
                name_screen = name_banner 
                banner = self.Screen(name=name_screen) 
                banner.add_widget(box_banner) 
                self.screen.ids.banner_manager.add_widget(banner) 
                effect = self.choice(self.effects_transition) 
                direction = self.choice(self.directions) 
                if effect != self.SwapTransition: 
                    self.screen.ids.banner_manager.transition = effect( 
                        direction=direction 
                    ) 
                else: 
                    self.screen.ids.banner_manager.transition = effect() 
                self.screen.ids.banner_manager.current = name_screen 
                self.screen.ids.banner_manager.screens.pop() 
    
        def press_banner(self, instance_banner): 
            if isinstance(instance_banner, str): 
                print(instance_banner) 
            else: 
                print(instance_banner.id)

    Данный класс просто меняет экраны с баннерами, устанавливая их в менеджере экранов banner_manager:



    Не забываем добавить импорт созданного класса в библиотеку классов programclass в файле инициализации:



    Набор шейдеров для анимаций смены афиш мы импортируем в базовом файле program.py:



    Реализация главного экрана приложения:


    startscreen.py
    import os 
    
    from kivy.uix.boxlayout import BoxLayout 
    from kivy.lang import Builder 
    from kivy.properties import ObjectProperty, ListProperty, StringProperty 
    
    from Libs.uix.custombutton import CustomButton 
    
    root = os.path.split(__file__)[0] 
    root = root if root != '' else os.getcwd()
    
    class StartScreen(BoxLayout): 
        events_callback = ObjectProperty(None) 
        '''Функция обработки сигналов экрана.''' 
    
        core = ObjectProperty(None) 
        '''module 'Libs.programdata' ''' 
    
        color_action_bar = ListProperty( 
            [0.4, 0.11764705882352941, 0.2901960784313726, 0.5607843137254902] 
        ) 
        '''Цвет ActionBar.''' 
    
        color_body_program = ListProperty( 
            [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] 
        ) 
        '''Цвет фона экранов программы.''' 
    
        color_tabbed_panel = ListProperty( 
            [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] 
        ) 
        '''Цвет фона tabbed panel.''' 
    
        title_previous = StringProperty('') 
        '''Заголовок ActionBar.''' 
    
        tabbed_text = StringProperty('') 
        '''Текст пунктов кастомной tabbed panel.''' 
    
        Builder.load_file('{}/kv/startscreen.kv'.format(root)) 
    
        def __init__(self, **kvargs): 
            super(StartScreen, self).__init__(**kvargs) 
            self.ids.custom_tabbed.bind(on_ref_press=self.events_callback) 
    
            # Cписок магазинов. 
            for name_shop in self.core.dict_shops.keys(): 
                self.ids.shops_list.add_widget( 
                    CustomButton( 
                        text=self.core.dict_shops[name_shop], 
                        icon='Data/Images/shops/{}.png'.format(name_shop), 
                        icon_people='Data/Images/people.png', 
                        icon_map='Data/Images/mapmarker.png', 
                        events_callback=self.events_callback, 
                    ) 
                )

    startscreen.kv
    #: kivy 1.9.1 
    #: import StiffScrollEffect Libs.uix.garden.stiffscroll.StiffScrollEffect 
    
    <StartScreen> 
        orientation: 'vertical' 
        canvas: 
            Color: 
                rgb: root.color_body_program 
            Rectangle: 
                pos: self.pos 
                size: self.size 
    
        ActionBar: 
            id: action_bar 
            canvas: 
                Color: 
                    rgb: root.color_action_bar 
                Rectangle: 
                    pos: self.pos 
                    size: self.size 
            ActionView: 
                id: action_view 
                ActionPrevious: 
                    id: action_previous 
                    app_icon: 'Data/Images/logo.png' 
                    title: root.title_previous 
                    with_previous: False 
                    on_release: root.events_callback('navigation_drawer') 
                ActionButton: 
                    icon: 'Data/Images/trash_empty.png' 
                ActionButton: 
                    icon: 'Data/Images/search.png' 
    
        Label: 
            id: custom_tabbed 
            text: root.tabbed_text 
            bold: True 
            markup: True 
            size_hint: 1, .35 
            text_size: self.width - 40, None 
            canvas.before: 
                Color: 
                    rgb: root.color_tabbed_panel 
                Rectangle: 
                    pos: self.pos 
                    size: self.size 
    
        ScreenManager: 
            id: screen_manager 
            size_hint: 1, 8 
            Screen: 
                ScreenManager: 
                    id: banner_manager 
                    size_hint: 1, .38 
                    pos_hint: {'top': 1} 
    
                ScrollView: 
                    effect_cls: StiffScrollEffect 
                    size_hint_y: None 
                    height: root.height // 1.8 
                    pos_hint: {'top': .62} 
                    GridLayout: 
                        id: shops_list 
                        cols: 1 
                        spacing: 5 
                        padding: 5 
                        size_hint_y: None 
                        height: self.minimum_height

    Как вы могли заметить, я не использую TabbedPanel, так как считаю ее стандартную реализацию в Android не слишком красивой. Она была заменена на Label + ref:




    Базовый класс Program:


    program.py
    import os 
    import sys 
    
    from random import choice 
    
    from kivy.app import App 
    from kivy.uix.screenmanager import Screen, SlideTransition, SwapTransition 
    from kivy.core.window import Window 
    from kivy.config import ConfigParser 
    from kivy.clock import Clock 
    from kivy.utils import get_hex_from_color, get_color_from_hex 
    from kivy.properties import ObjectProperty, NumericProperty 
    
    from Libs.uix.kdialog import KDialog, BDialog, Dialog 
    from Libs.uix.startscreen import StartScreen 
    from Libs.uix.custommenu import CustomMenuItem 
    from Libs.uix.navigationmenu import NavigationMenu 
    
    from Libs.uix.garden.navigationdrawer import NavigationDrawer 
    
    # Классы программы. 
    from Libs import programclass as prog_class 
    
    from Libs import programdata as core 
    from Libs.manifest import Manifest 
    
    # Графика для диалоговых окон. 
    Dialog.background_image_buttons = core.image_buttons 
    Dialog.background_image_shadows = core.image_shadows 
    Dialog.background = core.decorator 
    
    class Program(App, prog_class.ShowPlugin, prog_class.ShowBanners, 
                  prog_class.SearchShop, prog_class.ShowLicense, 
                  prog_class.ShowLocations): 
        '''Функционал программы.''' 
    
        start_screen = ObjectProperty(None) 
        ''':attr:`start_screen` is a :class:`~Libs.uix.startscreen.StartScreen`''' 
    
        screen = ObjectProperty(None) 
        ''':attr:`screen` is a :class:`~Libs.uix.startscreen.StartScreen`''' 
    
        window_text_size = NumericProperty(15) 
    
        def __init__(self, **kvargs): 
            super(Program, self).__init__(**kvargs) 
            Window.bind(on_keyboard=self.events_program) 
    
            # Для области видимомти в programclass. 
            self.Screen = Screen 
            self.Clock = Clock 
            self.CustomMenuItem = CustomMenuItem 
            self.KDialog = KDialog 
            self.BDialog = BDialog 
            self.Manifest = Manifest 
            self.SwapTransition = SwapTransition 
            self.choice = choice 
            self.get_color_from_hex = get_color_from_hex 
            self.get_hex_from_color = get_hex_from_color 
            self.core = core 
            self.name_program = core.string_lang_title 
            self.navigation_drawer = NavigationDrawer(side_panel_width=230) 
            self.current_open_tab = core.string_lang_tabbed_menu_shops 
            self.shop = False  # выбранный магазин 
            self.open_dialog = False  # открыто диалоговое окно 
    
            self.effects_transition = (SlideTransition, SwapTransition) 
            # Список магазинов. 
            self.shops = core.dict_shops.keys() 
            # Список локаций. 
            self.locations = [ 
                location.split('.')[0].lower() for location in os.listdir( 
                    '{}/Data/Images/locations'.format(core.prog_path))] 
    
        def build_config(self, config): 
            config.adddefaultsection('General') 
            config.setdefault('General', 'language', 'Русский') 
            config.setdefault('General', 'theme', 'default') 
    
        def build(self): 
            self.title = self.name_program  # заголовок окна программы 
            self.icon = 'Data/Images/logo.png'  # иконка окна программы 
            self.use_kivy_settings = False 
    
            self.config = ConfigParser() 
            self.config.read('{}/program.ini'.format(core.prog_path)) 
            self.set_var_from_file_settings() 
    
            # Главный экран программы. 
            self.start_screen = StartScreen( 
                color_action_bar=core.color_action_bar, 
                color_body_program=core.color_body_program, 
                color_tabbed_panel=core.color_tabbed_panel, 
                tabbed_text=core.string_lang_tabbed_menu.format( 
                    TEXT_SHOPS=core.string_lang_tabbed_menu_shops, 
                    TEXT_LOCATIONS=core.string_lang_tabbed_menu_locations, 
                    COLOR_TEXT_SHOPS=get_hex_from_color(core.color_action_bar), 
                    COLOR_TEXT_LOCATIONS=core.theme_text_color), 
                title_previous=self.name_program[1:], 
                events_callback=self.events_program, core=core 
            ) 
    
            self.screen = self.start_screen 
            navigation_panel = NavigationMenu( 
                events_callback=self.events_program, 
                items=core.dict_navigation_items 
            ) 
    
            Clock.schedule_interval(self.show_banners, 4) 
    
            self.navigation_drawer.add_widget(navigation_panel) 
            self.navigation_drawer.anim_type = 'slide_above_anim' 
            self.navigation_drawer.add_widget(self.start_screen) 
    
            return self.navigation_drawer 
    
        def set_var_from_file_settings(self): 
            '''Установка значений переменных из файла настроек program.ini.''' 
    
            self.language = core.select_locale[ 
                self.config.get('General', 'language') 
            ] 
    
        def set_current_item_tabbed_panel(self, color_current_tab, color_tab): 
            self.screen.ids.custom_tabbed.text = \ 
                core.string_lang_tabbed_menu.format( 
                    TEXT_SHOPS=core.string_lang_tabbed_menu_shops, 
                    TEXT_LOCATIONS=core.string_lang_tabbed_menu_locations, 
                    COLOR_TEXT_SHOPS=color_tab, 
                    COLOR_TEXT_LOCATIONS=color_current_tab 
                ) 
    
        def events_program(self, *args): 
            '''Обработка событий программы.''' 
    
            if self.navigation_drawer.state == 'open': 
                self.navigation_drawer.anim_to_state('closed') 
    
            if len(args) == 2:  # нажата ссылка 
                event = args[1] 
            else:  # нажата кнопка программы 
                try: 
                    _args = args[0] 
                    event = _args if isinstance(_args, str) else _args.id 
                except AttributeError:  # нажата кнопка девайса 
                    event = args[1] 
    
            if core.PY2: 
                if isinstance(event, unicode): 
                    event = event.encode('utf-8') 
    
            if event == core.string_lang_settings: 
                pass 
            elif event == core.string_lang_exit_key: 
                self.exit_program() 
            elif event == core.string_lang_license: 
                self.show_license() 
            elif event == core.string_lang_plugin: 
                self.show_plugins() 
            elif event in self.locations: 
                print(event) 
            elif event == 'search_shop': 
                self.search_shop() 
            elif event == 'navigation_drawer': 
                self.navigation_drawer.toggle_state() 
            elif event == core.string_lang_tabbed_menu_locations: 
                self.show_locations() 
            elif event == core.string_lang_tabbed_menu_shops: 
                self.back_screen(event) 
            elif event == 'obi_banner': 
                self.press_banner(event) 
            elif event in (1001, 27): 
                self.back_screen(event) 
            elif event in self.shops: 
                print(event) 
            return True 
    
        def back_screen(self, event): 
            '''Менеджер экранов.''' 
    
            # Нажата BackKey на главном экране. 
            if self.screen.ids.screen_manager.current == '': 
                if event in (1001, 27): 
                    self.exit_program() 
                return 
            if len(self.screen.ids.screen_manager.screens) != 1: 
                self.screen.ids.screen_manager.screens.pop() 
            self.screen.ids.screen_manager.current = \ 
                self.screen.ids.screen_manager.screen_names[-1] 
            # Устанавливаем имя предыдущего экрана. 
            #self.screen.ids.action_previous.title =  self.screen.ids.screen_manager.current 
            # Устанавливаем активный пункт в item_tabbed_panel. 
            self.set_current_item_tabbed_panel( 
                    core.theme_text_color, get_hex_from_color(core.color_action_bar) 
            ) 
    
        def exit_program(self, *args): 
            def dismiss(*args): 
                self.open_dialog = False 
    
            def answer_callback(answer): 
                if answer == core.string_lang_yes: 
                    sys.exit(0) 
                dismiss() 
    
            if not self.open_dialog: 
                KDialog(answer_callback=answer_callback, on_dismiss=dismiss, 
                        separator_color=core.separator_color, 
                        title_color=get_color_from_hex(core.theme_text_black_color), 
                        title=self.name_program).show( 
                    text=core.string_lang_exit.format(core.theme_text_black_color), 
                    text_button_ok=core.string_lang_yes, 
                    text_button_no=core.string_lang_no, param='query', 
                    auto_dismiss=True 
                ) 
                self.open_dialog = True 
    
        def on_pause(self): 
            '''Ставит приложение на 'паузу' при выхоже из него. 
            В противном случае запускает программу заново''' 
    
            return True 
    
        def on_resume(self): 
            print('on_resume') 
    
        def on_stop(self): 
            print('on_stop')

    Оставляя за бортом (не рассмотренными) файл локализации — Data/Language/russian.txt, расфасовку графических ресурсов, цветовую схему приложения в файле Data/Themes/default/default.ini, создание данных в programdata.py, меню Navigation Drawer — все это несложные мелочи, запускаем тестовый пример:


    python3 main.py

    … и получаем вот такую картинку:



    Ввиду плохого качества gif-ки, анимация экранов плохо просматривается, но это не столь важно. Те, кто будет тестировать пример из исходников проекта на девайсах, сразу выделят недочеты: я пока не реализовал алгоритм, по которому размеры рекламных баннеров будут подгоняться под все разрешения экранов без искажения пропорций; также, ввиду отсутствия возможности протестировать приложение хотя в эмуляторе не удалось найти оптимальный размер шрифта в программе, отсутствует анимация кнопок, хромает библиотека для работы с диалоговыми окнами kdialog, поскольку пока находится в разработке.


    Но не смотря на все это, думаю, эта статья станет полезной для тех, кто также, как и я, любит и использует такой замечательный фремворк, как Kivy!


    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 34

      –4
      Что только люди не придумают, лишь бы Java не изучать…

      Я вот всё равно не понимаю – какой в этом смысл? Изучать новый фреймворк, который всегда будет поддерживаться заведомо хуже, чем оригинальный, городить костыли. Только для того, чтобы писать на питоне, а не на джаве?

      Я еще могу как-то понять использование HTML + JS для очень простых промо-приложений, для которых достаточно, по сути, сверстать страничку и завернуть в apk, но какой смысл пихать питон в андроид?
        +4

        Расскажите это разработчикам Kivy и тысячам людей, которые его используют всместе c Python во всем мире!


        Что только люди не придумают, лишь бы Java не изучать…

        Вы видели у статьи метку? Или вы пытаетесь развести здесь бесполезный холивар?

          +3
          Мне кажется вы преувеличиваете необходимость Java, есть много девов которым лишний груз не нужен, и киви как раз решает эту проблему для питонистов. И, к слову, вы сильно недооцениваете html5 приложения.
          +1
          Расскажите откуда и как берутся эти значения:
          color_action_bar = ListProperty( 
                  [0.4, 0.11764705882352941, 0.2901960784313726, 0.5607843137254902] 
              ) 
              '''Цвет ActionBar.''' 
          
              color_body_program = ListProperty( 
                  [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] 
              ) 
              '''Цвет фона экранов программы.''' 
          
              color_tabbed_panel = ListProperty( 
                  [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] 
              ) 
          
            0

            Поскольку архитектура Kivy проектов предполагает модульность, эти параметры передаются при создании экземпляра используемого класса. К тому же, если я захочу, например, быстро протестировать новую цветовую схему, мне достаточно изменить значения переменных, которые отвечают за цвет приложения в файле Data/Themes/default.ini.


            А если вы о самом формате этих значений, то это обычное представление цвета в формате rgba, которое чаще всего используется в Kivy:


            >>> from kivy.utils import get_hex_from_color, get_color_from_hex
            >>> get_hex_from_color([0.4, 0.11764705882352941, 0.2901960784313726, 0.5607843137254902])
            >>> '#661e4a8f'
            
            >>> get_color_from_hex('#661e4a8f')
            >>> [0.4, 0.11764705882352941, 0.2901960784313726, 0.5607843137254902]
              +2
              Может добавить это в статью под спойлер.
                –1

                Я как-то не думал, что это может быть для кого-то большим вопросом.

            0
            В своё время пробовал kivi и мне понравилось. Скажите, а они как-то поборолись с неоправданно большим весом приложения на выходе?
              0

              И да и нет. Минимальная стандартная сборка — это 8-9 Мб. Но! При сборке можно указать, какие библиотеки и API не включать в проект. Таким образом размер сборки сокращается до 4 Мб.

                0
                тык как же это сделать то? где именно указывать надо?
                  0

                  Ищите в своем python-for-android файл blacklist.txt. В данный файл заносите все модули и библиотеки, которые НЕ НУЖНО влючать в сборку итогового apk.

                    0
                    Скинте пожалуйста Ваш blacklist.txt.
                      0

                      Один момент. Но учтите, что вручную вы ничего не добьетесь, потому что вы не знаете, какой модуль какую библиотеку потребует в процессе работы. Вам нужно создать полное дерево импортируемых и используемых вашим приложением модулей и библиотек, включая стандартные библиотеки. У меня есть подобная утилита, которая все это делает автоматически и записывает в blacklist все не нужное проекту. Но! Все это я готовил для очередной статьи и этот процесс требует тестов. Статья заброшена, утилита тоже, так лично для меня стало не важно весит ли мое приложение 4 Mb или 7Mb. Если хотите, могу поискать в загашниках...

                        0
                        Почему забросили статью? из-за минусов? ну так они потому что вещи которые вы так чательно разбирали — после разборки кажутся вам очевидными… И вы мало их освещаете в статьях. Но это не повод не писать ещё одну статью. например: вы предлагаете перейти на python3 но при этом не пишите как заставить buildozer (про который была прошлая статья) его использовать. Нужно просто составляя статью «пройти» ВЕСЬ путь в месте с читателем, и тогда будут только плюсы… (да-да, я намекаю что хочу увидеть именно это в следующей статье). И даже не рассчитывайте на мозги у читателя. Нет, читатель не туп. Просто он, читая статью, надеется что в ней будут все грабли собраны в одном месте. Но даже пара грабель — УЖЕ ценные знания.

                        > «могу поискать в загашниках.»
                        буду рад даже просто вашему последнему созданному blacklist.txt. (не тому что идёт в комплекте)
                          0

                          К сожалению, старые сборки в python-for-android, в которых я тестировал упомянутую утилиту, благополучно мною удалены как и сама утилита (возмножно, позже еще посмотрю в корзине). Но принцип я вам уже описал. Почему забросил статью? Конечно же, не из-за минусов, коих, к слову, по пальцам можно пересчитать. Работа, плюс был занят частным заказом на Kivy проект для RespberyPI. К тому же готовил новую статью для Хабра -"Kivy — еще проще! Еще нативнее!" (сегодня опубликую). И потом, я пользуюсь мобильным Интернет провайдером, поэтому у меня нет возможности скачать новый SDK для тестовых сборок проектов под Python3. Когда этот вопрос станет для меня вплотную, тогда и статья появится.

              0
              Очень интересно. Посматривал на React native. Теперь узнал что есть схожий проект на Python. Скажите, в теории, какой сложности приложение уже можно написать и есть ли примеры приложений в Play Market?
                0

                Посмотрите мои публикации — в одной из статей я рассматривал примеры нескольких экранов программы Clean Master…
                Насколько сложный проект можно реализовать с помощью Python и Kivy? Любой! Причем в пять раз дешевле и быстрее, чем аналогичный проект на Java! Единственное, что отталкивает разработчиков от Kivy — это невозможность свернуть и восстановить приложение из трея (это грубо — здесь есть свои нюансы), пиар (вот я пытаюсь, как могу, как-то популизировать данный фреймворк), ну и возможности — на самом деле Kivy может все, что может ЛЮБОЕ Java приложение! Скорость работы? Поскольку самые "тяжелые" части Kivy скомпилированы в C, скорость работы соответствующая. Плюс никто не запрещает вам использовать Cython для "тяжелой" математики в вашем проекте. Пробуйте, пишите, подскажем, ответим!

                0
                Можно ли сделать так чтобы приложение выглядело нативно под каждую платформу? Хотя бы под одну, стиль кнопок, меню и т.п.
                  0

                  Под конкретную — легко! Хоть под Windows 10!

                    0
                    Темы прикручивать как то?
                      0

                      Как один из вариантов.

                        0
                        Одна из причин почему я и не стал дальше в нем разбираться. Полезнее изучить другой язык, чем kivy imho.
                          0

                          Kivy это не язык — это фрейморк, написанный для разработки кроссплатформенных приложений на и для языка программирования Python.

                            0
                            Мысль была что полезнее выучить новый язык, чем kivy фреймворк. Язык python нравится, но чтобы на нем с помощью kivy писать приложения считаю, на данный момент, извращением. Но буду рад если что-то изменится :)
                  0
                  Различается ли скорость разработки Android приложения на Python с использованием Kivy и на Java? Много ли велосипедов и костылей приходится придумывать в процессе разработки на Kivy?
                    0
                    Различается ли скорость разработки Android приложения на Python с использованием Kivy и на Java?

                    Я не заметил.


                    Много ли велосипедов и костылей приходится придумывать в процессе разработки на Kivy?

                    Ну, не знаю, если считать, что костыль — это во-о-он та красивая кнопка, то, наверное, много… А так — все, что нужно уже есть непосредственно в Kivy.

                    0
                    строЙтельный… везде…
                    P.S. я не Grammar Nazi =)
                      0
                      Когда пробовал kivy столкнулся с несколькими проблемами. Отсутствие нормального сглаживания — все элементы постоянно покрываются лесенкой.
                      И очень медленная работа с большим количеством виджетов.
                      К примеру, хочу сделать календарь и добавляю 30 кнопок в grid_layout и это занимает 1-2 сек. А если не хочется зависания, то предлагают через очередь и дополнительный трэд это делать. Но тогда видно как один за одним элементы появляются
                      Так же с файловым менеджером. Открываешь его и ждешь 3-5 сек пока появятся иконки, потому что иконка файла состоит из 2-3 виджетов(сама картинка + label к ней) и выходит 10 файлов — 20 виджетов и лаг или погрузка 1 секунду. (А в любом другом файловом менеджере на Java 10 файлов я увижу мгновенно). И я проверял на папках, а не на изображениях, где нужно preview генерировать.

                      Может у вас есть решение?
                        0

                        Судя по всему, у вас кривая реализация вашего кода. Только что проверил — список из более чем пятидесяти элементов Button отрисовывается за 0.3 секунды. С "лесекой" не сталкивался. Файловый менеджер открывается мгновенно, о каких 3-5 секундах ожидания идет речь не имею понятия.

                          +1
                          Для всех кто задумался попробовать kivy очень рекомендую прочитать эту запись в блоге разработчика Kognitivo — одно из лучших приложений на kivy (которых в маркете не больше 10 и половина от автора kivy)
                          Вам, HeaTTheatR, советую сразу найти в статье пункт Mipmapping and antialising. И вы узнаете почему ваши приложения так сильно пиксилизованны. Если кому-то будет интересно насчет большого количества виджетов тут описано решение подобной проблемы.
                          Еще хочу сказать по поводу тем оформления. В kivy одна тема android 4. В сети вы найдете от силы еще две и они не самые красивые. То есть вам для каждого приложения придется самому пилить тему для каждого виджета.
                          Я очень люблю питон и тоже готов все, что угодно пилить на нем, но с kivy проблем у меня было больше чем удобства (но естественно всему виной «кривая реализация вашего кода»)
                            –1
                            ваши приложения так сильно пиксилизованны

                            О чем вы, ради бога!?


                            В kivy одна тема android 4. В сети вы найдете от силы еще две

                            То есть, не используя тем, вы считаете, что я не могу сделать в Kivy окно аналогичное модальному диалогу в Windows 10? Вы вообще имеете понятие о Kivy, Canvas и т. д.?


                            с kivy проблем у меня было больше чем удобства

                            У некоторых людей есть проблемы с включением стиральной машинки… Удачи...

                              –1
                              приложений на kivy в маркете не больше 10

                              Видимо, потому, что у людей, у которых "с kivy проблем больше чем удобства" — есть проблемы с включением стиральной машинки…

                          0
                          Ох, фреймворк прекрасный, но поддержка свежих версий питона там страдает. К примеру, 3.5 еще не поддерживается, и, судя по всему, поддерживаться будет не скоро ( связано это с компиляцией зависимостей, насколько я смог понять).
                            0

                            Kivy развивается постоянно. Поддержка Python 3.4 имеется, насчет 3.5, пока не знаю...

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое