Flutter UI Widgets

Nov 9 2021 · Dart 2.14, Flutter 2.5, VS Code 1.61

Part 1: Flutter UI Widgets

09. Add Navigation & SliverAppBar

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 08. Style Your App with Themes Next episode: 10. Work with Forms

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In previous episodes, we used a FloatingActionButton to add an onPressed interaction. Flutter provides us with some widgets that let’s us build interactivity into any widget. We would be using a GestureDetector widget to do this. This widget detects different types of gestures from a user like a tap, drag, long press and many others.

...
final article = snapshot.data![index]; // Dont ignore this!!!
return GestureDetector(
  onTap: () {
    Navigator.push<void>(
      context,
      MaterialPageRoute(
          builder: (context) => ArticlePage(article: article)),
    );
  },
  child: ArticleCard(article: article), // add this Update too!!!
);
...
ListView(
  children: <Widget>[
    ArticleMeta(article: article),
    ArticleContent(article: article),
    ArticleTags(),
    Container(
      margin: const EdgeInsets.symmetric(vertical: 16),
      height: 16,
      color: Colors.grey[300],
    )
  ]
),
class ArticleMeta extends StatelessWidget {
  final Article? article;

  const ArticleMeta({
    Key? key,
    required this.article,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        children: <Widget>[
          Text(
            '${article!.title}',
            style: Theme.of(context).textTheme.headline4!.copyWith(
                  fontSize: 30,
                  fontWeight: FontWeight.w600,
                ),
          ),
          const SizedBox(height: 16),
          ListTile(
            contentPadding: const EdgeInsets.all(0),
            leading: const CircleAvatar(
              child: Icon(Icons.person),
            ),
            title: Text(article!.author),
            subtitle: Text(article!.publishedAt),
            trailing: ElevatedButton(
              onPressed: () {},
              child: const Text(
                'Subscribe',
                style: TextStyle(color: Colors.white),
              ),
              style: ElevatedButton.styleFrom(
                primary: Theme.of(context).primaryColor,
              ),
            ),
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }
}
class ArticleContent extends StatelessWidget {
  const ArticleContent({
    Key key,
    @required this.article,
  }) : super(key: key);

  final Article article;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
      child: Column(
        children: <Widget>[
          Text(
            '\"${article.description}\"',
            style: Theme.of(context).textTheme.subtitle.copyWith(
                  fontStyle: FontStyle.italic,
                  color: Colors.grey[600],
                  fontSize: 20,
                ),
          ),
          SizedBox(height: 16),
          Text(
            article.content,
            style: TextStyle(fontSize: 18, height: 1.5),
          ),
          SizedBox(height: 16),
        ],
      ),
    );
  }
}
class ArticleTags extends StatelessWidget {
  const ArticleTags({ Key? key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Wrap(
        spacing: 8,
        children: <Widget>[
          const Chip(label: Text('Science')),
          const Chip(label: Text('Technology')),
          const Chip(label: Text('Devices')),
        ],
      ),
    );
  }
}
...
body: CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      expandedHeight: 300,
      pinned: true,
      floating: true,
      elevation: 50,
      flexibleSpace: FlexibleSpaceBar(
        background: Image.network(
          '${article.urlToImage}',
          fit: BoxFit.cover,
        ),
      ),
    ),
    SliverList(
      delegate: SliverChildListDelegate(
        [
          ArticleMeta(article: article),
          ArticleContent(article: article),
          ...
        ]
      ),
    )
  ]
),