继续我们的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), ), )), ], ), ); } }
样式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~"), ), ], ), ); } }
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 Statewith 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'), ), ], ), ), ], ), ), ); } }
总结:这块的关键leading,TabBar,TabBarView,BottomNavigationBar,BottomAppBar的使用,写法都是固定的,需要相互配合,多练吧~