Snippets

Kevin Armstrong Weather Display

You are viewing an old version of this snippet. View the current version.
Revised by Kevin Armstrong 02e6cc9
import 'dart:convert';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:fluids/plugins/weather/models/models.dart';
import 'package:fluids/utils/md_icons.dart';

class CityForecast extends StatelessWidget {
  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  final String city;
  final String state;
  final Forecast forecast;

  CityForecast({this.city, this.state, this.forecast});

  @override
  Widget build(BuildContext context) {
    final int contentHgt = 240;
    double imageHeight = MediaQuery.of(context).size.height - contentHgt;
    return Stack(
      children: <Widget>[
        new Positioned(
          child: Image.network(
            weatherImage,
            fit: BoxFit.cover,
          ),
          height: imageHeight,
          top: 0.0,
          left: 0.0,
          right: 0.0,
        ),
        new Scaffold(
          appBar: new AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0.0,
          ),
          backgroundColor: Colors.transparent,
          body: new Column(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              _makeWeatherRow(context),
              Container(
                height: contentHgt.toDouble(),
                color: Colors.white,
                child: new SafeArea(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
                      _makeWeatherExtra(context),
                      Expanded(
                        child: AnimatedList(
                          key: _listKey,
                          initialItemCount: forecast.daily.length,
                          scrollDirection: Axis.horizontal,
                          itemBuilder: (BuildContext context, int index, animation){
                            return _makeDay(context, animation, forecast.daily[index]);
                          },
                        ),
                      )
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ],
    );
  }

  _makeDay(BuildContext context, animation, Weather w){
    return FadeTransition(
      opacity: animation,
      child: SizeTransition(
        sizeFactor: animation,
        child: new Container(
          width: 120.0,
          decoration: BoxDecoration(
            border: Border(right: BorderSide(width: 1.0, color: Colors.black26)),
          ),
          margin: EdgeInsets.symmetric(vertical: 10.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(DateFormat('EEE').format(w.dateTime).toUpperCase()),
              Expanded(
                child: Icon(w.mcIcon, size: 40.0,),
              ),
              Text('${w.temperatureMax.round()} / ${w.temperatureMin.round()}', style: Theme.of(context).textTheme.title,),
            ],
          ),
        ),
      ),
    );
  }

  _makeWeatherRow(context) {
    Weather current = forecast != null && forecast.currently != null ? forecast.currently : null;
    return current == null ? Container() : Container(
      color: Colors.black45,
      padding: EdgeInsets.all(20.0),
      child: new Column(
        children: <Widget>[
          new Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(current.temperature.toStringAsFixed(0), style: Theme.of(context).textTheme.display2.copyWith(color: Colors.white),),
                  Icon(MDIcons.temperature_fahrenheit, color: Colors.white, size: 30.0,),
                ],
              ),
              new Expanded(
                child: Container(
                  alignment: Alignment.center,
                  padding: const EdgeInsets.only(right: 30.0),
                  child: Icon(current.mcIcon, color: Colors.white, size: 60.0,),
                ),
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('$city, $state'.toUpperCase(), style: Theme.of(context).textTheme.title.copyWith(color: Colors.white),),
                  Text(DateFormat('EEEEE, MMMM d').format(DateTime.now()).toUpperCase(), style: Theme.of(context).textTheme.body1.copyWith(color: Colors.white),),
                ],
              )
            ],
          ),
          _makeWeatherSummary(context),
        ],
      ),
    );
  }

  _makeWeatherExtra(BuildContext context) {
    Weather current = forecast != null && forecast.currently != null ? forecast.currently : null;
    return current == null ? Container() : Container(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.all(15.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                _makeExtraInfoStat(context, MDIcons.flag_variant_outline, '${current.windSpeed.round()} MPH'),
                _makeExtraInfoStat(context, MDIcons.compass_outline, '${current.windDirection}'),
                _makeExtraInfoStat(context, MDIcons.umbrella_outline, '${current.precipitationProbability.round()}%'),
              ],
            ),
          ),
          Divider(),
        ],
      ),
    );
  }

  _makeExtraInfoStat(BuildContext context, IconData icon, String info){
    return Row(
      children: <Widget>[
        Icon(icon),
        Text(info.toUpperCase(), style: Theme.of(context).textTheme.title,),
      ],
    );
  }

  _makeWeatherSummary(BuildContext context) {
    String summary = Utf8Codec().decode(forecast.dailySummary.codeUnits);
    return Container(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.only(top: 10.0),
            child: Text(
              summary,
              style: Theme.of(context).textTheme.body1.copyWith(color: Colors.white),
            ),
          ),
        ],
      ),
    );
  }
}
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.