본문 바로가기

Flutter/10 app Weather

[Flutter] App Weather - 4단계 UI

이번에는 화면구성에 대해서 알아보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오(Arctic Fox 2020.3.1 Patch 4), flutter 2.8.1

소스코드 위치 - Release UI · mike-bskim/weather (github.com)

 

Release UI · mike-bskim/weather

 

github.com

 

오늘의 목표 화면입니다.

 

 

먼저 패키지 버전 문제로 약간의 수정이 필요합니다. 패키지 호환문제로 구글링하니 '^'를 제거하라고 해서 했습니다.

 

google_fonts: 2.2.0 '^'를 삭제해주세요. 문제없는분들은 스킵하세요.

 

loading.dart 수정 - api 에서 한글을 지원해서 언어설정을 추가했습니다. 안하셔도 됩니다.

Network 클래스 객체 생성시, 파라미터에  "&lang=kr" 추가함

 

  void getLocation() async {
    MyLocation myLocation = MyLocation();

    await myLocation.getMyCurrentLocation();
    latitude = myLocation.latitude;
    longitude = myLocation.longitude;
    debugPrint('loading.dart >> ' + latitude.toString() +' / ' +longitude.toString());

    String baseApi = 'https://api.openweathermap.org/data/2.5/weather';
    Network network = Network(
        '$baseApi?lat=${latitude.toString()}&lon=${longitude.toString()}&appid=$apiKey&units=metric&lang=kr');
    var weatherData = await network.getJsonData();
    debugPrint(weatherData.toString());

    CurrentWeather currentWeather = CurrentWeather.fromJson(weatherData);
    debugPrint(currentWeather.name);

    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => WeatherScreen(weatherData: currentWeather)));
  }

 

weather_screen.dart 수정.

1. AppBar - leading, actions 추가

2. body 는 아래 그림으로 구성을 설명합니다.

 

 

 

전체 코드는 "더보기" 클릭하세요.

더보기
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timer_builder/timer_builder.dart';
import 'package:weather/model/current_weather.dart';

class WeatherScreen extends StatefulWidget {
  final CurrentWeather weatherData;

  const WeatherScreen({Key? key, required this.weatherData}) : super(key: key);

  @override
  State<WeatherScreen> createState() => _WeatherScreenState();
}

