Youtube视频地址:
https://www.youtube.com/watch?v=OO_-MbnXQzY&t=437s
dart在线工具:
https://dartpad.dev/
Flutter是widget的嵌套
MaterialApp是应用的起点
import'package:flutter/material.dart';void main() { runApp(MaterialApp( home:Material( child: Text('Hello world'), ), ));}
StatelessWidget内返回的必须是Widget
必须用StatelessWidget才能reload(热更新)
Column 部件用children, children是个list,因为有多个
mainAxisAlignment改变Column的沿主轴的分布方式
child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('hello, welcome back!'), Text('Login to continue'), Text('new text'), ], )
Scaffold部件可以新增更多的属性,方便排版布局;
用Scaffold 替代Material时,需要将child改为body
TextField是全屏的宽度,所以会影响到组件的布局
// hintText是提示词,类似web里的placeholderTextField( decoration: InputDecoration(hintText: 'username'), )
按钮:
//字体按钮TextButton(onPressed: () { print('clicked'); }, child: Text('Forget Password?')),//主按钮ElevatedButton(onPressed: () { print('Login is clicked'); }, child: Text('Log in')),
添加图片,在根目录下新建assets/images目录,并需要在pubspec.yaml中加入该图片文件夹的路径:
flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: assets: - assets/images/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg
可以直接新增一个文件将原UI代码拆开放在一个新的class(继承自StatelessWidget),在原文件中可直接引用该类
修改Widget样式的时候,可用Wrap将Widget作为child包裹在里面
Google fonts:
https://fonts.google.com/
在assets目录下新建fonts目录,并需要在pubspec.yaml中加入字体目录,修改对应的字重及对应weight数值
flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: assets: - assets/images/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg fonts: - family: Urbanist fonts: - asset: assets/fonts/Urbanist-Light.ttf weight: 300 - asset: assets/fonts/Urbanist-Regular.ttf - asset: assets/fonts/Urbanist-Medium.ttf weight: 500 - asset: assets/fonts/Urbanist-SemiBold.ttf weight: 600 - asset: assets/fonts/Urbanist-Bold.ttf weight: 700 - asset: assets/fonts/Urbanist-ExtraBold.ttf weight: 800 - asset: assets/fonts/Urbanist-Black.ttf weight: 900
App Figma地址:
https://www.figma.com/file/ldUCcQApMTiTzs2jzAx7Iw/Flutter-course?type=design&node-id=0-1&mode=design&t=8JNDMsrUCxrRgQO8-0
lib文件夹下创建styles文件夹,创建app_colors.dart,加入颜色
import 'package:flutter/material.dart'; class AppColors{ static const primary = Color(0xfffbd512); static const font = Color(0xffD8D8D8); static const font2 = Color(0xff373737); static const disableFont = Color(0xffa7a7a7); static const disableButton = Color(0xff303030); static const background = Color(0xff1A2947); static const black = Color(0xff000000); static const white = Color(0xffffffff); }
在main.dart > MaterialApp中加入theme可修改主题(全局样式)
import 'package:first1/login_page.dart'; import 'package:first1/styles/app_colors.dart'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( fontFamily: 'Urbanist', scaffoldBackgroundColor: AppColors.background, ), home: LoginPage(), ); } }
Spacer(),可以根据屏幕尺寸自动加一些空间,而SizedBox()是固定的尺寸,需要根据UI灵活调整用哪个Widget
渲染溢出:
A RenderFlex overflowed by xxx pixels on the bottom.
SingleChildScrollView与Spacer()冲突,可以在Widget之间再加个SizedBox给出明确的高度或使用height: MediaQuery.of(context).size.height查询设备高度
width: double.infinity可以填满宽度或高度
方法一:MaterialPageRoute:
ElevatedButton( onPressed: () { Navigator.of(context).push(MaterialPageRoute( builder: (context) { return HomePage(); } ) ); } child: Text('Log in') ),
方法二:在MaterialApp中建立routes,并在点击时调用routes name
class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( fontFamily: 'Urbanist', scaffoldBackgroundColor: AppColors.background, ), initialRoute: '/', routes: { '/': (context) => LoginPage(), '/home': (context) => HomePage(), }, ); } }
ElevatedButton( onPressed: () { Navigator.of(context).pushNamed('/home'); }, child: Text('Log in') ),
如果不希望返回,如登录页到首页,则用pushReplacementNamed('/home')替代pushNamed('/home')
绘制列表时,用ListView()替代Column(),性能会更好
使用setState改变状态
import 'package:flutter/material.dart'; class TestPage extends StatefulWidget { const TestPage({super.key}); @override State<TestPage> createState() => _TestPageState(); } class _TestPageState extends State<TestPage> { int count = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Text( 'This is a counter: $count', style: TextStyle( fontSize: 30, color: Colors.white, ), ), ), floatingActionButton: FloatingActionButton( onPressed: () { setState(() { count++; }); }, child: Icon(Icons.add), ), ); } }
https://pub.dev/
使用flutter_svg第三方库
下面的记录不完整
下方导航栏问题:
type:
BottomNavigationBarType.shifting,
PreferredSizeWidget
implements ?
PopupMenuButton
ClipRRect
Expanded()等分,类似css的dsiplay:flex
contentPadding: EdgeInsets.zero,清除默认Padding
copyWith继承样式并修改属性
ColorFilter
extendBody: true, 显示组件遮挡(多余)的部分
fultter_map
https://docs.fleaflet.dev/
视频中的openstreet连不上
用的ArcGIS,下面这个
https://server.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}.png
知乎:
https://zhuanlan.zhihu.com/p/641436984
GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, // crossAxisSpacing: 2.0, // mainAxisSpacing: 4.0, childAspectRatio: 0.75, mainAxisExtent: 260), itemCount: 9, // 假设有20张图片 itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: Container( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ ClipRRect( clipBehavior: Clip.antiAlias, child: Image.network( 'https://shorturl.at/csQTX', width: double.infinity, fit: BoxFit.cover, )), // 替换为你的图片部件 SizedBox(height: 8.0), Text( 'Doutei Yuusha no...', style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold), ), Text( 'Author', style: TextStyle(fontSize: 14.0, color: Colors.grey), ), SizedBox(height: 8.0), ], ), ), ); }, )
DefaultTabController( length: 3, // 标签的数量 child: Scaffold( appBar: AppBar( title: Text('Bookshelf'), bottom: TabBar( tabs: [ Tab(text: 'Tab 1'), Tab(text: 'Tab 2'), Tab(text: 'Tab 3'), ], ), ), body: TabBarView( children: [ TabContent('Tab 1 Content'), TabContent('Tab 2 Content'), TabContent('Tab 3 Content'), ], ), ), )
https://blog.csdn.net/qq_39081974/article/details/100201821
Text( 'Sample Text', softWrap:true, textAlign:TextAlign.left, overflow:TextOverflow.ellipsis, maxLines:3, style:Textstyle( fontSize:14, ),),
https://blog.csdn.net/ww897532167/article/details/111933624
https://juejin.cn/post/7031196891358429220
WidgetsFlutterBinding 将是 Widget 架构和 Flutter Engine 连接的核心桥梁,也是整个 Flutter 应用层的核心。通过 ensureInitialized() 方法我们可以得到一个全局单例 WidgetsFlutterBinding。
有时候我们会在发现有的app 在在运行应用程序之前先与 Flutter Engine 进行通信,所以要先将
WidgetsFlutterBinding.ensureInitialized()提前