继续我们的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<FormTestRoute1> {
@override
Widget build(BuildContext context) {
return Padding(
//上下左右各添加16像素补白
padding: EdgeInsets.all(16.0),
child: Column(
//显式指定对齐方式为左对齐,排除对齐干扰
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
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<FormTestRoute1> {
@override
Widget build(BuildContext context) {
return Padding(
//上下左右各添加16像素补白
padding: EdgeInsets.all(16.0),
child: Column(
//显式指定对齐方式为左对齐,排除对齐干扰
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
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 State<FormTestRoute1>
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: <Widget>[
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>[
// 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: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 38.0),
child: Row(
children: <Widget>[
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: <Widget>[
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的使用,写法都是固定的,需要相互配合,多练吧~
转载于:https://blog.51cto.com/liangxiao/2386257