Build a WordPress Blog App using Flutter

Emmanuel

Administrator
Staff member
May 11, 2020
126
28
84
We have an exciting tutorial today, together we will learn how to build a WordPress Blog App in flutter and link it to any WordPress website!

As always you can find the whole code for this tutorial on GitHub: Source code.
😁



What we will cover:

  1. Getting wordpress posts in Json formate.
  2. Using an Isolate to parse the json data in the background.
  3. Display full post content using the Flutter Html package.
  4. Open post URLs in the browser using the Url Launcher package.
What we will build: WordPress Blog App
The goal is to build an app that get data from the public wordpress Api and displays is in a slick looking UI.

Packages we will use:
Google_fonts
: The google_fonts package for Flutter allows you to easily use any of the 977 fonts (and their variants) from fonts.google.com in your Flutter app. Link: google_fonts | Flutter Package

Flutter_html: A Flutter widget for rendering static html tags as Flutter widgets. (Will render over 70 different html tags!). Link: flutter_html | Flutter Package

Http: A composable, Future-based library for making HTTP requests. Link: http | Dart Package

Url_launcher: A Flutter plugin for launching a URL in the mobile platform. Supports iOS and Android. Link: url_launcher | Flutter Package

Getting Started:
Let’s begin by important the packages, in your pubspec.yaml file add these lines under dependencies:

dependencies:
flutter:
sdk: flutter

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
google_fonts:
http:
flutter_html:
url_launcher:
Models: Single Post
class SinglePost {
final String featuredImage, title, date, url, content, avatarURL, authorName;


Code:
 SinglePost({

    this.authorName,

    this.content,

    this.avatarURL,

    this.featuredImage,

    this.title,

    this.date,

    this.url,

  });



  factory SinglePost.fromJson(Map json) {

    return SinglePost(

      authorName: json['author']['name'],

      avatarURL: json['author']['avatar_URL'],

      content: json['content'],

      date: json['date'],

      featuredImage: json['featured_image'],

      title: json['title'],

      url: json['URL'],

    );

  }

}
This model allows us to parse the json data into a dart class which makes it way easier to understand and use.

The functions:
The home screen widget is responsible for getting the posts data as well as parsing it. So the first future function is getPosts.

Code:
Future> _getPosts() async {

  final response = await http.get(baseUrl);

  return compute(parsePosts, response.body);

}
Make sure to call this function on the initState of the home screen widget as follows:

Code:
class _HomeScreenState extends State {

  Future> _postsFuture;

  @override

  void initState() {

    super.initState();

    _postsFuture = _getPosts();

  }
All this function does is sending a get request into the WordPress.com REST API (learn more), once it gets the response it creates a new Isolate that parses the json data.
Code:
List parsePosts(response) {

  final parsed = jsonDecode(response)['posts'].cast>();

  return parsed.map((json) => SinglePost.fromJson(json)).toList();

}
In order to use the parsed data we use a FutureBuilder that listens to the state of _postsFuture.
Code:
FutureBuilder>(

        future: _postsFuture,

        builder: (context, snapshot) {

          if (snapshot.hasError)

            return Center(

              child: Text("Error"),

            );

          if (snapshot.hasData) {

         // Show the blog posts

         }

         else {

            return Scaffold(

              body: Center(

                child: CircularProgressIndicator(),

              ),

            );

          }

)
If any error is caught the FutureBuilder returns an Error message inside a Text Widget, otherwise all the posts are shown on the main page. While the future is running and before having data we show a CircularProgressIndicator indicating that something is happening in the background.

Passing data around:
Because this app is really simple I didn’t feel the need to use Provider for the state management. For now all I do is that once I get the List of type SinglePost I pass it directly to the widgets that needs it.

The UI: Home Screen

Home Screen

Starting from the top we have an AppBar with the title of the app as well as the actual Avatar of my website that we get from the Api.

After that, we have a Container that takes 35% of the height of the device’s screen, inside of it there is a PageView.Builder that returns a custom widget named OverlayContainer.

Code:
Container(

  height: MediaQuery.of(context).size.height * .35,

  margin: const EdgeInsets.symmetric(vertical: 15.0),

  child: PageView.builder(

    controller: PageController(viewportFraction: .76),

    scrollDirection: Axis.horizontal,

    itemCount: snapshot.data.length,

    itemBuilder: (context, i) => OverlayedContainer(

      authorAvatar: "${snapshot.data[i].avatarURL}",

      author: "${snapshot.data[i].authorName}",

      image: "${snapshot.data[i].featuredImage}",

      title: "${snapshot.data[i].title}",

      onTap: () => Navigator.push(

        context,

        MaterialPageRoute(

          builder: (context) =>

              PostScreen(postData: snapshot.data[i]),

        ),

      ),

    ),

  ),

),
At the middle there is a small text widget that indicates that the following is a list of all the posts.

These posts themselves are inside a none scrollable ListViewBuilder while also having it’s shrinkWrap set to true.

Code:
ListView.builder(

  shrinkWrap: true,

  physics: NeverScrollableScrollPhysics(),

  itemCount: 5,

  itemBuilder: (context, i) => PostContainer(

    author: "${snapshot.data[i].authorName}",

    image: "${snapshot.data[i].featuredImage}",

    title: "${snapshot.data[i].title}",

    onTap: () => Navigator.push(

      context,

      MaterialPageRoute(

        builder: (context) =>

            PostScreen(postData: snapshot.data[i]),

      ),

    ),

  ),

)
When the user taps on either PostContainer or OverlayContainer they are taken to the next page.

The UI: Post Screen

Post Screen

This screen consists of a Stack of three widgets.

First, we have a Row of two IconButtons, let’s call it an appbar.

Then, we have a NetworkImage that displays the blog post cover picture wrapped in a Positioned widget to take 55% of the device’s height.

Finally, we have a DraggableScrollableSheet, it’s child is a white Container that has rounded top corners.

Inside the container we have a ListView that is required to give us that draggable and scrollable effect, make sure to pass the DraggableScrollableSheet controller to the ListView controller for that to work.

The ListView’s first widget is a ListTile, we can use that for different purposes but here it shows the blog’s avatar as well as the author name. (You may want to use it to show the blog post’s title).

The most important part here is the Html widget, it takes the content of the blog post that we got from the API and displays it nearly as well as it would show in the browser.

Code:
Html(

  data: "${postData.content}",

  showImages: true,

  onLinkTap: (url) async {

    if (await canLaunch(url)) {

      await launch(url);

    } else {

      throw 'Could not launch $url';

    }

  },

),
Thanks to the onLinkTap and Url_launcher package we can listen for when the user taps on a link that is inside the post content and open it in the browser. And this is how you build a WordPress Blog App in flutter!

Result:

  • Single Post