上篇博客记录了使用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安装。安装包在此
有没有感受到满满的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实现的代码
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
这个类,修改自NavigationDrawerIconButton
,并添加进navigationdrawer.py
3)MDScreenWidthFlatButton
比如星期和课表一栏的GridLayout
这里很久都没有想到哪一个控件能够担任此任务,最后用了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后,由于获取课程的链接返回数据庞大,因此处理起来比较吃内存。在电脑上运行感觉不到,但是在手机上运行就会变得非常明显。运行一段时间后,缓存已经高达650MB,而且还在逐渐增加。
结语
鉴于高内存占用目前还未找到合适的解决办法,因此这个项目到此结束。欣慰的是,kivy水平已经脱离小白程度了。
项目放在github上,可自行下载查看。
打包的App点此下载。