好久沒(méi)在簡(jiǎn)書(shū)寫(xiě)東西了失尖,基本上自己的筆記都寫(xiě)在印象上去了妹窖。這次分享flutter呢纬朝,是記錄一下自己用flutter做的第一個(gè)app. 首先這個(gè)app沒(méi)有flutter的知識(shí)講解,只是簡(jiǎn)單的記錄一下自己這個(gè)app完成的過(guò)程骄呼。 推薦大家學(xué)習(xí)flutter可以去 技術(shù)胖學(xué)習(xí)共苛。
項(xiàng)目git地址:flower_gift
app框架搭建 - 2019-07-26
app首頁(yè):
1.創(chuàng)建app
2.創(chuàng)建app開(kāi)發(fā)相關(guān)文件夾
lib文件夾下創(chuàng)建:
config :基本配置文件,如url地址等
model :數(shù)據(jù)模型
pages :界面文件
provide :數(shù)據(jù)交互
routers :路由文件
service :網(wǎng)絡(luò)請(qǐng)求方法
- tabBar文件編寫(xiě):
import "package:flutter/material.dart";
import 'package:flutter/cupertino.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';//界面適配插件
import './home_page.dart';
import './category_page.dart';
import './flower_find_page.dart';
import './car_shop_page.dart';
import './mine_page.dart';
import 'package:provide/provide.dart'; //數(shù)據(jù)交互插件
import '../provide/tabBarTap_provide.dart'; //tabBar Provide文件
class TabBarPage extends StatelessWidget {
//tabBar子界面
final List<BottomNavigationBarItem> bottomTabs = [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
title: Text("首頁(yè)")
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.collections),
title: Text("分類(lèi)")
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.share),
title: Text("花現(xiàn)")
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.shopping_cart),
title: Text("購(gòu)物車(chē)")
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.profile_circled),
title: Text("我的")
),
];
//對(duì)應(yīng)的tabBar子頁(yè)面
final List<Widget> tabBarSubPages = [
HomePage(),
CategoryPage(),
FlowerFindPage(),
CarShopPage(),
MinePage()
];
@override
Widget build(BuildContext context) {
//界面適配
ScreenUtil.instance = ScreenUtil(width: 750.0,height: 1334.0)..init(context);//給定初始尺寸蜓萄,也就是基本尺寸隅茎,其余的都在此基礎(chǔ)上縮放
return Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: Provide<TabBarTapProvide>(
builder: (context,child,tabBarTap){
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: tabBarTap.currentTabIndex,
fixedColor: Color.fromRGBO(255, 95, 63, 1.0),
items: bottomTabs,
onTap: (index){
Provide.value<TabBarTapProvide>(context).bottomTabBarTap(index);
},
);
},
),
body: Provide<TabBarTapProvide>(
builder: (context,child,tabBarTap){
return IndexedStack(
index: tabBarTap.currentTabIndex,
children: tabBarSubPages,
);
},
)
);
}
}
tabBar Provide 文件:
import 'package:flutter/widgets.dart';
class TabBarTapProvide with ChangeNotifier{
int currentTabIndex = 0;
bottomTabBarTap(tapIndex){
currentTabIndex = tapIndex;
//通知
notifyListeners();
}
}
通過(guò)provide來(lái)控制這個(gè)數(shù)據(jù)的變化,從而控制界面變化嫉沽。尤其是在完全不相關(guān)的多個(gè)widget之間的數(shù)據(jù)交互辟犀。 除了編寫(xiě)對(duì)應(yīng)的provide文件外,還需要在main.dart中注冊(cè)绸硕。 用provide控制數(shù)據(jù)變化堂竟,比用StatefulWidget狀態(tài)組件要方便得多
- 首頁(yè):
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';//iOS風(fēng)格UI
import './pages/tabBar_page.dart';
import 'package:provide/provide.dart';//狀態(tài)管理
import './provide/tabBarTap_provide.dart';//底部tab點(diǎn)擊狀態(tài)管理
void main() {
var providers = Providers();
var tabBarTapProvide = TabBarTapProvide();
//狀態(tài)管理注冊(cè)
providers
..provide(Provider<TabBarTapProvide>.value(tabBarTapProvide));
runApp(
ProviderNode(
child: MyApp(),
providers: providers,
)
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Container(
child: MaterialApp(
title: "花禮網(wǎng)",
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color.fromRGBO(45, 60, 49, 1.0),//主題色
),
home: TabBarPage(),
),
);
}
}
首頁(yè)主要就看看這個(gè)provide注冊(cè)
5.各個(gè)子界面:
5.1: homePage.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../service/service_http_method.dart';
import 'dart:convert';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
_getHomePageData();
return Scaffold(
appBar: AppBar(
title: Text("花禮網(wǎng)",
style: TextStyle(
color: Color.fromRGBO(255, 95, 63, 1.0),
fontSize: ScreenUtil().setSp(45.0)
),
),
),
body:Container(
child: Center(
child: Text("我是首頁(yè)"),
),
)
);
}
void _getHomePageData(){
requestGet("shouye").then((val){
var data = json.decode(val.toString());
print("獲取首頁(yè)數(shù)據(jù)成功:${data}");
});
}
}
給homePage頁(yè)面加上了導(dǎo)航欄,其次進(jìn)行了首頁(yè)數(shù)據(jù)請(qǐng)求的測(cè)試玻佩。
5.2: category.dart
import 'package:flutter/material.dart';
class CategoryPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("我是分類(lèi)"),
),
);
}
}
其它三個(gè)界面只是標(biāo)題不一樣出嘹。
6.網(wǎng)絡(luò)請(qǐng)求配置:
config/service_url_config.dart
const baseServiceUrl = "https://fbz.dbhome.com/";(不是真實(shí)接口地址,怕放上來(lái)侵權(quán),也不懂咬崔。疚漆。。)
const requestUrl = {
"shouye":baseServiceUrl + "shouye/v3",//首頁(yè)數(shù)據(jù)請(qǐng)求
"itemList":baseServiceUrl + "itemlist/list",//分類(lèi)頁(yè)面
};
service/service_http_method.dart
import 'package:dio/dio.dart';
import 'dart:async';
import 'dart:io';
import '../config/service_url_config.dart';
//抽取公共的網(wǎng)絡(luò)請(qǐng)求方法
Future requestGet(url,{formData}) async{
try{
print("開(kāi)始獲取網(wǎng)絡(luò)數(shù)據(jù)...");
Response response;
Dio dio = new Dio();
dio.options.responseType = ResponseType.plain;//不整這個(gè)就會(huì)報(bào)Unexpected character錯(cuò)誤
dio.options.contentType = ContentType.parse("application/x-www-form-urlencoded");
if(formData == null){
//無(wú)參
response = await dio.post(requestUrl[url]);
}else{
response = await dio.post(requestUrl[url],data:formData);
}
if(response.statusCode == 200){
return response.data;
}else{
throw Exception("<<<<<<請(qǐng)求失敗,檢查接口或者參數(shù)>>>>>>");
}
}catch(e){
return print("HTTPERROR: ============> ${e}");
}
}
最后R 加載,數(shù)據(jù)請(qǐng)求成功,最后效果: