This is the 11th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021

Now that you’ve built the basic page and created the bottom navigation bar, let’s start building the Discover page and my page today. Go to the rootPage and change _currentIndex to 2, so that the default selection is the discovery page, easy to build the page. To build a page, think in your mind about what parts you will use to build the page.

1. Discover pages

So when you look at the interface and see the AppBar, the idea is to use that scaffold and then wrap the row in a container in the body.

Change the AppBar Title color to black, then the background color to gray, change the bottom shadow size to 0, and set centerTitle to True for Android so that the Title will be in the middle when it cuts out, and then create a Container.

Class _DiscoverPageState extends State<DiscoverPage> {Color _themColor = color.fromrgbo (220, 220, 220, 1.0); @override Widget build(BuildContext context) {return Scaffold(appBar: appBar (title: const Text(' discover page ',style: TextStyle(color: Colors.black),), backgroundColor: _themColor, elevation: 0, centerTitle: true, ), body: Container( height: 800, color: _themColor, ), ); }}Copy the code

Next, create the Discover cell. In daily development, statelessWidgets are used first and then changed to statefulWidgets later when the state needs to be preserved. So first create the DiscoverCell with the StatelessWidget, then create the four parameters that need to be passed in, and create the constructor, where title and imageName must be required. Here we use a Row for the page thinking, and we use two rows inside a Row, one left and one right, so we use spaceBetween here.

