Hacker News Flutter App using Hacker Api for Qtec

Hacker News Flutter App using Hacker Api for Qtec

hacker_news_for_qtec .Hacker News Flutter App using Hacker Api for Qtec

hacker_news_for_qtec

Documentation

##Fetching Top Stories

The first step is to implement a web service to fetch top stories. There are several packages available to perform networking tasks in Flutter.

For the sake of simplicity, I have used the http package. Install the package by adding the http package in the pubspec.yaml.

I have implemented getTopStories method in a Webservice.dart file. The implementation is shown below:

void _populateTopStories() async { final responses = await Webservice().getTopStories(); final stories = responses.map((response) { final json = jsonDecode(response.body); return Story.fromJSON(json); }).toList();

setState(() {
  _stories = stories;
});

}

We used the http package to invoke the following URL:

https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty

The response from the above URL, returns an array of story IDs. I have used those IDs to retrieve the actual stories and utilize Future.wait to wait for all the responses. https://hacker-news.firebaseio.com/v0/item/25003999.json?print=pretty

Once all the responses have been evaluated, a Future<List> is returned to the caller.

Displaying Top Stories

The TopArticleList widget is responsible for displaying the top Hacker News stories to the user. I called _populateTopStories inside the initState method, as shown in the implementation below:

class TopArticleList extends StatefulWidget { TopArticleList({Key key, this.title}) : super(key: key); final String title;

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

class _TopArticleListState extends State { List _stories = List();

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

void _populateTopStories() async { final responses = await Webservice().getTopStories(); final stories = responses.map((response) { final json = jsonDecode(response.body); return Story.fromJSON(json); }).toList();

setState(() {
  _stories = stories;
});

}

The build function is responsible for creating the user interface for the app. The implementation is shown below:

@override Widget build(BuildContext context) { final topAppBar = AppBar( elevation: 0.1, backgroundColor: Color.fromRGBO(58, 66, 86, 1.0), title: Text(widget.title), );

final makeBottom = Container(
  height: 55.0,
  child: BottomAppBar(
    color: Color.fromRGBO(58, 66, 86, 1.0),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        IconButton(
          icon: Icon(Icons.home, color: Colors.white),
          onPressed: () {},
        ),
        IconButton(
          icon: Icon(Icons.blur_on, color: Colors.white),
          onPressed: () {},
        ),
        IconButton(
          icon: Icon(Icons.hotel, color: Colors.white),
          onPressed: () {},
        ),
        IconButton(
          icon: Icon(Icons.account_box, color: Colors.white),
          onPressed: () {},
        )
      ],
    ),
  ),
);

final makeBody = Container(
    child: ListView.builder(
  scrollDirection: Axis.vertical,
  shrinkWrap: true,
  itemCount: _stories.length,
  itemBuilder: (BuildContext context, int index) {
    return Card(
        elevation: 8.0,
        margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
        child: Container(
          decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
          child: ListTile(
              onTap: () {
                _navigateToShowCommentsPage(context, index);
              },
              contentPadding:
                  EdgeInsets.symmetric(horizontal: 5.0, vertical: 2.0),
              leading: Container(
                  child: new Container(
                width: 50,
                height: 50,
                padding: const EdgeInsets.all(6.0),
                child: Column(
                  children: <Widget>[
                    Text("${index + 1}",
                        style:
                            TextStyle(color: Colors.black, fontSize: 16)),
                    SizedBox(
                      height: 3.0,
                    ),
                    Text("${_stories[index].points}p",
                        style: TextStyle(color: Colors.white)),
                  ],
                ),
              )),
              title: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(_stories[index].title,
                      style: TextStyle(fontSize: 18),
                      textAlign: TextAlign.left),
                  SizedBox(
                    height: 3.0,
                  ),
                  Text(
                    _stories[index].url.substring(8),
                    style: TextStyle(fontSize: 12),
                    textAlign: TextAlign.left,
                  ),
                  SizedBox(
                    height: 3.0,
                  ),
                  Row(
                    children: <Widget>[
                      Text(
                        "${_stories[index].time}h - ",
                        style: TextStyle(fontSize: 14),
                        textAlign: TextAlign.left,
                      ),
                      SizedBox(
                        width: 1.0,
                      ),
                      Text(
                        _stories[index].by,
                        style: TextStyle(fontSize: 14),
                        textAlign: TextAlign.left,
                      ),
                    ],
                  )
                ],
              ),
              // subtitle: Text("Intermediate", style: TextStyle(color: Colors.white)),
              trailing: Column(
                children: <Widget>[
                  Icon(
                    Icons.message,
                    color: Colors.red,
                  ),
                  SizedBox(
                    width: 1.0,
                  ),
                  Text(
                    "${_stories[index].commentIds.length}",
                    style: TextStyle(fontSize: 16, color: Colors.red),
                    textAlign: TextAlign.end,
                  ),
                ],
              )),
        ));
  },
));

