Flutter UI Designs

Overview

The screen is a normal information display screen. In this use case, it displays weather information. It can be used as part of a dedicated weather app or as part of another app which provides weather for it’s users.

Features

  • The screen displays the current weather forecast.
  • It displays an icon which indicates the current conditions, with the temperature, the city and date and a summary of the forecast over the following days.
  • It has an info bar with wind speed, wind direction and chance of rain.
  • Last, is a horizontal scrolling list with the forecast over the next 10 days.

Implementation

This screen uses a Stack widget as its main widget. The first child of the Stack is a Positioned widget. It is used to display an Image for the current city. The image is about 2/3 of the device height. Since I am loading the image over the network, one possible improvement is to use the FadeInImage widget so that an image placeholder could be presented until the actual image is loaded from the network.

new Positioned(
  child: Image.network(
	weatherImage,
	fit: BoxFit.cover,
  ),
  height: imageHeight,
  top: 0.0,
  left: 0.0,
  right: 0.0,
),

The next child in the Stack is a Scaffold which takes up the entire screen. I set the background color to transparent so that the city photo is visible. I added an AppBar with a transparent background and an elevation of 0. For the body of the Scaffold, I used a Column widget and set the main axis alignment to end so the children of the Column would be positioned at the bottom.

new Scaffold(
  appBar: new AppBar(
	backgroundColor: Colors.transparent,
	elevation: 0.0,
  ),
  backgroundColor: Colors.transparent,
  body: new Column(
	mainAxisAlignment: MainAxisAlignment.end,
...

The first child of the Column is a Container widget which is used to create a semi dark background over the bottom of the image. The child of the Container is a Column widget which has two widgets as its children. The first widget is a Row widget which is used to display the current temperature, an icon for the current conditions and city and state, followed by the date. The second widget is a summary of the forecast over the next few days.

...
  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,),
		),
	  ),
	  new 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),
			),
		],
	  )
	],
  ),
...

The second child of the Column is another Container with a white background. It is used to display extra weather information. The child of the Container is a SafeArea widget which is used to create a safe area at the bottom for iPhone X devices. Its child is a Column widget which has two widgets as its children. The first widget is Row widget. It displays the wind speed, wind direction and chance of precipitation. The second widget is a ListView widget. It is used to display a horizontally scrolling list of forecasts over a specified number of days. The widget uses an itemBuilder which calls a local method to create the widget for displaying the days. The method returns a Container which has a single right border and a Column widget with a Text for the day, an Icon for the condition, and another Text for the high and low temps.

...
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),),
		],
	  )
	],
),
...

Screenshots


The complete source code can be found here.


As always, this is one of many possible ways to design this UI. If you feel this design could be improved, please feel free to leave me a comment.