Flutter combat 1: complete a main interface with a sidebar

After a week of study, many friends who have read Notes 1-8 have started to write their own APPs. I can’t bear this enthusiasm and want to develop an APP for fun. So, from this article Starting from imitating an APP, the project starts from 0, adds some content to each article, and completes the APP bit by bit. The code of each iteration will be uploaded to my git repository.

In view of my more than 2 weeks of Flutter code experience, the thinking of the code structure may not be as stable as that of a veteran with many years of development experience. If there is any bad writing, please give me advice.

Tasks to be completed in this article

As shown in the figure above, this article will build a HomePage, add a sidebar entry in the upper left corner, and enter other pages through the sidebar.

first step

Create projects and folders. Open vscode, go to a path and enter the command:

flutter create appbyflutter

Prepare the project directory as shown in the figure:

program directory

Since there are not many things used in the development of the first article, first simply add an images file to the project directory to store the APP default image. Add a pages folder under the default lib folder to store each page.

second step

Use main.dart only as the entry of the APP, and assume the functions of page entry and routing:

main.dart does not write page code

Since the APP has more than one page, in order to facilitate maintenance and management, all page codes are transferred to the pages folder, and main.dart handles the APP main page entry, routing and a series of initializations (such as automatic login, entry animation etc.) tasks. The front-end masters who have experience in vue and react development should be familiar with it. Doing so can decouple the main program and the page. Of course, this article has not used routing yet, so I won’t write the routing code for now. Students who can’t wait to learn about routing can Refer to the first APP or English reading comprehension of the front-end master .

third step

home page

As shown in the first step, two files are added to the pages folder: home_page.dart and other_page.dart , where home_page.dart is the main page of the APP, and other_page.dart is the page to be developed later.

Note that in the function of the second step runapp(), it is used MaterialApp(), which means that all page controls of the program APP are matched with the Material style by default.

Since the main page will dynamically reference various controls, the StatefulWidget type can meet the page requirements. Break down the page structure from the following diagram:

Main page structure diagram

First look at the stateful control on the left of the picture HomePage, which is the top-level package of the entire page, and a Scaffoldscaffold is placed Scaffoldin it, which has very rich properties, which can be placed in the sidebar button Drawercontrol, page title AppBarcontrol and bodyparts, so paste the following code:

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("CYC"), backgroundColor: Colors.redAccent,),  //头部的标题AppBar
      drawer: new Drawer(),  //侧边栏按钮Drawer
      body: new Center(  //中央内容部分body
        child: new Text('HomePage',style: new TextStyle(fontSize: 35.0),),
      ),
    );
  }
}

OK, the page on the left is so easily built. To achieve the expanded sidebar in the picture on the right, it is very simple, Drawerjust plug something into the control.

Sidebar

Let's first illustrate the structure of the sidebar:

Diagram of sidebar structure

  • From top to bottom, the entire sidebar has a list of account numbers and several function items + dividing lines. It is easy to think of using layout controls ListView.

  • In the account information area, there are account avatars, fan avatars, account text information, and background images. We can use the controls in the Material control library UserAccountsDrawerHeaderto implement this.

  • Needless to say, the following function list items ListTitleare properly controlled, and the dividing line can be directly Dividerused.

So, we new Drawer()add the following code to it:

//侧边栏填充内容
drawer: new Drawer(     //侧边栏按钮Drawer
        child: new ListView(
          children: <Widget>[
            new UserAccountsDrawerHeader(   //Material内置控件
              accountName: new Text('CYC'), //用户名
              accountEmail: new Text('[email protected]'),  //用户邮箱
              currentAccountPicture: new GestureDetector( //用户头像
                onTap: () => print('current user'),
                child: new CircleAvatar(    //圆形图标控件
                  backgroundImage: new NetworkImage('https://upload.jianshu.io/users/upload_avatars/7700793/dbcf94ba-9e63-4fcf-aa77-361644dd5a87?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240'),//图片调取自网络
                ),
              ),
              otherAccountsPictures: <Widget>[    //粉丝头像
                new GestureDetector(    //手势探测器,可以识别各种手势,这里只用到了onTap
                  onTap: () => print('other user'), //暂且先打印一下信息吧,以后再添加跳转页面的逻辑
                  child: new CircleAvatar(
                    backgroundImage: new NetworkImage('https://upload.jianshu.io/users/upload_avatars/10878817/240ab127-e41b-496b-80d6-fc6c0c99f291?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240'),
                  ),
                ),
                new GestureDetector(
                  onTap: () => print('other user'),
                  child: new CircleAvatar(
                    backgroundImage: new NetworkImage('https://upload.jianshu.io/users/upload_avatars/8346438/e3e45f12-b3c2-45a1-95ac-a608fa3b8960?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240'),
                    ),
                ),
              ],
              decoration: new BoxDecoration(    //用一个BoxDecoration装饰器提供背景图片
                image: new DecorationImage(
                  fit: BoxFit.fill,
                  // image: new NetworkImage('https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/images/lake.jpg')
                  //可以试试图片调取自本地。调用本地资源,需要到pubspec.yaml中配置文件路径
                  image: new ExactAssetImage('images/lake.jpg'),
                ),
              ),
            ),
            new ListTile(   //第一个功能项
              title: new Text('First Page'),
              trailing: new Icon(Icons.arrow_upward),
              onTap: () {
                Navigator.of(context).pop();
                Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new SidebarPage()));
              }
            ),
            new ListTile(   //第二个功能项
              title: new Text('Second Page'),
              trailing: new Icon(Icons.arrow_right),
              onTap: () {
                Navigator.of(context).pop();
                Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new SidebarPage()));
              } 
            ),
            new ListTile(   //第二个功能项
              title: new Text('Second Page'),
              trailing: new Icon(Icons.arrow_right),
              onTap: () {
                Navigator.of(context).pop();
                Navigator.of(context).pushNamed('/a');
              } 
            ),
            new Divider(),    //分割线控件
            new ListTile(   //退出按钮
              title: new Text('Close'),
              trailing: new Icon(Icons.cancel),
              onTap: () => Navigator.of(context).pop(),   //点击后收起侧边栏
            ),
          ],
        ),
      )

