KivyMD做一个课程表App(下)


上篇博客记录了使用kivy开发安卓App,但是外观惨不忍睹。有幸在项目一开始就了解到了KivyMD,及时止损,重构项目。项目地址:https://github.com/tianqiraf/HfutCommunity

KivyMD

1.介绍

KivyMD是一个基于kivy的扩展包,包含与Google Material Design兼容的控件的集合,基于kivy框架开发。因此项目可以基于KivyMD,省去重新绘制UI的步骤。
项目地址:KivyMD
在demos文件夹下面有个kitchen_sink的demo,运行main.py可以查看效果

KivyMD Demo

可以打包之后在手机端运行,也可以在谷歌商店搜索KivyMD安装。安装包在此

KivyMD Demo安卓版

有没有感受到满满的Google风格。这个的demo包含了所有实现的KivyMD控件。

2.安装

  • 按照官方要求
    sudo python ./setup.py install
  • 也可以不安装,然后在项目中包含KivyMD-master\kivymd这个文件夹。等到打包的时候,其实还是需要在项目中包含此文件夹,否则会提示找不到模块

安装完成之后,开始重新编写HfutCommunity,基于KivyMD。

HfutCommunity

1.目录结构

项目结构我采用了和pydelhi相似的结构
目录结构

  • data中存放必要数据,如中文字体,课程安排,成绩和数据库等
  • pic文件夹存放图片
  • utils用于存放其它组件,暂无内容
  • uix文件下在hfutcommunityconf.py中实现ScreenManager有关的类,screens文件夹存放各个screen实现的代码
    screen概览

2.实现细节

1)screen调用

由于模仿了pydelhi的目录结构,因此这里借鉴了它调用不同screen的方式。

def load_screen(self, screen, manager=None, store_back=True, direction='left'):

    store_back = False if screen == 'StartupScreen' else store_back

    manager = manager or self.root
    # load screen modules dynamically
    # for example load_screen('LoginScreen')
    # will look for uix/screens/loginscreen
    # load LoginScreen
    module_path = screen.lower()
    if not hasattr(self, module_path):
        import imp
        module = imp.load_module(screen, *imp.find_module(module_path))
        print(module)
        screen_class = getattr(module, screen)
        print(screen_class)
        sc = screen_class()
        sc.from_back = not store_back
        setattr(self, module_path, sc)
        manager.add_widget(sc)

    else:
        sc = getattr(self, module_path)

    sc.from_back = not store_back
    manager = manager or self.root
    print(screen)
    # load screen modules dynamically
    # for example load_screen('LoginScreen') will look for uix/screens/loginscreen to load LoginScreen
    manager.transition.direction = direction
    manager.current = screen
    return getattr(self, module_path)

由于KivyMD控件种类有限,有些控件组合比较难以实现,因此修改对应控件的源码。

2)NavigationDrawerRightIconButton

比如邮箱一栏的控件组合
NavigationDrawerRightIconButton
使用的是NavigationDrawerRightIconButton这个类,修改自NavigationDrawerIconButton,并添加进navigationdrawer.py

3)MDScreenWidthFlatButton

比如星期和课表一栏的GridLayout
MDScreenWidthFlatButton
这里很久都没有想到哪一个控件能够担任此任务,最后用了Button来实现。由于需要横向铺满屏幕,只好自己编写新的Button类,即MDScreenWidthFlatButton,添加进button.py
GridLayout下,多个按钮会平均分摊屏幕宽度,形成网格状布局,并且单个方格可以作为按钮(本来就是-_-|)点击来查看课程详情。

4)MDDropdownMenu

由于KivyMD-Demo中的MDDropdownMenu的子控件是MDMenuItem,没有实现点击功能,而且按下的时候也没有反馈.因此添加类DotsMenuButton,继承自MDFlatButton

<DotsMenuButton@MDFlatButton>:
    on_release:
        app.load_screen(self.name + "Screen") if "My" in self.name else app.mainscreen.select_menu_item(self.name)
        self.parent.parent.parent.parent.dismiss() # Close the menu      

on_release表示按钮释放时执行的动作。然后就可以在MDDropdownMenu的子控件中使用DotsMenuButton来响应点击事件。

community_menu_items = [
    {"viewclass": "DotsMenuButton",
     "name": "MyConfe",
     "text": "我的表白"},
    {'viewclass': 'DotsMenuButton',
     "name": "MyComment",
     'text': '我的评论'},
    {'viewclass': 'DotsMenuButton',
     "name": "Refresh",
     'text': '刷新'}
]

点击菜单

3.难点

  • 目前kivy打包app对数据的支持不是很好,因此暂时使用json来存放课程的数据。
    巨大的json数据
  • 使用json后,由于获取课程的链接返回数据庞大,因此处理起来比较吃内存。在电脑上运行感觉不到,但是在手机上运行就会变得非常明显。运行一段时间后,缓存已经高达650MB,而且还在逐渐增加。
    运行测试

结语

鉴于高内存占用目前还未找到合适的解决办法,因此这个项目到此结束。欣慰的是,kivy水平已经脱离小白程度了。
项目放在github上,可自行下载查看。
打包的App点此下载。


文章作者: Tqraf
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Tqraf !
评论
  目录