前言
這次對佈局進行優化,主要包含了首頁tabview pageview 以及新增幾個按鈕的操作過程.主要使用到stack層疊佈局,tabpview和pageview,tabview兩個頁面,一個關注,一個推薦,左右切換,pageview被包含在tabview裡面.
佈局優化
抖音的頂部appbar 是懸浮層疊展示,而flutter的層疊元件是stack, 因此最外面採用stack, 其次中間是tabview,分別是關注和推薦兩個選項卡,關注在沒有登入的時候會彈出一個提示需要認證登入的頁面,這裡加了兩個頁面,subscriptionScreen.dart,另外一個是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(), ); }
底部彈出提示認證頁面
在 onTap 方法裡
Scaffold.of(context).showBottomSheet<void>((BuildContext context) { return Login(); });
BottomSheet 是一個底部滑出的元件
new BottomSheet( onClosing: () {}, builder: (BuildContext context) { return new Text('aaa'); }, ),
通常很少直接使用 BottomSheet 而是使用 showModalBottomSheet。直接時候的時候看到的知識 builder 裡的內容。
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); });
具體詳細介紹參考官網.
關注頁面
整個頁面佈局,左右都有邊距,頂部也有邊距,所有采用Container包含,邊距使用padding: EdgeInsets.only(top: 150.0, left: 65.0, right: 65.0), 背景顏色 color: Color.fromRGBO(14, 15, 26, 1),依次image,另外使用sizebox佔用空間,
其他的中間層都是居中,所以採用center都是居中,另外登入按鈕是佔滿螢幕的,所以也採用SizeBox,並且把width:設定為double.infinity,這樣就佔滿螢幕,button採用預設的RaisedButton,在button的onpressed事件呼叫showBottomSheet
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(); }); }, ), ), ]), ); } }
登入頁面
佈局如下圖:
這個頁面整體佈局頂部,左右都有邊距,因此使用Container比較合適,設定背景顏色為color: Colors.white, 邊距設定為padding:EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0, bottom: 50.0),整體佈局採用Column,因為是上下佈局,因此Column 設定
全部程式碼如下:
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))))), ], ), ); } }
變更記錄
本次變更主要體現在首頁的選項卡設計,需要層疊展示,並且透明的採用appbar顯示出頂部的關注、推薦按鈕,另外新增了關注頁,登入頁,並且把底部按鈕以及右邊的按鈕都加上了觸發時間
接下來要完成的雙擊心形按鈕點贊,評論頁面,分享頁面,這些都可以採用showmodalbottomsheet方法開啟一個底部抽屜頁面
還有底部的首頁重新整理,訊息頁面,拍短視訊頁面,訊息頁面,我的個人資訊頁面
結語
請繼續關注本部落格,其他頁面持續更新完成,原始碼地址:https://github.com/WangCharlie/douyin,歡迎fork和star,謝謝!!!