Flutter Challenge: The Medium App

Deven Joshi
5 min readJul 13, 2018
The original Medium Android app

Flutter Challenges will attempt to recreate a particular app UI or design in Flutter.

Today we’ll attempt to create the home screen of the Medium app. Note that the focus will be on the UI rather than actually fetching articles.

Getting Started

Before developing a design, identify the components required to make the screen in any framework.

The app screen has a drawer, a notification and search option, and a list of articles.

Let’s take a look at the article

At the very top, the article has a text which gives you relevance as to why it’s there. For example, if it’s based on your reading history or if it’s from a category you follow.

Below that is the title of the article itself, which is bold and black as to stand out.

Below the title is the author of the article, date of publishing, and how long the article is estimated to take to read.

On the right hand side is the article image and a bookmark button for saving it for later.

Setting up the app

Create a new Flutter, example: “medium_app_ui”.

Remove the code for the counter app until you only remain with a Scaffold with an AppBar.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Home',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}

class MyHomePage extends StatefulWidget {

@override
_MyHomePageState createState() => new _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage> {

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Home"),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
],
),
),
);
}
}

This is the app with a simple app bar.

Before we move on to the list, let’s construct the AppBar according to the Medium design.

As of now, the appBar is blue. We need to change the app bar to black. The actions on the appBar are notifications and search. Doing these changes:

appBar: new AppBar(
title: new Text("Home"),
backgroundColor: Colors.black,
actions: <Widget>[
Icon(Icons.notifications_none, color: Colors.grey,),
Icon(Icons.search, color: Colors.grey),
],
),

After this, we need to adjust a few icons and add a drawer. To add a drawer without any content, simply add

drawer: Drawer(),

to your Scaffold.

Here is the code and resulting AppBar.

So far, so good.

Let’s create a class to store articles named NewsArticle.dart

class NewsArticle {

String categoryTitle;
String title;
String author;
String date;
String readTime;
String imageAssetName;

NewsArticle(this.categoryTitle, this.title, this.author, this.date,this.readTime, this.imageAssetName);

}

For now, they’re just hardcoded articles.

Creating the List

To create a repeating list in Flutter, we use ListView.builder().

In the image, the cards are over a grey background.

Let’s analyse the card components themselves.

There’s a class named NewsHelper which provides the hard-coded articles.

The final item is build like this:

Padding(
padding: const EdgeInsets.fromLTRB(0.0,0.5,0.0,0.5),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(article.categoryTitle, style: TextStyle(color: Colors.black38,fontWeight: FontWeight.w500, fontSize: 16.0),),
Padding(
padding: const EdgeInsets.fromLTRB(0.0,12.0,0.0,12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(child: Text(article.title, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22.0),), flex: 3,),
Flexible(
flex: 1,
child: Container(
height: 80.0,
width: 80.0,
child: Image.asset("assets/" + article.imageAssetName, fit: BoxFit.cover,)
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(article.author, style: TextStyle(fontSize: 18.0),),
Text(article.date + " . " + article.readTime, style: TextStyle(color: Colors.black45, fontWeight: FontWeight.w500),)
],
),
Icon(Icons.bookmark_border),
],
)
],
),
),
),
);
The recreated Flutter app

Designing the Drawer

This is how the drawer looks on the Medium app:

The original drawer

The Drawer is simply a Column with a list of elements and an Image at the top. The top white portion can be represented by one container and the bottom half by another.

Here is the drawer in code:

Drawer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(32.0,64.0,32.0,16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Icon(Icons.account_circle, size: 90.0,),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("John Doe", style: TextStyle(fontSize: 20.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("See profile", style: TextStyle(color: Colors.black45),),
)
],
),
),
),
Expanded(
child: Container(
color: Colors.black12,
child: Padding(
padding: const EdgeInsets.fromLTRB(40.0,16.0,40.0,40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Home", style: TextStyle(fontSize: 18.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Audio", style: TextStyle(fontSize: 18.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Bookmarks", style: TextStyle(fontSize: 18.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Interests", style: TextStyle(fontSize: 18.0),),
),
Divider(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Become a member", style: TextStyle(fontSize: 18.0, color: Colors.teal),),
),
Divider(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("New Story", style: TextStyle(fontSize: 18.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Stats", style: TextStyle(fontSize: 18.0),),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Drafts", style: TextStyle(fontSize: 18.0),),
),
],
),
),
),
),
],
),
),
The recreated drawer

Here is the final code of the page:

That’s it for today. Feel free to suggest any other apps you may want to see recreated in Flutter.

Project GitHub link : https://github.com/deven98/MediumAppFlutter

More where this came from

This story is published in Noteworthy, where thousands come every day to learn about the people & ideas shaping the products we love.

Follow our publication to see more product & design stories featured by the Journal team.

--

--

Deven Joshi

Google Developer Expert, Flutter | Technical Writer | Speaker