天天看点

Flutter实战(二) 写一个天气查询的APP

前面一篇文章[Flutter实战1 写一个天气查询的APP]实现了一个显示城市、温度、天气、湿度的界面,但是这个界面只有一个显示的功能,没有任何可交互的地方,本篇文章继续完善查询天气的APP的功能。

先上效果图;

增加两个功能:

  1. 新增一个城市选择的页面
  2. 在城市选择页面,点击城市,跳转到对应城市天气的页面

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

一样,不同的是:

  1. CityWidget是一个List,用

    ListView.builder

    实现,需要填两个参数

    itemCount

    (List数据的个数)和

    itemBuilder

    (List中item的view),在

    itemBuilder

    中有

    index

    的参数,可以直接从data中去到数据
  2. 为了让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.代码目录跳转

其实到前面一步,功能已经实现,但是因为现在已经有很多类了,现在目录结构太混乱了,调整一下,如下:

下一篇带大家一起检验跨平台能力。

欢迎加入学习交流群;964557053。进群可免费领取一份最新技术大纲和Android进阶资料。请备注csdn