Clima Flutter Weather App


An app that detects current location latitude and longitude, then fetch weather temperature for current city, also you can search for any city.


pubsec.yml

name: clima
description: A new Flutter application.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  geolocator: ^5.1.5
  http: ^0.12.0+2
  flutter_spinkit: ^4.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

  assets:
  - images/

  fonts:
  - family: Spartan MB
    fonts:
    - asset: fonts/SpartanMB-Black.otf
      weight: 900

lib/main.dart

import 'package:flutter/material.dart';
import 'package:clima/screens/loading_screen.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: LoadingScreen(),
    );
  }
}

lib/screens/loading_screen.dart

import 'package:flutter/material.dart';
import 'package:clima/screens/location_screen.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:clima/services/weather.dart';



class LoadingScreen extends StatefulWidget {
  @override
  _LoadingScreenState createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {


 @override
 void initState(){
   super.initState();

   getWeather();
 }


 void getWeather() async{
      var weatherData = await WeatherModel().getWeatherLocation();
      Navigator.push(context, MaterialPageRoute(builder: (context) => LocationScreen(weatherData: weatherData)));
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Builder(
        builder: (context) => Center(
          child: SpinKitWave(
            color: Colors.white,
            size: 40,
          ),
        ),
      ),
    );
  }
}


lib/screens/location_screen.dart

import 'package:clima/screens/city_screen.dart';
import 'package:flutter/material.dart';
import 'package:clima/utilities/constants.dart';
import 'package:clima/services/weather.dart';

class LocationScreen extends StatefulWidget {
  LocationScreen({this.weatherData});

  final weatherData;

