Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

繼續我們的flutter之旅,今天學首頁怎麼寫,APP的首頁目前比較單一,都是下面幾個菜單,上面幾個菜單,或者側面一個我的,所以可以寫一個活的套用,以後就不用麻煩了。

前言:樣式自定義基本上都是一樣的,什麼圓角,什麼陰影,什麼旋轉,什麼漸變,總結一下以後別忘了。

樣式1:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 // TODO: implement build
 return new MaterialApp(
 title: "樣式佈局",
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text("樣式佈局"),
 ),
 body: new Center(
 child: new FormTestRoute1(),
 ),
 ),
 );
 }
}
class FormTestRoute1 extends StatefulWidget {
 @override
 _FormTestRouteState1 createState() => new _FormTestRouteState1();
}
class _FormTestRouteState1 extends State {
 @override
 Widget build(BuildContext context) {
 return Padding(
 //上下左右各添加16像素補白
 padding: EdgeInsets.all(16.0),
 child: Column(
 //顯式指定對齊方式為左對齊,排除對齊干擾
 crossAxisAlignment: CrossAxisAlignment.start,
 children: [
 Padding(
 //左邊添加8像素補白
 padding: const EdgeInsets.only(left: 8.0),
 child: Text("hi yun1"),
 ),
 Padding(
 //上下各添加8像素補白
 padding: const EdgeInsets.symmetric(vertical: 8.0),
 child: Text("hi yun2"),
 ),
 Padding(
 // 分別指定四個方向的補白
 padding: const EdgeInsets.fromLTRB(20.0, .0, 20.0, 20.0),
 child: Text("hi yun3"),
 ),
 DecoratedBox(
 decoration: BoxDecoration(
 gradient: LinearGradient(
 colors: [Colors.red, Colors.orange[700]]), //背景漸變
 borderRadius: BorderRadius.circular(3.0), //3像素圓角
 boxShadow: [
 //陰影
 BoxShadow(
 color: Colors.black54,
 offset: Offset(2.0, 2.0),
 blurRadius: 4.0)
 ]),
 child: Padding(
 padding: EdgeInsets.symmetric(horizontal: 80.0, vertical: 18.0),
 child: Text(
 "Login",
 style: TextStyle(color: Colors.white),
 ),
 )),
 ],
 ),
 );
 }
}
Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

樣式2:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 // TODO: implement build
 return new MaterialApp(
 title: "樣式佈局",
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text("樣式佈局"),
 ),
 body: new Center(
 child: new FormTestRoute1(),
 ),
 ),
 );
 }
}
class FormTestRoute1 extends StatefulWidget {
 @override
 _FormTestRouteState1 createState() => new _FormTestRouteState1();
}
class _FormTestRouteState1 extends State {
 @override
 Widget build(BuildContext context) {
 return Padding(
 //上下左右各添加16像素補白
 padding: EdgeInsets.all(16.0),
 child: Column(
 //顯式指定對齊方式為左對齊,排除對齊干擾
 crossAxisAlignment: CrossAxisAlignment.start,
 children: [
 Container(
 margin: EdgeInsets.only(
 top: 50.0, left: 120.0, right: 0.0, bottom: 50.0),
 //容器外補白
 constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0),
 //卡片大小
 decoration: BoxDecoration(
 //背景裝飾
 gradient: RadialGradient(
 //背景徑向漸變
 colors: [Colors.red, Colors.orange],
 center: Alignment.topLeft,
 radius: .98),
 boxShadow: [
 //卡片陰影
 BoxShadow(
 color: Colors.black54,
 offset: Offset(2.0, 2.0),
 blurRadius: 4.0)
 ]),
 transform: Matrix4.rotationZ(.2),
 //卡片傾斜變換
 alignment: Alignment.center,
 //卡片內文字居中
 child: Text(
 //卡片文字
 "5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),
 ),
 ),
 Container(
 margin: EdgeInsets.all(20.0), //容器外補白
 color: Colors.orange,
 child: Text("hi yun~"),
 ),
 Container(
 padding: EdgeInsets.all(20.0), //容器內補白
 color: Colors.orange,
 child: Text("hi yun~"),
 ),
 ],
 ),
 );
 }
}
Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

Scaffold:

