程式碼github地址:github.com/koudle/GDG_…
前面一篇文章Flutter實戰1 — 寫一個天氣查詢的APP ,實現了一個顯示城市、溫度、天氣、溼度的介面,但是這個介面只有一個顯示的功能,沒有任何可互動的地方,本篇文章繼續完善查詢天氣的APP的功能。
增加兩個功能:
- 新增一個城市選擇的頁面
- 在城市選擇頁面,點選城市,跳轉到對應城市天氣的頁面
1. 建立城市選擇頁面
在Android中新建一個頁面,需要用Activity,在iOS中需要用ViewController,但在Flutter中,新建一個頁面只需要用Widge就行,所以我們新建一個CityWidget.dart
,CityWidget
是一個ListView,從伺服器拉取城市的列表並顯示,我們用CityData.dart
來儲存城市的資料。程式碼如下:
- CityData.dart
class CityData{
String cityName;
CityData(this.cityName);
}
複製程式碼
- CityWidget.dart
CityWidget是一個StatefulWidget,因為CityWidget裡的資料是從伺服器上拉的,是變的,所以需要用StatefulWidget來實現,從伺服器拉取資料的程式碼和Flutter實戰1 — 寫一個天氣查詢的APP裡的WeatherWidget
一樣,不同的是:
- CityWidget是一個List,用
ListView.builder
實現,需要填兩個引數itemCount
(List資料的個數)和itemBuilder
(List中item的view),在itemBuilder
中有index
的引數,可以直接從data中去到資料 - 為了讓List的item響應點選事件,在List的item外面包了一層
GestureDetector
,GestureDetector
也是一個Widget,因為在Flutter裡處理點選事件的也是一個Widget,所以你想讓你的Widget處理事件,必須得包一層處理事件的Widget,在Widget裡的onTap
處理點選事件
import `dart:convert`;
import `package:flutter/material.dart`;
import `package:gdg_weather/page/city/CityData.dart`;
import `package:gdg_weather/page/weather/WeatherWidget.dart`;
import `package:http/http.dart` as http;
class CityWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return CityState();
}
}
class CityState extends State<CityWidget>{
List<CityData> cityList = new List<CityData>();
CityState(){
_getCityList();
}
void _getCityList() async{
List<CityData> citys = await _fetchCityList();
setState(() {
cityList = citys;
});
}
//拉取城市列表
Future<List<CityData>> _fetchCityList() async{
final response = await http.get(`https://search.heweather.net/top?group=cn&key=ebb698e9bb6844199e6fd23cbb9a77c5`);
List<CityData> cityList = new List<CityData>();
if(response.statusCode == 200){
//解析資料
Map<String,dynamic> result = json.decode(response.body);
for(dynamic data in result[`HeWeather6`][0][`basic`]){
CityData cityData = CityData(data[`location`]);
cityList.add(cityData);
}
return cityList;
}else{
return cityList;
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return ListView.builder(
itemCount: cityList.length,
itemBuilder: (context,index){
return ListTile(
title: GestureDetector(
child: Text(cityList[index].cityName),
onTap:(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WeatherWidget(cityList[index].cityName))
);
},
),
);
});
}
}
複製程式碼
2.路由
要開啟一個頁面,Android中是先初始化Intent
,然後呼叫startActivity()
;在iOS中是先初始化ViewController
,然後呼叫pushViewController
;在web裡,是呼叫一個跳轉連結。
那麼在Dart中如何從一個頁面跳轉到另一個頁面呢?
答案就是 路由
!
路由有多種實現,這裡給出一個:
- 開啟一個頁面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WeatherWidget(cityList[index].cityName))
);
複製程式碼
- 返回
Navigator.pop(context);
複製程式碼
3.WeatheWidget
天氣頁面需要知道上個頁面點選的是哪個城市,所以將城市當做WeaterWidget
的構造引數傳過來。
4.頁面調整
因為我們想第一個開啟的頁面是城市列表,點選城市列表後,跳轉到天氣頁面,所以調整一下main.dart
裡面的程式碼,將WeatherWidget
改為CityWidget
:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: `Flutter Demo`,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: CityWidget(),
),
);
}
}
複製程式碼
5.程式碼目錄跳轉
其實到前面一步,功能已經實現,但是因為現在已經有很多類了,現在目錄結構太混亂了,調整一下,如下: