前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

Flutter学习(flutter教程)


Youtube视频地址:
https://www.youtube.com/watch?v=OO_-MbnXQzY&t=437s

dart在线工具:
https://dartpad.dev/

Widget

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里的placeholder
TextField( 
		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

Theme

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.

  1. 可以在Widget外包裹一层SingleChildScrollView,这样超出的部分可以滚动
  2. resizeToAvoidBottomInset: false弹出键盘后不改变布局,但会导致在键盘位置的输入框无法显示(尽量不要使用)

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(),性能会更好

StatefulWidget

使用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),  
      ),  
    );  
  }  
}

SVG

https://pub.dev/

使用flutter_svg第三方库

下面的记录不完整

下方导航栏问题:
type: BottomNavigationBarType.shifting,

组件复用

PreferredSizeWidget
implements ?

PopupMenuButton

ClipRRect

Expanded()等分,类似css的dsiplay:flex

contentPadding: EdgeInsets.zero,清除默认Padding

copyWith继承样式并修改属性

ColorFilter

extendBody: true, 显示组件遮挡(多余)的部分

Map

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

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),  
          ],  
        ),  
      ),  
    );  
  },  
)

TabBar

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,
	),
),

Border

https://blog.csdn.net/ww897532167/article/details/111933624

WidgetsFlutterBinding.ensureInitialized()

https://juejin.cn/post/7031196891358429220

WidgetsFlutterBinding 将是 Widget 架构和 Flutter Engine 连接的核心桥梁,也是整个 Flutter 应用层的核心。通过 ensureInitialized() 方法我们可以得到一个全局单例 WidgetsFlutterBinding。


有时候我们会在发现有的app 在在运行应用程序之前先与 Flutter Engine 进行通信,所以要先将WidgetsFlutterBinding.ensureInitialized()提前

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言