  @override
  _LocationScreenState createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen> {
  int temperature;
  int condition;
  String cityName;

  String cityIcon;
  String weatherMessage;

  @override
  void initState(){
    super.initState();
    updateUI(widget.weatherData);
  }

  updateUI(dynamic weatherData){
    setState(() {
      temperature = 0;
      condition  = 0;
      cityName = 'Phone';
      cityIcon = 'Error';
    if(weatherData == null){
      weatherMessage = 'Something wrong, May be internet problem';
      return;
    }

    double localTemp = weatherData['main']['temp'];
    temperature = localTemp.toInt();
    condition  = weatherData['weather'][0]['id'];
    cityName = weatherData['name'];

    WeatherModel weatherModel = WeatherModel();
    cityIcon = weatherModel.getWeatherIcon(condition);
    weatherMessage = weatherModel.getMessage(temperature);

    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        body: Builder(
        builder: (context) => Container(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage('images/location_background.jpg'),
              fit: BoxFit.cover,
              colorFilter: ColorFilter.mode(
                  Colors.white.withOpacity(0.8), BlendMode.dstATop),
            ),
          ),
          constraints: BoxConstraints.expand(),
          child: SafeArea(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    FlatButton(
                      onPressed: () async {
                        var weatherData = await WeatherModel().getWeatherLocation();
                        updateUI(weatherData);
                        Scaffold.of(context).showSnackBar(SnackBar(content: Text('Weather Data has been updated.',), duration: Duration(milliseconds: 1000),),);
                      },
                      child: Icon(
                        Icons.near_me,
                        size: 40.0,
                      ),
                    ),
                    FlatButton(
                      onPressed: () async{
                        String cityName = await Navigator.push(context, MaterialPageRoute(builder: (context) => CityScreen()));
                        if(cityName != null){
                          var weatherData = await WeatherModel().getCityWeather(cityName);
                          updateUI(weatherData);
                        }
                      },
                      child: Icon(
                        Icons.location_city,
                        size: 40.0,
                      ),
                    ),
                  ],
                ),
                Padding(
                  padding: EdgeInsets.only(left: 15.0),
                  child: Row(
                    children: <Widget>[
                      Text(
                        '$temperature°',
                        style: kTempTextStyle,
                      ),
                      Text(
                        cityIcon,
                        style: kConditionTextStyle,
                      ),
                    ],
                  ),
                ),
                Padding(
                  padding: EdgeInsets.only(right: 15.0),
                  child: Text(
                    '$weatherMessage in $cityName',
                    textAlign: TextAlign.right,
                    style: kMessageTextStyle,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

lib/screens/city_screen.dart

import 'package:flutter/material.dart';
import 'package:clima/utilities/constants.dart';

class CityScreen extends StatefulWidget {
  @override
  _CityScreenState createState() => _CityScreenState();
}

class _CityScreenState extends State<CityScreen> {
  String cityName;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage('images/city_background.jpg'),
            fit: BoxFit.cover,
          ),
        ),
        constraints: BoxConstraints.expand(),
        child: SafeArea(
          child: Column(
            children: <Widget>[
              Align(
                alignment: Alignment.topLeft,
                child: FlatButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  child: Icon(
                    Icons.arrow_back_ios,
                    size: 50.0,
                  ),
                ),
              ),
              Container(
                padding: EdgeInsets.all(20.0),
                child: TextField(
                  style: TextStyle(
                    color: Colors.black
                  ),
                  decoration: kTextFieldInputDecoration,
                  onChanged: (value){
                    cityName = value;
                  },
                ),
              ),
              FlatButton(
                onPressed: () {
                  Navigator.pop(context, cityName);
                },
                child: Text(
                  'Get Weather',
                  style: kButtonTextStyle,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

lib/services/location.dart

import 'package:geolocator/geolocator.dart';

class Location{
  double lattitude;
  double longitude;

  Future getCurrentLocation() async {
    try{
      Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.lowest);
      this.lattitude = position.latitude;
      this.longitude = position.longitude;
    }catch(e){
      print(e);
    }
  }

}

lib/services/networking.dart

import 'dart:convert';
import 'package:http/http.dart' as Http;

class NetworkHelper{
  NetworkHelper(this.url);
  final String url;

  Future getData() async{
    Http.Response response;
    try{
      response = await Http.get(url);
    }catch(e){
      return null;
    }

      if(response.statusCode == 200) {
        return jsonDecode(response.body);
      }else{
        print('Response was not 200');
      }
    }

}

lib/services/weather.dart

import 'package:clima/services/location.dart';
import 'package:clima/services/networking.dart';


class WeatherModel {

  String apiKey = 'c8ce20542b396ef0d2b4a37f9bf8c052';
  String openWeatherMapURL = 'https://api.openweathermap.org/data/2.5/weather';


  Future getWeatherLocation() async{
    Location location = Location();
    await location.getCurrentLocation();
    NetworkHelper networkHelper = NetworkHelper('$openWeatherMapURL?lat=${location.lattitude}&lon=${location.longitude}&units=metric&appid=$apiKey');

    return networkHelper.getData();
  }

  Future getCityWeather(String cityName) async{
    Location location = Location();
    await location.getCurrentLocation();
    NetworkHelper networkHelper = NetworkHelper('$openWeatherMapURL?q=${Uri.encodeComponent(cityName)}&units=metric&appid=$apiKey');
    return networkHelper.getData();
  }

  String getWeatherIcon(int condition) {
    if (condition < 300) {
      return '๐ŸŒฉ';
    } else if (condition < 400) {
      return '๐ŸŒง';
    } else if (condition < 600) {
      return '☔️';
    } else if (condition < 700) {
      return '☃️';
    } else if (condition < 800) {
      return '๐ŸŒซ';
    } else if (condition == 800) {
      return '☀️';
    } else if (condition <= 804) {
      return '☁️';
    } else {
      return '๐Ÿคท‍';
    }
  }

  String getMessage(int temp) {
    if (temp > 25) {
      return 'It\'s ๐Ÿฆ time';
    } else if (temp > 20) {
      return 'Time for shorts and ๐Ÿ‘•';
    } else if (temp < 10) {
      return 'You\'ll need ๐Ÿงฃ and ๐Ÿงค';
    } else {
      return 'Bring a ๐Ÿงฅ just in case';
    }
  }
}

lib/utilities/constant.dart

import 'package:flutter/material.dart';

const kTempTextStyle = TextStyle(
  fontFamily: 'Spartan MB',
  fontSize: 80.0,
);

const kMessageTextStyle = TextStyle(
  fontFamily: 'Spartan MB',
  fontSize: 40.0,
);

const kButtonTextStyle = TextStyle(
  fontSize: 30.0,
  fontFamily: 'Spartan MB',
);

const kConditionTextStyle = TextStyle(
  fontSize: 80.0,
);

const kTextFieldInputDecoration = InputDecoration(
  filled: true,
  fillColor: Colors.white,
  icon: Icon(Icons.location_city, color: Colors.yellow,),
  hintText: 'Enter City Name',
  hintStyle: TextStyle(
    color: Colors.grey,
  ),
  border: OutlineInputBorder(
    borderRadius: BorderRadius.all(Radius.circular(10.0)),
    borderSide: BorderSide.none,
  ),
);


Find me on:
https://twitter.com/naimurhasanrwd

Comments