The above code uses a lot of unfamiliar controls, such as UserAccountsDrawerHeader , GestureDetector , BoxDecoration , NetworkImage , ExactAssetImage , etc. I won’t introduce them one by one here. Please refer to the official reading and comprehension question bank for their characteristics and usage . I was also confused at the beginning Forced, you can simply recite these built-in controls. It is possible that due to the increase in the complexity of the page, you may take them out and package them separately, and you can use them.

You can try the gesture of swiping from the left edge of the screen to the right. Did you find that you can pull out the sidebar? Swipe right again to retract the sidebar. I didn't add any code for gesture events. This is Drawerthe property of the control itself. It is the same as the material style animation effect of the control. The built-in control also has its own default gesture. I can faintly hear ~ native developers crying and fainting in the toilet ,Hahaha

the fourth step

Function buttons trigger page jumps.

First of all, we need to create a subpage, so under the pages folder, I created another other_page.dart file. To jump to other_page.dart from HomePage.dart , you also need to quote other_page.dart in HomePage.dart . then:

page file reference

Then enter the code in other_page.dart :

import 'package:flutter/material.dart';

class OtherPage extends StatelessWidget {

  final String pageText;    //定义一个常量,用于保存跳转进来获取到的参数

  OtherPage(this.pageText);    //构造函数,获取参数

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text(pageText),),    //将参数当作页面标题
      body: new Center(
        child: new Text('pageText'),
      ),
    );
  }
}

Flutter requires that the transferred page must define a constant in advance to allocate space, and implant this parameter in the constructor to capture the parameter value passed from the outside.

trigger jump

Add the code to click to jump to the two controls of First Page and Second PageListTile :

new ListTile(
    title: new Text('First Page'),
    trailing: new Icon(Icons.arrow_upward),
    onTap: () {
        Navigator.of(context).pop();  //点击后收起侧边栏
        Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new OtherPage('First Page')));  //进入OtherPage页面,传入参数First Page
        }
 ),
new ListTile(
    title: new Text('Second Page'),
    trailing: new Icon(Icons.arrow_right),
    onTap: () {
        Navigator.of(context).pop();
        Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new OtherPage('Second Page')));
    } 
 ),

onTap()There is a sentence in the event in the above code Navigator.of(context).pop();, which means that the sidebar should be collapsed before entering a new page. If there is no such code, even if you enter a new page and come back, the sidebar will still be unfolded. This experience is anti-human, so write it down~boy.

Summarize

Since I didn’t go into detail about what the positioning and design of the product is, you may feel a little confused. Why is this sidebar layout instead of the top + bottom tab bar style commonly used by many social apps? Don’t worry. , our next implementation. What are the benefits of a sidebar? To save space, if more important functional controls (such as a music player) need to be placed at the bottom, it is a good solution to put page switching logic in the sidebar. The content of this article is actually very simple. It mainly introduces you to know a few common controls. You don’t need to adjust CSS, and you don’t need to think about the realization of complex interaction logic caused by bubbling events. This is the charm of Flutter . It is simple but not simple. I believe that after reading it , I am more confident in developing my own APP. Well, that’s it for today. Thank you for your support. Please pay attention to my Flutter circle and contribute more. You can also join the flutter Chinese community (official QQ group: 338252156) to grow together, thank you everyone~

Guess you like

Origin blog.csdn.net/qq_27981847/article/details/88037441