接下来说说主界面的实现。主界面这一块大部分都是参考UnityConnect 这个app的源码来实现的(github地址https://github.com/UnityTech/ConnectAppCN),如果有需要的话可以自行下载。
在常见的app里面,大多数应用进去后的第一个界面其实就是主界面。如果主界面的列表需要登录权限的话,则在主界面列表加载前先判断是否已经有用户信息的cookie,如果无则跳转回登录界面。
这一块的判断直接在initState方法里面执行就可以了。flutter的stateful组件跟unity的类一样,都有自己的生命周期,基本常用的就是initState-初始化,build-绘制组件,dispose-组件销毁。其他的例如deactivate,didUpdateWidget这些方法可以自行参考flutter官方文档的说明。第一次进入主界面,我是在initState方法里面了获取PlayerPrefs的操作,因为unity的PlayerPrefs的特性,只要写入一次就能保存,退出应用后再次打开还能获取上一次写入的数据。实现代码如下:
if ("" == PlayerPrefs.GetString("account_session"))
{
Router.navigator.popAndPushNamed(MainNavigatorRoutes.UserLogin);
return;
}
这个account_session就是我的用户缓存数据,会在每次登录的时候把数据写进去。
当然cookie数据是有时效性的,这个只要发起数据请求时做判断,如果服务器返回获取超时或者无权限的话,就强行跳转到登录界面。
主界面列表我做得比较简单,只有一个列表,下拉松开自动 刷新界面,列表有文件夹与文件,文件夹可以点击进去查看子元素,右划或者点击返回按钮返回上一级,点击文件的话可以查看模型详情。
主界面的列表可以直接用ListView来实现,主要的实现代码实现如下:
return new Expanded(
flex: 1,
child: new Container(
color: Color.fromARGB(255, 248, 248, 248),
//width:Screen.width,
height: MediaQuery.of(context).size.height,
child: new CustomListView(//CustomListView是自定义的一个ListView组件
controller: _refreshController,//刷新监听控制器
enablePullDown: true,
enablePullUp: false,
onRefresh: GetProjectDataByCondition,
itemCount: projectDatas.Count,//当前列表的item数目
hasBottomMargin: true,
itemBuilder:
((Context, index) =>
{
//封装每个item的操作
return GetSceneItems(context, index);
}),
// headerWidget: CustomListViewConstant.defaultHeaderWidget,
footerWidget: new EndView(hasBottomMargin: true)
)
));
默认的列表界面可以看作是一个父文件夹,它的下面会有子文件夹与文件,当点击子文件夹时,会显示子文件夹下的孙文件夹与文件。所以打开文件夹这块逻辑其实可以用一个类来实现,每次点击文件夹时,直接在父文件夹界面上面再push出一个子界面,这样的话当返回上一页时可以直接调用navigator.pop()来销毁当前页。返回上一页可以通过点击界面来触发,也可以通过左划触发,左划返回上一页我是参考 UnityConnect来实现的,这里就不赘述了。
当点击文件夹创建一个PageRoute来push一个子界面时,要注意每个子界面都需要使用new MaterialApp()来作为界面的根节点,不然的话如果用Scaffold或者Container的话,界面的元素会显示错位或者触发一串连奇怪的显示bug。跳转界面的实现代码如下
if (model.is_dir == "1")//文件夹
{
StaticData.isInit = false;
var callBack = Router.navigator.push(new CustomPageRoute(
builder:buildContext=>
new MaterialApp(//根节点一定是MaterialApp
home: new Scaffold(
backgroundColor: Color.fromARGB(255, 248, 248, 248),
body:new MainListPage(model)))//MainListPage是主界面类,这里直接用来创建子文件夹界面
));
//callBack.Then((ob)=> { models = (ProjectListModels)ob; });
}
主界面的逻辑比较简单,大概就这样了:)