class DiscoverCell extends StatelessWidget { final String? title; final String? imageName; final String? subTitle; final String? subImageName; DiscoverCell({required this.title, required this.imageName, this.subTitle, this.subImageName}): assert(title ! = null,"title cannot be null "),assert(imageName! = null,"imageName cannot be empty "); @override Widget build(BuildContext context) { return Container( height: 55, color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // left Container(), // right Container(), ], ), ); }}Copy the code

Add the required parts here, and add the padding to the container.

Container( padding: EdgeInsets.all(10), child: Row( children: [ //image Image( image: AssetImage(imageName!), width: 20, ), const SizedBox( width: 15, ), //title Text(title!), ], ), ), // right Container( padding: EdgeInsets.all(10), child: Row( children: [ // subtitle Text(subTitle ?? ""), // subimage Image( image: // AssetImage(subImageName?? ""), width: 20,), // [,], [, [, [, [, [, [,Copy the code

Once the DiscoverCell is created, build the Discover Page. Add child: ListView to the container of the previous scaffold body. Then add the required Cell and create the spacing using the SizedBox. The Row contains two containers to create a white front part and a gray back part.

Child: ListView(children: <Widget>[DiscoverCell(imageName: 'images/ friends.png ', title: 'friends ',), const SizedBox(height: 10,), DiscoverCell(imageName: 'images/ scan 2.png', title:' scan ',), Row(children: <Widget>[Container(width: 50, height: 0.5, color: color.white), Container(height: 0.5, color: color.white), Color.grey)],), DiscoverCell(imageName: 'images/ shake. PNG ', title: 'shake ',), SizedBox(height: 10,), DiscoverCell(imageName: 'images/ look at icon.png', title: 'look at ',), Row(children: <Widget>[Container(width: 50, color: 0, color: color.white), color (color: 0, color: color.grey),), DiscoverCell(color: 0, color: color.grey) 'images/ search 2.png', title: 'search 2.png',), SizedBox(height: 10,), DiscoverCell(imageName: 'images/ nearby people icon.png', title: 'Nearby people ',), SizedBox(height: 10,), DiscoverCell(imageName: 'images/ shopping.png ', title:' shopping.png ', subTitle: SubImageName: 'images/badge.png',), Row(children: <Widget>[Container(width: 50, height: 0.5, color: Color.white), color (height: 0.5, color: color.grey)],), DiscoverCell(imageName: 'images/ game.png ', title: 'game ',), SizedBox(height: 10,), DiscoverCell(imageName: 'images/ applet ', title:' applet ',),),Copy the code

Next, click on the cell to jump to the page. To respond to a click is to coat the DiscoverCell with a GestureDetector layer. GestureDetector is a functional component for gesture recognition, through which we can recognize various gestures.

Create a jump page:

class DiscoverChildPage extends StatelessWidget { final String title; DiscoverChildPage({required this.title}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("$title"), ), body: Center( child: Text("$title"), ), ); }}Copy the code

Then add the jump method when clicked.

  onTap: () {
          Navigator.of(context).push(MaterialPageRoute(
              builder: (BuildContext context) =>
                  DiscoverChildPage(title: '$title')));
          print('$title');
        },
Copy the code

Then add a graying click effect to the cell, which means that to make the cell stateful, DiscoverCell should be changed to a StatefulWidget. Just because the entire cell is stateful does not mean the render is complete. A Widget is a description of an interface, not an interface. If you change the entire cell to stateful, the description of the interface will be recreated, not the interface. If you are looking for performance, you can extract the Container to make a StatefulWidget. For convenience, change the entire DiscoverCell to a StatefulWidget.

class DiscoverCell extends StatefulWidget { final String? title; final String? imageName; final String? subTitle; final String? subImageName; DiscoverCell( {required this.title, required this.imageName, this.subTitle, this.subImageName}) : assert(title ! = null, "title cannot be null "), assert(imageName! = null, "imageName cannot be empty "); @override _DiscoverCellState createState() => _DiscoverCellState(); } class _DiscoverCellState extends State<DiscoverCell> { @override Widget build(BuildContext context) { return GestureDetector( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => DiscoverChildPage(title: '$widget.title'))); print('$widget.title'); }, onTapCancel: () {}, onTapDown: (TapDownDetails details) {}, child: Container( height: 55, color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // left Container( padding: EdgeInsets.all(10), child: Row( children: [ //image Image( image: AssetImage(widget.imageName!), width: 20, ), const SizedBox( width: 15, ), //title Text(widget.title!), ], ), ), // right Container( padding: EdgeInsets.all(10), child: Row( children: [ // subtitle Text(widget.subTitle ?? ""), // subimage widget.subImageName != null ? Image( image: AssetImage(widget.subimagename!), width: 12,) : Container(), AssetImage('images/icon_right.png'), width: 15, ), ], )), ], ), )); }}Copy the code

Add a _currentColor and in onTapDown change _currentColor to gray and in onTap change it to white. _currentColor is used as the Container color.

2. My page

My page and The Discover page are essentially the same, except for a different header, no Appbar and a new camera.To create my page, change _currentIndex to 3 for ease of creation. Because the camera here is floating, stack is used here. So here we just create a simple toy for the camera, and then the cell uses the DiscoverCell, and then we can concentrate on the head interface, and here we create the headerWidget for the head interface. Positioned in the back because the camera needs to be in the upper.

import 'package:flutter/material.dart'; import 'discover/discover_cell.dart'; class MinePage extends StatefulWidget { const MinePage({Key? key}) : super(key: key); @override _MinePageState createState() => _MinePageState(); } class _MinePageState extends State<MinePage> { Widget headerWidget() { return Container(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( child: Stack( children: [ Container( child: ListView( children: [ headerWidget(), SizedBox( height: 10, ), DiscoverCell( imageName: 'images/ wechat pay.png ', title: 'pay.png ',), SizedBox(height: 10,), DiscoverCell(imageName: 'images/ wechat pay.png ', title: Container(width: 50, height: 0.5, color: color.white), Container(height: 0.5, color: color.white), Container(height: 0.5, color: Color.grey)],), // DiscoverCell(imageName: 'images/微信 album ', title: 'album ',), Row(children: <Widget>[Container(width: 50, height: 0.5, color: color.white), Container(height: 0.5, color: color.white), Color.grey)],), // DiscoverCell(imageName: 'images/微信卡包 ', title: '微信卡包 ',), Row(children: <Widget>[Container(width: 50, height: 0.5, color: color.white), Container(height: 0.5, color: color.white), Color.grey),],), DiscoverCell(imageName: 'images/微信 emotics.png ', title: 'emoticon ',), SizedBox(height: 21,), DiscoverCell(imageName: 'images/微信设 备.png',],),), child: Image. The asset (" images/camera. PNG ", width: 25,), right: 10, top: 40,),),),),); }}Copy the code

Give the height and color of the Container in the headerWidget and you can see it on the screen

 Widget headerWidget() {
    return Container(
      height: 300,
      color: Colors.red,
    );
  }
Copy the code

Here you see that the Container is not at the top. This is a Padding that the Flutter sets for the fringe screen.

So to get rid of the padding, we need to use mediaQuery. removePadding, and we have removeTop, removeBottom, removeLeft, and removeRight.

So the padding is gone.

Going back to the headerWidget, add a Container inside the Container and add a Margin to it so that the container is at the bottom of the outside container.

  return Container(
      height: 200,
      color: Colors.white,
      child: Container(
        color: Colors.red,
        margin: EdgeInsets.only(top: 100,bottom: 20,left: 10,right: 10),
      ),
    );
Copy the code

Add a row to the child inside the container, then add the avatar first. ClipRRect is used here to add rounded corners to the image.

Container(child: ClipRRect(child: Image(Image: Image) AssetImage('images/ hank.png ')), borderRadius: borderRadius. Circular (5.0),),), // Right part],),Copy the code

The next part on the right would be Stack + toy.

Container( margin: EdgeInsets.only(left: 10), width: MediaQuery.of(context).size.width - 20 - 90, height: 100, child: Stack( children: [ Positioned( child: Text("Hank", style: TextStyle( fontSize: 28, fontWeight: 21. FontWeight. Bold,),, left: 0, top: 0,), toy (child: Text("微 博 : 1234", style: TextStyle(color: Toy. FromRGBO (144, 144, 144, 1.0),), left: 0, bottom: 0,), child: Image(Image: AssetImage('images/icon_right.png'), width: 15, ), right: 0, bottom: 0, ), ], ), ),Copy the code