class _WeatherScreenState extends State<WeatherScreen> {
  late String cityName;
  late int temp;
  late String currentDate;
  var date = DateTime.now();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    updateData(widget.weatherData);
  }

  void updateData(CurrentWeather weatherData) {
    var dt = weatherData.dt!;
    var timezone = weatherData.timezone!;
    var tempTime = DateTime.fromMillisecondsSinceEpoch((dt + timezone) * 1000);

    cityName = weatherData.name!;
    temp = weatherData.main!.temp!.round();
    currentDate = DateFormat('yyyy-MM-dd, HH:mm:ss').format(tempTime);
    debugPrint('cityName[$cityName], temp[${weatherData.main!.temp}]');
    debugPrint('dt[$dt], timezone[$timezone], Date[$currentDate]');
  }

  String getSystemTime() {
    var now = DateTime.now();
    return DateFormat('h:mm a').format(now);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        elevation: 0,
        leading: IconButton(
          icon: const Icon(Icons.near_me),
          onPressed: () {},
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.location_searching),
            onPressed: () {},
            iconSize: 30.0,
          ),
        ],
      ),
      body: Container(
        child: Stack(
          children: [
            Image.asset(
              'image/background.jpg',
              fit: BoxFit.cover,
              width: double.infinity,
              height: double.infinity,
            ),
            Container(
              padding: const EdgeInsets.all(20.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Expanded(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            const SizedBox(height: 150.0),
                            Text(
                              '${widget.weatherData.name}',
                              style: GoogleFonts.lato(
                                  fontSize: 30,
                                  fontWeight: FontWeight.bold,
                                  color: Colors.white),
                            ),
                            const SizedBox(height: 8.0),
                            Row(
                              children: [
                                TimerBuilder.periodic(
                                  const Duration(minutes: 1),
                                  builder: (context) {
                                    debugPrint(getSystemTime());
                                    return Text(
                                      getSystemTime(),
                                      style: GoogleFonts.lato(
                                          fontSize: 16,
                                          fontWeight: FontWeight.bold,
                                          color: Colors.white),
                                    );
                                  },
                                ),
                                Text(
                                  DateFormat(' - EEEE, ').format(date),
                                  style: GoogleFonts.lato(
                                      fontSize: 16,
                                      fontWeight: FontWeight.bold,
                                      color: Colors.white),
                                ),
                                Text(
                                  DateFormat('yyyy-MM-dd').format(date),
                                  style: GoogleFonts.lato(
                                      fontSize: 16,
                                      fontWeight: FontWeight.bold,
                                      color: Colors.white),
                                ),
                              ],
                            ),
                          ],
                        ), //City Name, Date, Time
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              '${widget.weatherData.main!.temp!.round().toString()}\u2103',
                              style: GoogleFonts.lato(
                                  fontSize: 85,
                                  fontWeight: FontWeight.w300,
                                  color: Colors.white),
                            ),
                            Row(
                              children: [
                                SvgPicture.asset('svg/climacon-sun.svg'),
                                const SizedBox(
                                  width: 8.0,
                                ),
                                Text(
                                  '${widget.weatherData.weather![0].description}',
                                  style: GoogleFonts.lato(
                                      fontSize: 16.0, color: Colors.white),
                                ),
                              ],
                            ),
                          ],
                        ), //Temperature
                      ],
                    ),
                  ),
                  Column(
                    children: [
                      const Divider(
                        height: 15.0,
                        thickness: 2.0,
                        color: Colors.white30,
                      ),//구분자
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Column(
                            children: [
                              Text(
                                'AQI(대기질지수)',
                                style: GoogleFonts.lato(
                                    fontSize: 14.0, color: Colors.white),
                              ),
                              const SizedBox(height: 8),
                              Image.asset(
                                'image/bad.png',
                                width: 37.0,
                                height: 35.0,
                              ),
                              const SizedBox(height: 8),
                              Text(
                                '"매우나쁨"',
                                style: GoogleFonts.lato(
                                  fontSize: 14.0,
                                  color: Colors.black87,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ],
                          ),//AQI(대기질지수)
                          Column(
                            children: [
                              Text(
                                '미세먼지',
                                style: GoogleFonts.lato(
                                    fontSize: 14.0, color: Colors.white),
                              ),
                              const SizedBox(height: 8),
                              Text(
                                '174.75',
                                style: GoogleFonts.lato(
                                    fontSize: 24.0, color: Colors.white),
                              ),
                              const SizedBox(height: 8),
                              Text(
                                'µg/m3',
                                style: GoogleFonts.lato(
                                  fontSize: 14.0,
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ],
                          ),//미세먼지
                          Column(
                            children: [
                              Text(
                                '초미세먼지',
                                style: GoogleFonts.lato(
                                    fontSize: 14.0, color: Colors.white),
                              ),
                              const SizedBox(height: 8),
                              Text(
                                '74.75',
                                style: GoogleFonts.lato(
                                    fontSize: 24.0, color: Colors.white),
                              ),
                              const SizedBox(height: 8),
                              Text(
                                'µg/m3',
                                style: GoogleFonts.lato(
                                  fontSize: 14.0,
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ],
                          ),//초미세먼지
                        ],
                      ),
                    ],
                  ), //extra information
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

 


 

 

image 및 svg 이미지는 소스코드에 포함되어 있습니다(이미지 출처: 코딩셰프).

 

[참고자료] 코딩셰프

- https://www.youtube.com/watch?v=yfbQVkTZ6F0&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=16