1.有状态组件StatefulWidget
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(primarySwatch: Colors.blue), home: const HomePage()); } } // 有状态组件 class HomePage extends StatefulWidget { const HomePage({super.key}); @override //实现抽象方法 State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { int _num = 0; final List<String> list = []; @override Widget build(BuildContext context) { print(_num); return Scaffold( appBar: AppBar( title: const Text("flutter app"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "$_num", style: Theme.of(context).textTheme.headlineLarge, ), const SizedBox( height: 40, ), ElevatedButton( onPressed: () { setState(() { _num++; }); }, child: const Text("增加")) ], ), ), //浮动的按钮 floatingActionButton: FloatingActionButton( onPressed: () {
//通过setState来更新视图
setState(() { _num++; }); },
child: const Icon(Icons.add), ), ); } }
2.自定义底部导航bottomNavigationBar
import 'package:flutter/material.dart'; import 'package:flutter02/pages/tabs/cate.dart'; import 'package:flutter02/pages/tabs/message.dart'; import 'package:flutter02/pages/tabs/setting.dart'; import 'package:flutter02/pages/tabs/home.dart'; import 'package:flutter02/pages/tabs/user.dart'; class Tabs extends StatefulWidget { const Tabs({super.key}); @override State<Tabs> createState() => _TabsState(); } class _TabsState extends State<Tabs> { int _currentIndex = 0; List list = const [ HomePage(), CatePage(), MessagePage(), SettingPage(), UserPage(), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("flutter app"), ), body: list[_currentIndex], bottomNavigationBar: BottomNavigationBar( iconSize: 40, //底部菜单大小 currentIndex: _currentIndex, //当前的索引 fixedColor: Colors.red, //选择的颜色 type: BottomNavigationBarType.fixed, //底部有4个或4个以上菜单需要配置 onTap: (index) => { setState( () { _currentIndex = index; }, ) }, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"), BottomNavigationBarItem( icon: Icon( Icons.category, ), label: "分类"), BottomNavigationBarItem( icon: Icon( Icons.message_rounded, ), label: "消息"), BottomNavigationBarItem( icon: Icon( Icons.settings, ), label: "设置"), BottomNavigationBarItem( icon: Icon( Icons.person_2, ), label: "用户"), ]), floatingActionButton: Container( padding: const EdgeInsets.all(8), margin: const EdgeInsets.only(top: 32), height: 60, width: 60, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30)), child: FloatingActionButton( onPressed: () { setState(() { _currentIndex = 2; }); }, backgroundColor: _currentIndex == 2 ? Colors.yellow : Colors.blue, child: const Icon(Icons.add), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, //调整浮动按钮的位置 ); } }
3.侧边栏组件
import 'package:flutter/material.dart'; import 'package:flutter02/pages/tabs/cate.dart'; import 'package:flutter02/pages/tabs/message.dart'; import 'package:flutter02/pages/tabs/setting.dart'; import 'package:flutter02/pages/tabs/home.dart'; import 'package:flutter02/pages/tabs/user.dart'; class Tabs extends StatefulWidget { const Tabs({super.key}); @override State<Tabs> createState() => _TabsState(); } class _TabsState extends State<Tabs> { int _currentIndex = 0; List list = const [ HomePage(), CatePage(), MessagePage(), SettingPage(), UserPage(), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("flutter app"), ), body: list[_currentIndex], drawer: const Drawer( //配置侧边栏 child: Column( children: [ Row( children: [ Expanded( // UserAccountsDrawerHeader flex: 1, child: UserAccountsDrawerHeader( //使用内置配置 currentAccountPicture: CircleAvatar( backgroundImage: NetworkImage( "https://p1.itc.cn/q_70/images03/20210817/1203acff86d74d7e8cd644d05d3e5525.jpeg"), ), accountName: Text("张三"), //用户名 accountEmail: Text("igqq.com"), //邮箱 decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.cover, image: NetworkImage( "https://pic.616pic.com/bg_w1180/00/23/16/1KY6cAGuC9.jpg"))), )) ], ), ListTile( leading: CircleAvatar( child: Icon(Icons.people), ), title: Text('个人中心'), ), Divider(), ListTile( leading: Icon(Icons.settings), title: Text('系统设置'), ), Divider(), ], )), endDrawer: Drawer(child: Text("又称侧边栏")), bottomNavigationBar: BottomNavigationBar( iconSize: 40, //底部菜单大小 currentIndex: _currentIndex, //当前的索引 fixedColor: Colors.red, //选择的颜色 type: BottomNavigationBarType.fixed, //底部有4个或4个以上菜单需要配置 onTap: (index) => { setState( () { _currentIndex = index; }, ) }, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"), BottomNavigationBarItem( icon: Icon( Icons.category, ), label: "分类"), BottomNavigationBarItem( icon: Icon( Icons.message_rounded, ), label: "消息"), BottomNavigationBarItem( icon: Icon( Icons.settings, ), label: "设置"), BottomNavigationBarItem( icon: Icon( Icons.person_2, ), label: "用户"), ]), floatingActionButton: Container( padding: const EdgeInsets.all(8), margin: const EdgeInsets.only(top: 32), height: 60, width: 60, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30)), child: FloatingActionButton( onPressed: () { setState(() { _currentIndex = 2; }); }, backgroundColor: _currentIndex == 2 ? Colors.yellow : Colors.blue, child: const Icon(Icons.add), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, //调整浮动按钮的位置 ); } } // DrawerHeader( // //配置侧边栏顶部 // decoration: BoxDecoration( // // color: Colors.yellow, // image: DecorationImage( // fit: BoxFit.cover, // image: NetworkImage( // "https://pic.616pic.com/bg_w1180/00/23/16/1KY6cAGuC9.jpg"))), // child: Column( // children: [ // ListTile( // leading: CircleAvatar( // backgroundImage: NetworkImage( // "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202008%2F13%2F20200813151914_vk2eR.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1680700489&t=219227023128b19f44b83679a2fd3074"), // ), // title: Text( // '张三', // style: TextStyle(color: Colors.white), // ), // ), // ListTile( // title: Text("邮箱:xxxqq.com"), // ), // ], // )),
4.头部TabBar组件
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, //去掉debug title: "flutter app", theme: ThemeData(primarySwatch: Colors.blue), home: const HomePage()); } } class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin { late TabController _tabController; @override //生命周期函数,组件初始化时触发 void initState() { // TODO: implement initState super.initState(); _tabController = TabController(length: 3, vsync: this); //指定长度 //监听_tabController的改变事件,获取索引值 _tabController.addListener(() { // print(_tabController.index);//回触发两次 // if (_tabController.animation!.value == _tabController.index) { // print(_tabController.index); // } }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( //配置导航左侧图标 icon: const Icon(Icons.menu), onPressed: () { print("asdsdfds"); }, ), backgroundColor: Colors.yellow, //背景颜色 actions: [ //右侧的图标,可以配置多个 IconButton(onPressed: () {}, icon: const Icon(Icons.search_sharp)) ], bottom: TabBar( controller: _tabController, indicatorColor: Colors.red, //指示器的颜色 indicatorWeight: 3, //指示器的高度 indicatorPadding: const EdgeInsets.all(5), //指示器的边距 labelColor: Colors.blue, //选中的颜色 unselectedLabelColor: Colors.green, //未选择的颜色 labelStyle: const TextStyle(fontSize: 16), //设置样式 onTap: (index) { //只能监听点击事件 print(index); }, tabs: const [ //配置tabs Tab( child: Text("关注"), ), Tab( child: Text("热门"), ), Tab( child: Text("视频"), ), ]), title: const Text("FLutter app")), body: TabBarView(controller: _tabController, children: const [ //与TabBar对应 Text("我是关注"), Text("我是热门"), Text("我是视频"), ]), ); } }
5.路由
5.1基本路由
import 'package:flutter/material.dart'; import '../search.dart'; import '../form.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return Center( child: Column( children: [ ElevatedButton( onPressed: () { Navigator.of(context) //路由跳转页面 .push(MaterialPageRoute(builder: (BuildContext context) { return const SearchPage(); })); }, child: const Text("跳转搜索")), ElevatedButton( onPressed: () { Navigator.of(context) //跳转传值 .push(MaterialPageRoute(builder: (BuildContext context) { return const FromPage(title: "表单页面", id: 13); })); }, child: const Text("跳转表单")) ], ), ); } } import 'package:flutter/material.dart'; class SearchPage extends StatefulWidget { const SearchPage({super.key}); @override State<SearchPage> createState() => _SearchPageState(); } class _SearchPageState extends State<SearchPage> { @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { Navigator.pop(context); //返回到上一页 }, child: const Icon(Icons.home), ), appBar: AppBar( title: const Text("搜索页面"), ), body: const Center(child: Text("搜索页面")), ); } }import 'dart:ffi';
//接受传递的参数
import 'package:flutter/material.dart';
class FromPage extends StatefulWidget { final String title; //接受路由传参 final int id; const FromPage({super.key, this.title = "新闻", required this.id});
@override State<FromPage> createState() => _FromPageState(); }
class _FromPageState extends State<FromPage> { @override void initState() { // TODO: implement initState super.initState(); print(widget.id); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("表单页面"), ), body: Text(widget.title), //接受路由传参 ); } }
5.2命名路由
//路由配置route.dart文件 import 'package:flutter/material.dart'; import 'package:flutter02/pages/mine.dart'; import 'package:flutter02/pages/news.dart'; import 'package:flutter02/pages/search.dart'; import 'package:flutter02/pages/shop.dart'; //定义命名路由 Map routes = { "/": (context) => const NewPage(), "/shop": (context) => const ShopPage(), "/search": (context) => const SearchPage(), "/mine": (context, {arguments}) => MinePage(arguments: arguments), }; // 路由配置,跳转路由时执行,全局的路由跳转前置处理逻辑。 var onGenerateRoute = (RouteSettings settings) { final String? name = settings.name; final Function? pageContentBuilder = routes[name]; if (pageContentBuilder != null) { if (settings.arguments != null) { final Route route = MaterialPageRoute( builder: (context) => pageContentBuilder(context, arguments: settings.arguments)); return route; } else { final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context)); return route; } } else { return null; } }; //入口文件main.dart import 'package:flutter/material.dart'; import 'package:flutter02/pages/tabs.dart'; import './routers/route.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, //去掉debug title: "flutter app", theme: ThemeData(primarySwatch: Colors.blue), initialRoute: "/new", //初始化路由 onGenerateRoute: onGenerateRoute, //路由配置,跳转路由时执行 ); } } //路由传参文件 import 'package:flutter/material.dart'; class NewPage extends StatefulWidget { const NewPage({ super.key, }); @override State<NewPage> createState() => _NewPageState(); } class _NewPageState extends State<NewPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("新闻页面"), ), body: Column( children: [ ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/shop"); //命名路由跳转 }, child: const Text("跳转购物页面")), ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/mine", arguments: {"title": "我是命名路由", "id": 20}); //命名路由跳转传值 }, child: const Text("跳转我的页面")), ], ) //接受路由传参 ); } } //路由接受参数文件 import 'package:flutter/material.dart'; class MinePage extends StatefulWidget { final Map arguments; const MinePage({super.key, required this.arguments}); @override State<MinePage> createState() => _MinePageState(); } class _MinePageState extends State<MinePage> { @override void initState() { // TODO: implement initState super.initState(); print(widget.arguments); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("我的页面"), ), body: const Text("我的页面"), //接受路由传参 ); } }
5.3 路由替换
//main.dart入口文件 import 'package:flutter/material.dart'; import 'package:flutter02/pages/tabs.dart'; import './routers/route.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, //去掉debug title: "flutter app", theme: ThemeData(primarySwatch: Colors.blue), initialRoute: "/", //初始化路由 onGenerateRoute: onGenerateRoute, //路由配置,跳转路由时执行 ); } } //路由配置文件 // import 'package:flutter/material.dart'; //配置ios风格步骤 //1.删除material.dart 引入cupertino.dart 将MaterialPageRoute替换成CupertinoPageRoute import 'package:flutter/cupertino.dart'; import 'package:flutter02/pages/mine.dart'; import 'package:flutter02/pages/news.dart'; import 'package:flutter02/pages/search.dart'; import 'package:flutter02/pages/shop.dart'; import 'package:flutter02/pages/user/enter.dart'; import 'package:flutter02/pages/user/login.dart'; import 'package:flutter02/pages/user/register1.dart'; import 'package:flutter02/pages/user/register2.dart'; import 'package:flutter02/pages/user/register3.dart'; //定义命名路由 Map routes = { // "/": (context) => const NewPage(),//根页面 "/": (context) => const EnterPage(), "/shop": (context) => const ShopPage(), "/search": (context) => const SearchPage(), "/mine": (context, {arguments}) => MinePage(arguments: arguments), "/login": (context) => const LoginPage(), "/register1": (context) => const Register1(), "/register2": (context) => const Register2(), "/register3": (context) => const Register3(), }; // 路由配置,跳转路由时执行 var onGenerateRoute = (RouteSettings settings) { final String? name = settings.name; final Function? pageContentBuilder = routes[name]; if (pageContentBuilder != null) { if (settings.arguments != null) { final Route route = CupertinoPageRoute( builder: (context) => pageContentBuilder(context, arguments: settings.arguments)); return route; } else { final Route route = CupertinoPageRoute(builder: (context) => pageContentBuilder(context)); return route; } } else { return null; } }; //根页面 import 'package:flutter/material.dart'; class EnterPage extends StatefulWidget { const EnterPage({super.key}); @override State<EnterPage> createState() => _EnterPageState(); } class _EnterPageState extends State<EnterPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("登录入口页面"), ), body: Column( children: [ Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/login"); //命名路由跳转 }, child: const Text("登录")), ), Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/register1"); //命名路由跳转 }, child: const Text("注册1")), ), ], ), ); } } //登录页面 import 'package:flutter/material.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("登录页面"), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text("登录"))) //接受路由传参 ); } } //注册页面1 import 'package:flutter/material.dart'; class Register1 extends StatefulWidget { const Register1({super.key}); @override State<Register1> createState() => _Register1State(); } class _Register1State extends State<Register1> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("注册第一步"), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/register2"); }, child: const Text("下一步"))) //接受路由传参 ); } } //注册2 import 'package:flutter/material.dart'; class Register2 extends StatefulWidget { const Register2({super.key}); @override State<Register2> createState() => _Register2State(); } class _Register2State extends State<Register2> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("注册第二步"), ), body: Center( child: ElevatedButton( onPressed: () { // Navigator.pushNamed(context, "/register3"); //替换路由,返回时直接到第一步 Navigator.of(context).pushReplacementNamed("/register3"); }, child: const Text("下一步"))) //接受路由传参 ); } } //注册3 import 'package:flutter/material.dart'; import 'package:flutter02/pages/user/enter.dart'; class Register3 extends StatefulWidget { const Register3({super.key}); @override State<Register3> createState() => _Register3State(); } class _Register3State extends State<Register3> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("注册第三步"), ), body: Center( child: ElevatedButton( onPressed: () { // Navigator.pushNamed(context, "/"); //跳转到根页面 Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( builder: (context) => const EnterPage()), (route) => false); }, child: const Text("完成注册"))) //接受路由传参 ); } }
6.内置弹框组件dialog以及自定义弹框
import 'package:fluttertoast/fluttertoast.dart'; import './myDialog.dart'; import 'package:flutter/material.dart'; class DialogPage extends StatefulWidget { const DialogPage({super.key}); @override State<DialogPage> createState() => _DialogPageState(); } class _DialogPageState extends State<DialogPage> { late bool result; late int value; void _alertDialog() async { result = await showDialog( //获取对话框 数据 context: context, builder: (context) { return AlertDialog( title: const Text("提示"), content: const Text("您确定要删除当前文件吗?"), actions: <Widget>[ TextButton( child: const Text("取消"), onPressed: () => Navigator.of(context).pop(), //关闭对话框 ), TextButton( child: const Text("确认"), onPressed: () { // ... 执行删除操作 Navigator.of(context).pop(true); //关闭对话框 }, ), ], ); }); print(result); } //选择弹框 void _selectDialog() async { value = await showDialog( barrierDismissible: false, //点击遮挡层弹框关闭控制 context: context, builder: (context) { return SimpleDialog(title: const Text('请选择语言'), children: [ SimpleDialogOption( onPressed: () { // 返回1 Navigator.pop(context, 1); }, child: const Padding( padding: EdgeInsets.symmetric(vertical: 6), child: Text('中文简体'), ), ), SimpleDialogOption( onPressed: () { // 返回1 Navigator.pop(context, 2); }, child: const Padding( padding: EdgeInsets.symmetric(vertical: 6), child: Text('美式英语'), ), ), ]); }); print(value); } //底部弹框 void _showBottomSheetDialog() async { var result = await showModalBottomSheet( context: context, builder: (context) { return SizedBox( height: 280, child: Column(children: [ ListTile( title: const Text("取消"), onTap: () { Navigator.of(context).pop(1); }, ), const Divider(), ListTile( title: const Text("收藏"), onTap: () { Navigator.of(context).pop(2); }, ), const Divider(), ListTile( title: const Text("分享"), onTap: () { Navigator.of(context).pop(3); }, ), const Divider(), ]), ); }); print(result); } //toast弹窗使用第三方插件 void _toast() { Fluttertoast.showToast( msg: "提示信息", toastLength: Toast.LENGTH_LONG, //设置弹窗消失的时间针对android gravity: ToastGravity.CENTER, timeInSecForIosWeb: 2, //设置弹窗消失的时间ios backgroundColor: Colors.black, textColor: Colors.white, fontSize: 16.0); } //自定义dialog void _myDialog() { //需要包裹在showDialog组件中 showDialog( context: context, builder: (context) { return MyDialog( title: "提示!", content: "我是一段提示信息", onTap: () { Navigator.pop(context); }, ); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("弹窗页面"), ), body: Column(children: [ Center( child: ElevatedButton( onPressed: _alertDialog, child: const Text("打开对话框")), ), const SizedBox(height: 20), Center( child: ElevatedButton( onPressed: _selectDialog, child: const Text("打开选择对话框")), ), const SizedBox(height: 20), Center( child: ElevatedButton( onPressed: _showBottomSheetDialog, child: const Text("打开底部对话框")), ), const SizedBox(height: 20), Center( child: ElevatedButton(onPressed: _toast, child: const Text("toast弹框")), ), const SizedBox(height: 20), Center( child: ElevatedButton( onPressed: _myDialog, child: const Text("自定义dialog")), ), ]), //接受路由传参 ); } } //自定义弹框 import 'package:flutter/material.dart'; //自定义dialog需要继承Dialog类 class MyDialog extends Dialog { final String title; final String content; final Function()? onTap; const MyDialog( {super.key, required this.title, required this.content, this.onTap}); // 实现类中的方法 @override Widget build(BuildContext context) { return Material( type: MaterialType.transparency, //设置透明度 child: Center( //要用center组件包裹,不然会全屏 child: Container( height: 200, width: 260, color: Colors.white, child: Column(children: [ Padding( padding: EdgeInsets.all(5), child: Stack(children: [ Align( alignment: Alignment.centerLeft, child: Text( title, style: TextStyle(fontSize: 18), ), ), Align( alignment: Alignment.centerRight, child: InkWell( //套InkWell组件给元素添加点击事件 onTap: onTap, child: const Icon(Icons.close), ), ) ]), ), const Divider(), Container( padding: const EdgeInsets.all(10), child: Text(content), ) ]), )), ); } }
7.页面切换组件pageView及轮播组件的封装
7.1 pageView组件
import 'package:flutter/material.dart'; class PageViewPage extends StatefulWidget { const PageViewPage({super.key}); @override State<PageViewPage> createState() => _PageViewPageState(); } class _PageViewPageState extends State<PageViewPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("title")), body: PageView( scrollDirection: Axis.vertical, //配置滑动的方位 onPageChanged: (index) { print(index); }, children: [ Center( child: Text( "第一屏", style: Theme.of(context).textTheme.labelLarge, ), ), Center( child: Text( "第二屏", style: Theme.of(context).textTheme.labelLarge, ), ), Center( child: Text( "第三屏", style: Theme.of(context).textTheme.labelLarge, ), ), Center( child: Text( "第四屏", style: Theme.of(context).textTheme.labelLarge, ), ), ]), ); } }
7.2 PageView.builder组件
import 'package:flutter/material.dart'; class PageViewBuilderPage extends StatefulWidget { const PageViewBuilderPage({super.key}); @override State<PageViewBuilderPage> createState() => _PageViewBuilderPageState(); } class _PageViewBuilderPageState extends State<PageViewBuilderPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("pageViewbuilder"), ), body: PageView.builder( itemCount: 5, //循环的次数 itemBuilder: (context, index) { return Center( child: Text( "第${index + 1}屏", style: Theme.of(context).textTheme.labelLarge, ), ); })); } }
7.3 轮播组件swiper的封装
import 'package:flutter/material.dart'; import '../../widget/swiper.dart'; class PageViewSwiperPage extends StatefulWidget { const PageViewSwiperPage({super.key}); @override State<PageViewSwiperPage> createState() => _PageViewSwiperPageState(); } class _PageViewSwiperPageState extends State<PageViewSwiperPage> { List<String> list = []; @override void initState() { // TODO: implement initState super.initState(); list = const [ "https://img1.baidu.com/it/u=413643897,2296924942&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500", "https://img1.baidu.com/it/u=1919509102,1927615551&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500", "https://img0.baidu.com/it/u=3007048469,3759326707&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500" ]; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("pageViewSwiper"), ), body: Swiper(list: list)); } }
import 'dart:async'; import 'package:flutter/material.dart'; // import '../widget/image.dart'; class Swiper extends StatefulWidget { final double width; final double height; final List<String> list; const Swiper( {super.key, this.height = 200, this.width = double.infinity, required this.list}); @override State<Swiper> createState() => _SwiperState(); } class _SwiperState extends State<Swiper> { int _currentIndex = 0; List<Widget> pagelist = []; late PageController _pageController; late Timer timer; @override void initState() { // TODO: implement initState super.initState(); for (var i = 0; i < widget.list.length; i++) { pagelist.add(ImagePage( width: widget.width, height: widget.height, src: widget.list[i])); } _pageController = PageController(initialPage: 0); //定时器实现自动轮播 timer = Timer.periodic(Duration(seconds: 3), (t) { _pageController.animateToPage( (_currentIndex + 1) % pagelist.length, //下一个页面 duration: const Duration(microseconds: 200), curve: Curves.linear); }); } @override void dispose() { //页面销毁时清除定时器 // TODO: implement dispose super.dispose(); timer.cancel(); //清除定时器 _pageController.dispose(); } @override Widget build(BuildContext context) { return Stack( children: [ SizedBox( height: 200, child: PageView.builder( controller: _pageController, //控制页面 onPageChanged: (index) { setState(() { _currentIndex = index % pagelist.length; }); }, itemCount: 1000, itemBuilder: (context, index) { return pagelist[index % pagelist.length]; //实现循环轮播的效果 })), Positioned( right: 0, left: 0, bottom: 2, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (index) { return Container( height: 10, width: 10, margin: EdgeInsets.all(5), decoration: BoxDecoration( color: _currentIndex == index ? Colors.blue : Colors.grey, borderRadius: BorderRadius.circular(5)), ); }).toList(), )) ], ); } } class ImagePage extends StatelessWidget { final double height; final double width; final String src; const ImagePage( {super.key, this.width = double.infinity, this.height = 200, required this.src}); @override Widget build(BuildContext context) { return Container( width: width, height: height, child: Image.network( src, fit: BoxFit.cover, ), ); } }
8.flutter中key以及通过全局key获取子widget实例
8.1 flutter中key的作用
import 'package:flutter/material.dart'; //flutter中key是不能重复使用的,作为唯一标识,组件更新时其状态的保存主要是通过判断组件的类型 //或者key是否一致,如果类型不同时,类型已经足够区分不同组件,此时没必要使用key,但存在多个同意 //组件就需要key来判定,组件不同但是全局key一样也可保留组件的状态 class KeyPage extends StatefulWidget { const KeyPage({super.key}); @override State<KeyPage> createState() => _KeyPageState(); } //1.全局keyGlobalKey //2.常用局部key有ValueKey、UniqueKey class _KeyPageState extends State<KeyPage> { GlobalKey _globalKey1 = GlobalKey(); //定义全局key List<Widget> list = []; @override void initState() { // TODO: implement initState super.initState(); list = [ const Box( key: ValueKey("1"), //指定key color: Colors.red, ), Box( key: UniqueKey(), //生成唯一值 color: Colors.yellow, ), Box( key: _globalKey1, color: Colors.blue, ), ]; } @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { list.shuffle(); //对数据元素进行重新排序 }); }, child: const Icon(Icons.refresh), ), appBar: AppBar( title: Text("flutter"), ), body: Center( child: Column(mainAxisAlignment: MainAxisAlignment.center, children: list), ), ); } } class Box extends StatefulWidget { final Color color; const Box({super.key, required this.color}); @override State<Box> createState() => _BoxState(); } //定义盒子组件 class _BoxState extends State<Box> { late int _count = 0; @override Widget build(BuildContext context) { return Container( height: 100, width: 100, child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(widget.color)), onPressed: () { setState(() { _count++; }); }, child: Text("$_count")), ); } }
8.2 flutter 通过全局key获取子widget的属性和方法
import 'package:flutter/material.dart'; class Key2Page extends StatefulWidget { const Key2Page({super.key}); @override State<Key2Page> createState() => _KeyPageState(); } class _KeyPageState extends State<Key2Page> { GlobalKey _globalKey1 = GlobalKey(); //定义全局key @override @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { // 1.通过全局key获取 currentState子组件属性 var boxState = _globalKey1.currentState as _BoxState; setState(() { boxState._count++; }); //调用currentState子组件的方法 boxState.run(); //2.获取子widget var boxWidget = _globalKey1.currentWidget as Box; //3.获取子组件渲染属性 var renderBox = _globalKey1.currentContext!.findRenderObject() as RenderBox; print(renderBox.size); }, child: const Icon(Icons.add), ), appBar: AppBar( title: Text("flutter"), ), body: Center( child: Box(key: _globalKey1, color: Colors.blue), ), ); } } //子widget class Box extends StatefulWidget { final Color color; const Box({super.key, required this.color}); @override State<Box> createState() => _BoxState(); } //定义盒子组件 class _BoxState extends State<Box> { late int _count = 0; void run() { print("我是子组件的方法"); } @override Widget build(BuildContext context) { return Container( height: 100, width: 100, child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(widget.color)), onPressed: () { setState(() { _count++; }); }, child: Text("$_count")), ); } }
9.动态列表
import 'dart:async'; import 'package:flutter/material.dart'; class AnimateListPage extends StatefulWidget { const AnimateListPage({super.key}); @override State<AnimateListPage> createState() => _AnimateListPageState(); } class _AnimateListPageState extends State<AnimateListPage> { final _globalKey = GlobalKey<AnimatedListState>(); //加上泛型AnimatedListState List<String> list = ["第一条", "第二条"]; bool flag = true; Widget _BuildItem(index) { return ListTile( title: Text(list[index]), trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () { _delete(index); }, ), ); } //删除 _delete(index) { if (flag) { flag = false; _globalKey.currentState?.removeItem(index, (context, animation) { var removeItem = _BuildItem(index); //获取执行动画的元素 list.removeAt(index); //数组中删除数据 return FadeTransition( opacity: animation, child: removeItem, ); }); //解决快速删除时的bug Timer.periodic(Duration(milliseconds: 500), (timer) { flag = true; timer.cancel(); }); } } @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { // setState(() { // //使用setState给AnimatedList数据页面不更新 // list.add("新增的数据"); // }); //要通过insertItem来添加数据 list.add("新增的数据"); _globalKey.currentState?.insertItem(list.length - 1); }, child: Icon(Icons.add), ), appBar: AppBar( title: Text("动态列表页面"), ), body: AnimatedList( key: _globalKey, initialItemCount: list.length, itemBuilder: (context, index, Animation) { //Animation动态的时间0-1,执行动画的元素child return FadeTransition(opacity: Animation, child: _BuildItem(index)); }), ); } }
10.getx
10.1 getx的介绍
通俗的讲: 当我们想在多个页面(组件/Widget)之间共享状态(数据),或者一个页面(组件/Widget)中的多个子组件之间共享状态(数据),这个时候我们就可以用Flutter中的状态管理来管理统一的状态(数据),实现不同组件之间的传值和数据共享。现在Flutter的状态管理方案很多,redux、bloc、state、provider、Getx。provider是官方提供的状态管理解决方案,主要功能就是状态管理。Getx是第三方的状态管理插件,不仅具有状态管理的功能,还具有路由管理、主题管理、国际化多语言管理、Obx局部更新、网络请求、数据验证等功能,相比其他状态管理插件Getx 简单、功能强大并且高性能。
官网:https://pub.dev/packages/get
中文文档:https://github.com/jonataslaw/getx/blob/master/README.zh-cn.md
10.2 安装使用
dependencies: get: ^4.6.5
10.3 getx中的dialog以及主题切换
import 'package:flutter/material.dart'; import 'package:get/get.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { //使用GetMaterialApp return GetMaterialApp( debugShowCheckedModeBanner: false, //去掉debug title: "getx app", theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("getx"), ), body: Center( child: Column(children: [ ElevatedButton( onPressed: () { //getx默认弹框 Get.defaultDialog( title: "提示信息", middleText: "你确定要删除么", confirm: ElevatedButton( onPressed: () { print("确认"); Get.back(); //关闭弹框 }, child: const Text("确认")), cancel: ElevatedButton(onPressed: () {}, child: Text("取消"))); }, child: const Text("getx defaultDialog")), ElevatedButton( onPressed: () { //getx默认弹框 Get.snackbar("提示", "你还没有登录", snackPosition: SnackPosition.TOP); //修改位置 }, child: const Text("getx saackbar")), ElevatedButton( onPressed: () { //getx默认弹框 Get.bottomSheet(Container( height: 200, child: Column(children: [ ListTile( onTap: () { //切换主题 Get.changeTheme(ThemeData.light()); Get.back(); }, leading: const Icon( Icons.wb_sunny_outlined, ), title: const Text( "白天模式", style: TextStyle(color: Colors.blue), ), ), ListTile( onTap: () { Get.changeTheme(ThemeData.dark()); Get.back(); }, leading: Icon(Icons.wb_sunny), title: const Text("夜晚模式", style: TextStyle(color: Colors.yellow)), ), ]), )); //修改位置 }, child: const Text("getx bottomSheet")), ]), ), ); } }
10.4 getx中的基础路由
import 'package:flutter/material.dart'; import 'package:get/get.dart'; //getx基础路由 void main() { runApp(GetMaterialApp( home: Home(), )); } class Home extends StatelessWidget { const Home({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("getx router"), ), body: Column(children: [ ElevatedButton( onPressed: () { //1.基础路由跳转,可以定义跳转动画 Get.to(Other(), transition: Transition.fadeIn, duration: Duration(milliseconds: 2000), arguments: {"name": "张三", "age": 18}); //传参 //2.跳转后不能回退 // Get.off(Other()); //3.跳转关闭之前所有路由 // Get.offAll(Other()); }, child: Text("路由跳转")) ]), ); } } class Other extends StatelessWidget { const Other({super.key}); @override Widget build(BuildContext context) { //获取路由传过来的参数 final res = Get.arguments; return Scaffold( appBar: AppBar(title: Text("other页面")), body: Center( child: Text("other页面" + '--' + res["name"]), ), ); } }
10.5 getx中的命名路由
import 'package:flutter/material.dart'; import 'package:flutter02/pages/user/login.dart'; import 'package:flutter02/routers/route.dart'; import 'package:get/get.dart'; //getx命名路由 void main() { runApp(GetMaterialApp( initialRoute: "/login", //初始化路由 defaultTransition: Transition.zoom, //全局设置动画
//配置路由
getPages: [ GetPage(name: "/", page: () => Home()), GetPage(name: "/other", page: () => Other()), GetPage(name: "/login", page: () => Login()) ], //路由拦截 routingCallback: (routing) => {print(routing?.current)}, )); } class Home extends StatelessWidget { const Home({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("getx router"), ), body: Column(children: [ ElevatedButton( onPressed: () { //1.命名路由跳转, Get.toNamed("/other", arguments: {"name": "张三", "age": 18}); //传参 //2.跳转后不能回退 // Get.offNamed("/other", arguments: {"name": "张三", "age": 18}); //3.跳转关闭之前所有路由 // Get.offAllNamed("/other", arguments: {"name": "张三", "age": 18}); }, child: Text("路由跳转")) ]), ); } } //其他页面 class Other extends StatelessWidget { const Other({super.key}); @override Widget build(BuildContext context) { //获取路由传过来的参数 final res = Get.arguments; return Scaffold( appBar: AppBar(title: Text("other页面")), body: Center( child: Text("other页面" + '--' + res["name"]), ), ); } } //登录页面 class Login extends StatelessWidget { const Login({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("login"), ), body: Center( child: ElevatedButton( onPressed: () { Get.offNamed("/"); }, child: Text("跳转home"), )), ); } }
10.6 getx状态管理
import 'package:flutter/material.dart'; import 'package:get/get.dart'; void main() { runApp(const GetMaterialApp( home: Home(), )); } class Home extends StatelessWidget { const Home({super.key}); @override Widget build(BuildContext context) { //使用控制器根据依赖注入 final controller = Get.put(Controller()); //实例化类时转换为响应式变量 final user = User1(name: "Camila", age: 18).obs; var num = 0; // final user = User(); return Scaffold( appBar: AppBar( title: Text("state"), ), body: Center( child: Column(children: [ //使用Obx包裹数据变为响应式数据 Obx(() => Text('count1--' + '${controller.count1.value}')), GetX<Controller>( //需要加上value获取值 builder: (controller) { print("count 1 rebuild"); return Text('count1--' + '${controller.count1.value}'); }, ), GetX<Controller>( builder: (controller) { print("count 2 rebuild"); return Text('count2--' + '${controller.count2.value}'); }, ), GetX<Controller>( builder: (controller) { print("count 3 rebuild"); return Text('sum--' + '${controller.sum}'); }, ), ElevatedButton( onPressed: () { //只会局部更新 controller.count1.value++; }, child: Text("改变count1")), Obx(() => Text("age is ${user.value.age}")), ElevatedButton( onPressed: () { //只会局部更新 user.update((user) { // 这个参数是你要更新的类本身。 user?.name = 'Jonny'; user?.age = 20; }); }, child: Text("改变User1")), //数据不需要加value获取值 Obx(() => Text("list is ${controller.list}")), ElevatedButton( onPressed: () { num++; controller.list.add(num); }, child: Text("改变list")), ]), )); } } //创建控制器 class Controller extends GetxController { //定义响应式变量 final count1 = 1.obs; final count2 = 2.obs; int get sum => count1.value + count2.value; final list = [].obs; //初始化方法 @override void onInit() { // TODO: implement onInit super.onInit(); list.add(1); ///每次`count1`变化时调用。 ever(count1, (_) => print("$_ has been changed")); ///只有在变量$_第一次被改变时才会被调用。 once(count1, (_) => print("$_ was changed once")); ///防DDos - 每当用户停止输入1秒时调用,例如。 debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1)); ///忽略1秒内的所有变化。节流 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); } } //类中定义响应式变量 class User { final name = "tom".obs; final age = 18.obs; } //也可先定义实例化时转换为obs class User1 { User1({required String name, int? age}); var name = "tom"; var age = 18; }
标签:const,Text,基础,dart,context,child,import,flutter From: https://www.cnblogs.com/chenxian123m/p/fliutter_02.html