Chapter 4-Use Flutter to roll a vibrato domestic version to see how cool it is
Tags: Flutter, Dart, Flutter Widget

Chapter 4-Use Flutter to roll a vibrato domestic version to see how cool it is charliewong Jun 1, 2020·6 min read

Foreword

This time to optimize the layout, mainly includes the home page tabview pageview and the operation process of adding a few buttons. Mainly used stack stack layout, tabpview and pageview, tabview two pages, one attention, one recommendation, left and right switching, pageview is included Inside tabview..

Layout optimization

The top appbar of Douyin is a floating stack display, and the stacking component of flutter is stack, so the outermost adopts stack, followed by the tabview in the middle, which are the two tabs of follow and recommend, and a prompt will pop up when there is no login Authentication login page, two pages are added here, subscriptionScreen.dart, and the other is loginScreen.dart

@override

Widget build(BuildContext context) {

return Scaffold(

//backgroundColor: Colors.transparent,

body: Stack(

//fit: StackFit.expand,

children: <Widget>[

TabBarView(

controller: _tabController,

children: <Widget>[

Subscription(),

PageView(

allowImplicitScrolling: true,

controller: _pageController,

children: <Widget>[

Trending(),

],

onPageChanged: (int index) {

setState(() {

currentIndex = index;

});

},

),

],

),

Column(

children: [

AppBar(

backgroundColor: Colors.transparent,

elevation: 0,

centerTitle: true,

leading: IconButton(

icon: Icon(Icons.tv),

onPressed: () {

print('点击了直播按钮');

}),

actions: <Widget>[

//导航栏右侧菜单

IconButton(

icon: Icon(Icons.search),

onPressed: () {

print('点击了搜索按钮');

}),

],

title: TabBar(

indicator: UnderlineTabIndicator(

borderSide: BorderSide(width: 2.0, color: Colors.white),

insets: EdgeInsets.symmetric(horizontal: 18.0)),

labelStyle: TextStyle(fontSize: 18),

isScrollable: true,

controller: _tabController,

tabs: toptabs,

onTap: (index) {

print(index);

},

),

)

],

),

],

),

bottomNavigationBar: bottomItems(),

);

}

Prompt authentication page pops up at the bottom

In the onTap method

Scaffold.of(context).showBottomSheet<void>((BuildContext context) {

return Login();

});

BottomSheet is a component that slides out at the bottom

new BottomSheet(

onClosing: () {},

builder: (BuildContext context) {

return new Text('aaa');

},

),

Usually it is rare to use BottomSheet directly but showModalBottomSheet. The content in the knowledge builder that you see when you are directly。

Future<T> showModalBottomSheet <T>({

@required BuildContext context,

@required WidgetBuilder builder

});

看一个示例

new MaterialButton(

color: Colors.blue,

child: new Text('点我'),

onPressed: () {

showModalBottomSheet(

context: context,

builder: (BuildContext context) {

return new Container(

height: 300.0,

child: new Image.network(this.imgurl),

);

},

).then((val) {

print(val);

});

Follow the page

The entire page layout has margins on the left and right, and margins on the top. All are included in the Container. The margins use padding: EdgeInsets.only (top: 150.0, left: 65.0, right: 65.0), background color: Color.fromRGBO 14, 15, 26, 1), followed by image, and using sizebox to take up space，

The other middle layers are centered, so center is centered, and the login button fills the screen, so SizeBox is also used, and width: is set to double.infinity, so that it fills the screen, the button uses the default RaisedButton , Call showBottomSheet in the onpressed event of the button

import 'package:flutter/material.dart';

import 'package:flutter_app/Screens/loginScreen.dart';

class Subscription extends StatefulWidget {

@override

State<StatefulWidget> createState() => _SubscriptionState();

}

class _SubscriptionState extends State<Subscription>

with TickerProviderStateMixin {

final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

@override

Widget build(BuildContext context) {

return Container(

padding: EdgeInsets.only(top: 150.0, left: 65.0, right: 65.0),

color: Color.fromRGBO(14, 15, 26, 1),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: <Widget>[

Image(image: AssetImage("assets/images/int_1581491273221.png")),

SizedBox(height: 20),

Center(

child: Text(

'你还没有登录',

style: TextStyle(

color: Colors.white,

fontSize: 20.0,

fontWeight: FontWeight.w400),

),

),

SizedBox(height: 10),

Center(

child: Text(

'登录账号，查看你关注的精彩内容',

style: TextStyle(

color: Color.fromRGBO(253, 253, 253, 0.6),

fontSize: 14.0,

fontWeight: FontWeight.w400),

),

),

SizedBox(height: 20),

SizedBox(

width: double.infinity,

child: RaisedButton(

color: Color.fromRGBO(252, 1, 86, 1),

child: Text(

'登录',

style: TextStyle(color: Colors.white),

),

onPressed: () {

Scaffold.of(context)

.showBottomSheet<void>((BuildContext context) {

return Login();

});

},

),

),

]),

);

}

}