return Scaffold(
  backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
  appBar: topAppBar,
  body: makeBody,
  bottomNavigationBar: makeBottom,

);

}

I have also added a new page which displays list of comments and an article tab taht invokes a web view with the stories'url. class CommentListPage extends StatefulWidget { final List comments; final Story story;

CommentListPage({Key key, this.story, this.comments}) : super(key: key);

@override _CommentListPageState createState() => _CommentListPageState(story, comments); }

class _CommentListPageState extends State with AutomaticKeepAliveClientMixin{ final List comments; final Story story;

_CommentListPageState(this.story, this.comments);

final Completer _controller = Completer();

num position = 1;

final key = UniqueKey();

doneLoading(String A) { setState(() { position = 0; }); }

startLoading(String A) { setState(() { position = 1; }); }

@override Widget build(BuildContext context) { return DefaultTabController( length: 2, child: Scaffold( backgroundColor: Color.fromRGBO(58, 66, 86, 1.0), appBar: AppBar( elevation: 0.1, backgroundColor: Color.fromRGBO(58, 66, 86, 1.0), bottom: TabBar( tabs: [ Tab( text: "${this.comments.length} Comments", ), Tab(text: "Websites"), ], ), title: Text(this.story.title), ), body: TabBarView( children: [ Center( child: ListView.builder( itemCount: this.comments.length, itemBuilder: (context, index) { return ListTile( leading: Container( alignment: Alignment.center, width: 35, height: 35, decoration: BoxDecoration( color: Colors.purple, borderRadius: BorderRadius.all(Radius.circular(10))), child: Text("${1 + index}", style: TextStyle(fontSize: 22, color: Colors.white))), title: Padding( padding: const EdgeInsets.only(top: 8.0), child: Html( data: this.comments[index].text, ), //style: TextStyle(fontSize: 14, color: Colors.white), textAlign: TextAlign.justify,), )); }, )), IndexedStack( children: [ WebView( initialUrl: this.story.url, key: key, onPageStarted: startLoading, onPageFinished: doneLoading, javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); }, ), Container( color: Colors.red, child: Center( child: CircularProgressIndicator( backgroundColor: Colors.red, )), ), ], ), ], ), ), ); } @override bool get wantKeepAlive => true;

}

The screenshot below shows the result:

Screenshot 1 Screenshot 1 Screenshot 1

Download Details:

Author: bipulhstu

Source Code: https://github.com/bipulhstu/hacker_news_for_qtec

flutter dart mobile-apps

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Google's Flutter 1.20 stable announced with new features - Navoki

Google has announced new flutter 1.20 stable with many improvements, and features, enabling flutter for Desktop and Web

Top 25 Flutter Mobile App Templates in 2020

Flutter has been booming worldwide from the past few years. While there are many popular mobile app development technologies out there, Flutter has managed to leave its mark in the mobile application development world. In this article, we’ve curated the best Flutter app templates available on the market as of July 2020.

Flutter App Development Trends 2020

As the new decade dawns upon us, a slew of technologies has been making a lot of noise to grab the developers’ attention. While native app development is going strong, the trade winds are now blowing towards going cross-platform.

How To Succeed In Mobile App Wireframe Design?

This article covers everything about mobile app wireframe design: what to do and what not, tools used in designing a mobile or web app wireframe, and more.

What is Flutter and why you should learn it?

Flutter is an open-source UI toolkit for mobile developers, so they can use it to build native-looking Android and iOS applications from the same code base for both platforms. Flutter is also working to make Flutter apps for Web, PWA (progressive Web-App) and Desktop platform (Windows,macOS,Linux).