大多數路由頁都會包含一個導航欄,有些路由頁可能會有抽屜菜單(Drawer)以及底部Tab導航菜單等。如果每個頁面都需要開發者自己手動去實現,這會是一件非常無聊的事。幸運的是,我們前面提到過,Flutter Material庫提供了一個Scaffold Widget,它是一個路由頁的骨架,可以非常容易的拼裝出一個完整的頁面。

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 // TODO: implement build
 return new MaterialApp(
 title: "Scaffold首頁",
 home: new Scaffold(
// appBar: new AppBar(
// title: new Text("Scaffold首頁"),
// ),
 body: new Center(
 child: new FormTestRoute1(),
 ),
 ),
 );
 }
}
class FormTestRoute1 extends StatefulWidget {
 @override
 _FormTestRouteState1 createState() => new _FormTestRouteState1();
}
class _FormTestRouteState1 extends State
 with SingleTickerProviderStateMixin {
 int _selectedIndex = 1;
 void _onItemTapped(int index) {
 setState(() {
 _selectedIndex = index;
 });
 }
 void _onAdd() {}
 TabController _tabController;
 List tabs = ["Yun1", "Yun2", "Yun3"];
 @override
 void initState() {
 // TODO: implement initState
 super.initState();
 _tabController = TabController(length: tabs.length, vsync: this);
 }
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: new Text("Scafford首頁"),
 leading: Builder(builder: (context) {
 return IconButton(
 icon: Icon(Icons.dashboard, color: Colors.white), //自定義圖標
 onPressed: () {
 // 打開抽屜菜單
 Scaffold.of(context).openDrawer();
 },
 );
 }),
 actions: [
 IconButton(
 icon: Icon(
 Icons.share,
 ),
 onPressed: () {},
 ),
 ],
 bottom: TabBar(
 controller: _tabController,
 tabs: tabs.map((e) => Tab(text: e)).toList(),
 ),
 ),
 drawer: new MyDrawer(),
 body: TabBarView(
 controller: _tabController,
 children: tabs.map((e) {
 return Container(
 alignment: Alignment.center,
 child: Text(
 e,
 textScaleFactor: 5,
 ),
 );
 }).toList(),
 ),
// bottomNavigationBar: BottomNavigationBar(
// items: [
// BottomNavigationBarItem(
// icon: Icon(Icons.home), title: new Text("Yun1")),
// BottomNavigationBarItem(
// icon: Icon(Icons.business), title: new Text("Yun2")),
// BottomNavigationBarItem(
// icon: Icon(Icons.school), title: new Text("Yun3")),
// ],
// currentIndex: _selectedIndex,
// fixedColor: Colors.blueGrey,
// onTap: _onItemTapped,
// ),
 bottomNavigationBar: BottomAppBar(
 color: Colors.white,
 shape: CircularNotchedRectangle(), // 底部導航欄打一個圓形的洞
 child: Row(
 children: [
 IconButton(icon: Icon(Icons.home)),
 SizedBox(), //中間位置空出
 IconButton(icon: Icon(Icons.business)),
 ],
 mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部導航欄橫向空間
 ),
 ),
 floatingActionButton: FloatingActionButton(
 child: Icon(Icons.add),
 onPressed: _onAdd,
 ),
 floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
 );
 }
}
// 抽屜
class MyDrawer extends StatelessWidget {
 const MyDrawer({
 Key key,
 }) : super(key: key);
 @override
 Widget build(BuildContext context) {
 return Drawer(
 child: MediaQuery.removePadding(
 context: context,
 // DrawerHeader consumes top MediaQuery padding.
 removeTop: true,
 child: Column(
 crossAxisAlignment: CrossAxisAlignment.start,
 children: [
 Padding(
 padding: const EdgeInsets.only(top: 38.0),
 child: Row(
 children: [
 Padding(
 padding: const EdgeInsets.symmetric(horizontal: 16.0),
 child: ClipOval(
 child: Image.asset(
 "imgs/avatar.png",
 width: 80,
 ),
 ),
 ),
 Text(
 "Wendux",
 style: TextStyle(fontWeight: FontWeight.bold),
 )
 ],
 ),
 ),
 Expanded(
 child: ListView(
 children: [
 ListTile(
 leading: const Icon(Icons.add),
 title: const Text('Add account'),
 ),
 ListTile(
 leading: const Icon(Icons.settings),
 title: const Text('Manage accounts'),
 ),
 ],
 ),
 ),
 ],
 ),
 ),
 );
 }
}
Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

總結:這塊的關鍵leading,TabBar,TabBarView,BottomNavigationBar,BottomAppBar的使用,寫法都是固定的,需要相互配合,多練吧~

Flutter第五期 - 樣式、Scaffold、TabBar、底部導航


分享到:


相關文章: