Forked from xsokev/weather_screen_with_forecast.dart
Created
December 24, 2018 10:01
-
-
Save kakopappa/6daf58733eaf65d49520b02413dd064f to your computer and use it in GitHub Desktop.
Flutter Weather Screen Design with Current Temperature and Forecast
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:convert'; | |
import 'package:intl/intl.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:fluids/plugins/weather/models/models.dart'; //custom data models | |
import 'package:fluids/utils/md_icons.dart'; //material design community icons | |
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), | |
), | |
), | |
], | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment