Sunday, November 17, 2019

Flutter HTTP REST API call with full screen cached image from network URL with translucent text overlay and download image, ask for permission, save it locally and show toast feature tutorial with examples

INTRODUCTION

Hey Folks, I've been developing mobile apps since starting of my career and I like it a lot. But, with Flutter, It has become so much fun and easy that I'm in love with this SDK. In case you're a complete beginner, I will suggest you to go through my post where I've introduced Flutter and how to setup and create a project. *LINK  COMING SOON*

WHAT WE WILL LEARN ?

In this tutorial, what we are going to learn is mentioned below :
1. How to call an API in Flutter ?
2. How to create a full screen image widget ?
3. How to show a cached image from network URL ?
4. How to display a translucent text overlay on an image ?
5. How to align buttons at the bottom horizontally and spaced evenly ?
6. How to ask for permission in Flutter ?
7. How to download an image from network URL and save it locally ?
8. How to show toast in Flutter ?

Our final app will look like this :




PACKAGES WE WILL USE :
1. http: ^0.12.0+2 

2 .cached_network_image: ^1.1.3

3. permission_handler: ^4.0.0
https://pub.dev/packages/permission_handler

4. toast: ^0.1.5
https://pub.dev/packages/toast

5. path_provider: ^1.4.2
https://pub.dev/packages/path_provider

6. dio: ^3.0.4
https://pub.dev/packages/dio


Now that we have passed the introduction phase, let's jump right to code.


1. How to call an API in Flutter ?

For calling an API, we need to use "http" package. Let's add it to our pubspec.yaml and 
save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the terminal.

dependencies:
  flutter:
    sdkflutter
  http^0.12.0+2


Next, we import the package in our dart file where we want to call the API :
import 'package:http/http.dart' as http;

We will also need to import 'async' library :
import 'dart:async';

Time to write method to call the API :
  Future _CallAPI() async {
  http.Response _response;
 _response = await http.get('https://REPLACE IT WITH YOUR API URL');
    
    Map<Stringdynamic> jsonResponse =
        json.decode(_response.body);
String imageUrl = jsonResponse["url"];
//replace 'url' with your JSON response key

     }


Here, in the 'imageUrl' string you will get the value of the json element from the API response. You can customize it according to the structure of the JSON object of your response.


2. How to create a full screen image widget ?

class FullScreenPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        image: DecorationImage(
          image: NetworkImage('https://Your image URL'),
          fit: BoxFit.fill
        ) ,
      ),
    );
  }
}

Just using this widget inside your 'Scaffold' or 'MaterialApp' will result in a full screen image.
Feel free to use image from your local asset in the 'image' attribute of the 'DecorationImage' Widget.

3. How to show a cached image from network URL ?

 For this, we need to use "cached_network_image" package. Let's add it to our pubspec.yaml as well   and save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the   terminal. 

Next, we import the package :
import 'package:cached_network_image/cached_network_image.dart';

Then, we write the new 'FullScreenPage' widget code :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      );
    
  }
}



That's it, you're done. This 'CachedNetworkImage' widget will cache the image automatically for you. 'Placeholder' and 'errorWidget' attributes are optional but they provide advance controls.


4. How to display a translucent text overlay on an image ?

For this, we just need to add a few more lines of code in the above code and the result will be :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
           child: Center(
              child: Text("Sample Text",
            style: TextStyle(
                color: Colors.black,
                backgroundColor: Colors.white38,
                fontSize: 18,
                fontWeight: FontWeight.w500,
                wordSpacing: 1.0,
                fontStyle: FontStyle.italic),
          )),
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      );
  }
}


In the above code, we have just added a 'Text' widget to the 'child' attribute of the 'Container' widget.
All the 'TextStyle' attribute is optional but 'backgroundColor' attribute with 'Colors.white38' is required to give the translucent visibility. You can play with different white values like 'white54', 'white30' to increase or decrease transparency.


5. How to align buttons at the bottom horizontally and spaced evenly ?

@override
  Widget build(BuildContext context) {
  
    return Scaffold(
      
        body: Stack(children: [
      Center(
          child: FullScreenPage( )),
      Align(
        alignment: Alignment.bottomCenter,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            RaisedButton(
                onPressed: () => _changeImageQuality(),
                child:Icon(Icons.hdr_on)                   ),
            RaisedButton(
                onPressed: () => _refresh(), child: Icon(Icons.flight)),
            RaisedButton(
                onPressed: () => _showHideInfo(),
                child: Icon(Icons.speaker_notes_off)),
            RaisedButton(
                onPressed: () => _downloadImage(),
                child: Icon(Icons.file_download)),
          ],
        ),
      ),
    ])

        
        );
  }

As you can see in the above code, our 'FullScreenPage' widget is used in the 'Scaffold' widget which is the root widget of the screen. The buttons are placed in the 'Row' widget which will align them horizontally. You can play with MainAxisAlignment.spaceAround .There's also 'spaceEvenly' and 'spaceBetween', use these to arrange buttons differently.


6. How to ask for permission in Flutter ?

 For this, we need to use "permission_handler" package. Let's add it to our pubspec.yaml as well   and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the   terminal.

 Next, we import the package :
import 'package:permission_handler/permission_handler.dart';

Now, let's write the code to ask permission where it's needed :

List<PermissionGroup> permissionList = new List<PermissionGroup>();
    permissionList.add(PermissionGroup.storage);
    final Map<PermissionGroupPermissionStatus> status =
        await PermissionHandler().requestPermissions(permissionList);
    if (status.values.first == PermissionStatus.granted) {
       // this means permission is granted
       }

You can add multiple permissions in the 'permissionList' to ask all the required permissions of your app at once.
Also keep in mind that you need to add the permission in the 'AndroidManifest.xml' like this :
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

7. How to download an image from network URL and save it locally ?

For this, we need to use "path_provider" and "dio" package. Let's add it to our pubspec.yaml as well  and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the  terminal.

 Next, we import the packages :

import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';

Now, let's write the code to download an image :

         Dio dio = Dio();
    var dir = await getExternalStorageDirectories(type: StorageDirectory.downloads);
  await dio.download(imageUrl, "${dir}/Your_fileName.jpeg");

As simple as that, this above code will download your image to the given directory. Feel free to change the 'type' attribute of the 'getExternalStorageDirectories' function.

8. How to show toast in Flutter ?

And, we have reached the final step, which to show a toast in flutter.

For this, we need to use "toast" package. Let's add it to our pubspec.yaml as well  and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the  terminal.

Next, we import the package :
import 'package:toast/toast.dart';

And now, we will update the above written download code with this new code with toast :

  Dio dio = Dio();
      try {
        var dir = await getExternalStorageDirectories(type: StorageDirectory.downloads);
      String progressString = '';

        await dio.download(imageUrl, "${dir}/Your_filename.jpeg",
            onReceiveProgress: (rec, total) {
          setState(() {
            progressString = ((rec / total) * 100).toStringAsFixed(0+ "%";
          });
          if (progressString == "100%") {
            Navigator.pop(context);
            Toast.show("Download completed !", context,
                duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
          }
        });
      } catch (e) {
        Toast.show(e.toString(), context,
            duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
      }

And that it, as simple as that. You're now ready to create an app with these features.

** You can find the complete project here :

 https://github.com/chetan-acharya/SpaceWander


Also, if you have any query, please comment below.






No comments:

Post a Comment