登录页面

布局如下图：

The top of the overall layout of this page has margins on both sides, so it is more appropriate to use Container. Set the background color to color: Colors.white, and the margin to padding: EdgeInsets.only (top: 25.0, left: 25.0, right: 25.0, bottom: 50.0), the overall layout uses Column, because it is the top and bottom layout, so Column sets crossAxisAlignment: CrossAxisAlignment.start,

the top layout is a clear icon button on the left, and a help button on the right, so use Row layout and set Row ’s mainAxisAlignment: MainAxisAlignment.spaceBetween, so that the layout is left and right, the other uses the SizeBox placeholder in turn, and the Center is used to display the text control in the middle. The login part at the bottom contains the label hyperlink, so it is more appropriate to use RichText, including TextSpan.:

import 'package:flutter/gestures.dart';

import 'package:flutter/material.dart';

import 'package:url_launcher/url_launcher.dart';

class Login extends StatefulWidget {

@override

State<StatefulWidget> createState() => _LoginState();

}

class _LoginState extends State<Login> {

TapGestureRecognizer _myTapGestureRecognizer;

@override

void initState() {

super.initState();

_myTapGestureRecognizer = TapGestureRecognizer()

..onTap = () {

launch('https://open.douyin.com/platform');

};

}

@override

void dispose() {

_myTapGestureRecognizer.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return Container(

color: Colors.white,

padding:

EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0, bottom: 50.0),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

Row(

mainAxisAlignment: MainAxisAlignment.spaceBetween,

children: [

IconButton(

icon: Icon(Icons.clear),

onPressed: () {

Navigator.pop(context);

},

color: Colors.black,

),

Text('帮助', style: TextStyle(color: Colors.black)),

],

),

SizedBox(

height: 150.0,

),

Center(

child: Text('180****2520',

style: TextStyle(color: Colors.black, fontSize: 38)),

),

Center(

child: Text('认证服务由中国电信提供',

style: TextStyle(

color: Color.fromRGBO(53, 53, 53, 1), fontSize: 12)),

),

SizedBox(

height: 50.0,

),

SizedBox(

width: double.infinity,

child: RaisedButton(

color: Color.fromRGBO(252, 1, 86, 1),

child: Text(

'本机号码一键登录',

style: TextStyle(color: Colors.white),

),

onPressed: () {

showBottomSheet(

context: context, builder: (context) => Login());

},

),

),

SizedBox(

height: 2.0,

),

SizedBox(

width: double.infinity,

child: OutlineButton(

color: Color.fromRGBO(252, 1, 86, 1),

child: Text(

'其他手机号码登录',

style: TextStyle(color: Colors.black),

),

onPressed: () {

showBottomSheet(

context: context, builder: (context) => Login());

},

),

),

SizedBox(

height: 5.0,

),

Center(

child: RichText(

text: TextSpan(

children: [

TextSpan(

text: '登录即表明同意',

style: TextStyle(color: Color.fromRGBO(53, 53, 53, 0.8)),

),

TextSpan(text: ' '),

TextSpan(

text: '用户协议',

style: TextStyle(color: Color.fromRGBO(0, 164, 219, 0.8)),

),

TextSpan(text: ' '),

TextSpan(

text: '和',

style: TextStyle(color: Color.fromRGBO(53, 53, 53, 0.8)),

),

TextSpan(text: ' '),

TextSpan(

text: '隐私政策',

style: TextStyle(color: Color.fromRGBO(0, 164, 219, 0.8)),

),

],

),

)),

Center(

child: RichText(

text: TextSpan(

children: [

TextSpan(

text: '以及',

style: TextStyle(color: Color.fromRGBO(53, 53, 53, 0.8)),

),

TextSpan(text: ' '),

TextSpan(

text: '《中国电信认证服务条款》',

style: TextStyle(color: Color.fromRGBO(0, 164, 219, 0.8)),

recognizer: _myTapGestureRecognizer),

],

),

)),

Expanded(

flex: 1,

child: Center(

heightFactor: 25.0,

child: Text('其他方式登录',

style:

TextStyle(color: Color.fromRGBO(0, 164, 219, 0.8))))),

],

),

);

}

}

change log

This change is mainly reflected in the tab design on the home page, which needs to be displayed in a cascade, and the appbar is used to transparently display the follow and recommend buttons at the top. In addition, a follow page and login page are added, and the bottom button and the right button are added. Trigger time

Next, double-click the heart-shaped button to complete the like, comment page, share page, these can use the showmodalbottomsheet method to open a bottom drawer

There are also home page refresh at the bottom, message page, short video page, message page, my personal information page

Conclusion

Please continue to follow this blog, other pages continue to be updated, source code address：https://github.com/WangCharlie/douyin，welcome to fork and star，thanks！！！