面试的要点和技巧,一个Android菜鸟入门Flutter 笔记(一),2024年字节跳动+京东+美团面试总结
9.4 NotificationListener
- NotificationListener是一个Widget,需要将ListView添加到NotificationListener中
class MyListenerApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: NotificationListener(
//添加NotificationListener作为父容器
//注册通知回调
onNotification: (scrollNotification) {
//开始滑动
if (scrollNotification is ScrollStartNotification) {
//scrollNotification.metrics.pixels 滑动的位置
print(‘scroll start ${scrollNotification.metrics.pixels}’);
} else if (scrollNotification is ScrollUpdateNotification) {
//滑动中
print(‘scroll update’);
} else if (scrollNotification is ScrollEndNotification) {
//滑动结束
print(‘scroll end’);
}
return null;
},
child: ListView.builder(
itemCount: 100,
itemExtent: 70,
itemBuilder: (context, index) => ListTile(
title: Text(‘index $index’),
)),
),
),
);
}
}
10.1 Container,Padding,Center
-
Container内部提供了间距,背景样式,圆角边框等基础属性,可以控制子Widget的摆放方式(居中,左,右)
-
Padding 设置间距,将Widget放里面
-
Center 设置居中,将Widget放里面
getContainer() {
return Container(
child: Center(
child: Text(‘Container(容器)在UI框架中是一个很常见的概念,Flutter也不例外。’),
),
//内边距
padding: EdgeInsets.all(18.0),
//外边距
margin: EdgeInsets.all(44.0),
width: 180.0,
height: 240,
//子Widget居中对齐
/* alignment: Alignment.center,*/
//Container样式
decoration: BoxDecoration(
//背景色
color: Colors.red,
//圆角边框
borderRadius: BorderRadius.circular(10.0),
),
);
}
getPadding() {
//只需要设置边距 可以使用Padding
return Padding(
padding: EdgeInsets.all(44.0),
child: Text(‘我是Padding’),
);
}
getCenter() {
//直接居中
return Center(
child: Text(‘center text’),
);
}
10.2 Row,Column,Expanded
-
Row是水平布局
-
Column是垂直布局
-
Expanded表示将剩余的空间,如何分配
-
Row 与 Column 自身的大小由父widget的大小、子widget的大小、以及mainSize设置共同决定(mainAxisSize和crossAxisSize)
-
主轴(纵轴)值为max:主轴(纵轴)大小等于屏幕主轴(纵轴)方向大小或者父widget主轴(纵轴)方向大小
-
主轴(纵轴)值为min: 所有子widget组合在一起的主轴(纵轴)大小
//Row的用法示范
Row(
children: [
Container(color: Colors.yellow, width: 60, height: 80,),
Container(color: Colors.red, width: 100, height: 180,),
Container(color: Colors.black, width: 60, height: 80,),
Container(color: Colors.green, width: 60, height: 80,),
],
);
//Column的用法示范
Column(
children: [
Container(color: Colors.yellow, width: 60, height: 80,),
Container(color: Colors.red, width: 100, height: 180,),
Container(color: Colors.black, width: 60, height: 80,),
Container(color: Colors.green, width: 60, height: 80,),
],
);
//第一个和最后一个平分
Row(
children: [
Expanded(flex: 1, child: Container(color: Colors.yellow, height: 60)), //设置了flex=1,因此宽度由Expanded来分配
Container(color: Colors.red, width: 100, height: 180,),
Container(color: Colors.black, width: 60, height: 80,),
Expanded(flex: 1, child: Container(color: Colors.green,height: 60),)/设置了flex=1,因此宽度由Expanded来分配
],
);
对齐方式
- 根据主轴与纵轴,设置子Widget在这两个方向上的对齐规则mainAxisAlignment与crossAxisAlignment.比如主轴方向start表示靠左对齐,center表示横向居中对齐,end表示靠右对齐,spaceEvenly表示按固定间距对齐;而纵轴方向start则表示靠上对齐,center表示纵向居中对齐,end表示靠下对齐.
控制大小
- 如果想让容器与子Widget在主轴上完全匹配,需要通过设置Row的mainAxisSize参数为MainAxisSize.min,由所有子Widget来决定主轴方向的容器长度,即主轴方向的长度尽可能小.类似wrap_content.
mainAxisSize: MainAxisSize.min, //让容器宽度与所有子Widget的宽度一致
10.3 Stack,Positioned
-
Stack,类似FrameLayout.
-
Stack提供了层叠布局的容器,而Positioned则提供了设置子Widget位置的能力.
Stack(
children: [
Container(color: Colors.yellow, width: 300, height: 300),//黄色容器
Positioned(
left: 18.0,
top: 18.0,
child: Container(color: Colors.green, width: 50, height: 50),//叠加在黄色容器之上的绿色控件
),
Positioned(
left: 18.0,
top:70.0,
child: Text(“Stack提供了层叠布局的容器”),//叠加在黄色容器之上的文本
)
],
)
- Positioned只能在Stack中使用.
11.1 组合控件
- 将多个控件组合在一起
11.2 自定义控件
-
CustomPaint是用来承接自绘控件的容器,并不负责真正的绘制.
-
画布是canvas,画笔是Paint.
-
画成什么样子由CustomPainter来控制,将CustomPainter设置给容器CustomPaint的painter属性,我们就完成了一个自绘组件的封装
-
Paint,其实和Android中的差不多,可以配置它的各种属性,比如颜色、样式、粗细等;而画布 Canvas,则提供了各种常见的绘制方法,比如画线 drawLine、画矩形 drawRect、画点 DrawPoint、画路径 drawPath、画圆 drawCircle、画圆弧 drawArc 等。
class WheelPainter extends CustomPainter {
Paint getColoredPaint(Color color) {
Paint paint = Paint();
paint.color = color;
return paint;
}
@override
void paint(Canvas canvas, Size size) {
//半径
double wheelSize = min(size.width, size.height) / 2;
//分成6份
double nbElem = 6;
//角度
double radius = (2 * pi) / nbElem;
//包裹饼图的矩形框 center:相对于原点的偏移量
Rect boundingRect = Rect.fromCircle(
center: Offset(wheelSize, wheelSize), radius: wheelSize);
//每次画1/6圆
canvas.drawArc(
boundingRect, 0, radius, true, getColoredPaint(Colors.orange));
canvas.drawArc(
boundingRect, radius, radius, true, getColoredPaint(Colors.green));
canvas.drawArc(
boundingRect, radius * 2, radius, true, getColoredPaint(Colors.red));
canvas.drawArc(
boundingRect, radius * 3, radius, true, getColoredPaint(Colors.blue));
canvas.drawArc(
boundingRect, radius * 4, radius, true, getColoredPaint(Colors.pink));
canvas.drawArc(boundingRect, radius * 5, radius, true,
getColoredPaint(Colors.deepOrange));
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
//判断是否需要重绘,简单做下比较
return oldDelegate != this;
}
}
class Cake extends StatelessWidget {
@override
Widget build(BuildContext context) {
//CustomPaint是用来承载自定义View的容器,需要自定义一个画笔,得继承自CustomPainter
return CustomPaint(
size: Size(200, 200),
painter: WheelPainter(),
);
}
}
-
视觉效果是易变的,我们将这些变化的部分抽离出来,把提供不同视觉效果的资源和配置按照主题进行归类,整合到一个统一的中间层去管理,这样我们就能实现主题的管理和切换.
-
Flutter中由ThemeData来统一管理主题的配置信息
-
ThemeData中涵盖了Material Design规范的可自定义部分样式,比如应用明暗模式 brightness、应用主色调 primaryColor、应用次级色调 accentColor、文本字体 fontFamily、输入框光标颜色 cursorColor 等。
-
全局统一的视觉风格:
MaterialApp(
title: ‘Flutter Demo’,//标题
theme: ThemeData(//设置主题
brightness: Brightness.dark,//设置明暗模式为暗色
accentColor: Colors.black,//(按钮)Widget前景色为黑色
primaryColor: Colors.cyan,//主色调为青色
iconTheme:IconThemeData(color: Colors.yellow),//设置icon主题色为黄色
textTheme: TextTheme(body1: TextStyle(color: Colors.red))//设置文本颜色为红色
),
home: MyHomePage(title: ‘Flutter Demo Home Page’),
);
-
局部主题: 需要使用Theme来对App的主题进行局部覆盖,Theme是一个单子Widget容器,将控件放里面就可以控制主题了.
-
局部新建主题: 如果不想继承任何App全局的颜色或字体样式,可以直接新建一个ThemeData实例,依次设置对应的样式.
// 新建主题
Theme(
data: ThemeData(iconTheme: IconThemeData(color: Colors.red)),
child: Icon(Icons.favorite)
);
- 继承主题: 如果不想在局部重写所有的样式,则可以继承App的主题,使用copyWith方法,只更新部分样式
// 继承主题
Theme(
data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Colors.green)),
child: Icon(Icons.feedback)
);
- 主题另一个用途是样式复用.
Container(
color: Theme.of(context).primaryColor,//容器背景色复用应用主题色
child: Text(
‘Text with a background color’,
style: Theme.of(context).textTheme.title,//Text组件文本样式复用应用文本样式
));
- 可以把资源放任意目录,只需要使用根目录下的pubspec.yaml文件,对这些资源的所在位置进行显示声明就行.
13.1 图片
flutter:
assets:
-
assets/background.jpg #挨个指定资源路径
-
assets/loading.gif #挨个指定资源路径
-
assets/result.json #挨个指定资源路径
-
assets/icons/ #子目录批量指定
-
assets/ #根目录也是可以批量指定的
-
Flutter遵循了基于像素密度的管理方式,如1.0x,2.0x,3.0x.Flutter会根据当前设备分辨率加载最接近设备像素比例的图片资源
-
想让Flutter适配不同的分辨率,只需要将其他分辨率的图片放到对应的分辨率子目录中.
目录如下
assets
├── background.jpg //1.0x图
├── 2.0x
│ └── background.jpg //2.0x图
└── 3.0x
在pubspec.yaml文件声明:
flutter:
assets:
- assets/background.jpg #1.0x图资源
13.2 字体
fonts:
- family: RobotoCondensed #字体名字
fonts:
-
asset: assets/fonts/RobotoCondensed-Regular.ttf #普通字体
-
asset: assets/fonts/RobotoCondensed-Italic.ttf
style: italic #斜体
- asset: assets/fonts/RobotoCondensed-Bold.ttf
weight: 700 #粗体
13.3 三方库 三方组件库
-
Dart提供包管理工具: Pub,管理代码和资源
-
对于包,通常是指定版本区间,而很少直接指定特定版本.
-
多人协作时,建议将Dart和Flutter的SDK环境写死,统一团队的开发环境.避免因为跨SDK版本出现的API差异而导致工程问题.
dependencies:
//1. #路径依赖
package1:
path: …/package1/
//2. github
date_format:
git:
url: https://github.com/xxx/package2.git #git依赖
//3. pub上面的
date_format: 1.0.6
- 底层原始指针事件: 用户的触摸数据,如手指接触屏幕 PointerDownEvent、手指在屏幕上移动 PointerMoveEvent、手指抬起 PointerUpEvent,以及触摸取消 PointerCancelEvent.
Listener(
child: Container(
color: Colors.red,//背景色红色
width: 300,
height: 300,
),
onPointerDown: (event) => print(“down $event”),//手势按下回调
onPointerMove: (event) => print(“move $event”),//手势移动回调
onPointerUp: (event) => print(“up $event”),//手势抬起回调
);
-
冒泡分发机制: 将触摸事件交给最内层的组件去响应,事件会从这个最内层的组件开始,沿着组件树向根节点向上冒泡分发.
-
封装了底层指针事件手势语义的Gesture,平常一般使用GestureDetector.如点击 onTap、双击 onDoubleTap、长按 onLongPress、拖拽 onPanUpdate、缩放 onScaleUpdate 等。
//红色container坐标
double _top = 0.0;
double _left = 0.0;
Stack(//使用Stack组件去叠加视图,便于直接控制视图坐标
children: [
Positioned(
top: _top,
left: _left,
child: GestureDetector(//手势识别
child: Container(color: Colors.red,width: 50,height: 50),//红色子视图
onTap: ()=>print(“Tap”),//点击回调
onDoubleTap: ()=>print(“Double Tap”),//双击回调
onLongPress: ()=>print(“Long Press”),//长按回调
onPanUpdate: (e) {//拖动回调
setState(() {
//更新位置
_left += e.delta.dx;
_top += e.delta.dy;
});
},
),
)
],
);
-
事件处理机制: Flutter会使用手势竞技场来进行各个手势的PK,以保证最后只有一个手势能够响应用户行为.
-
手势冲突只是手势的语义化识别过程,对于底层指针事件是不会冲突的.
-
父子都有点击事件的情况 因为子视图在父视图的上面,所以如果点击区域在子视图区域,子视图响应事件.
视图层级比较深的UI样式,直接通过属性传值会导致很多中间层增加冗余属性.
- 代码太多,见demo https://github.com/xfhy/FlutterBasic/tree/master/lib/data
15.1 InheritedWidget
- 共享父Widget的属性
15.2 Notification
- 从下往上的数据传递,在父Widget中监听来自子Widget的事件
15.3 EventBus
-
EventBus 不依赖Widget树 这是事件总线,666
-
遵循发布订阅 模式
15.4 对比
| 方式 | 数据流动方式 | 使用场景 |
| — | — | — |
| 属性传值 | 父到子 | 简单数据传递 |
| InheritedWidget | 父到子 | 跨层数据传递 |
| Notification | 子到父 | 状态通知 |
| EventBus | 发布订阅 | 消息批量同步 |
-
Route是页面的抽象,主要负责创建对应的界面,接收参数,响应Navigator打开和关闭
-
Navigator则会维护一个路由栈管理Route,Route打开即入栈,Route关闭即出栈.
-
基本路由: 创建一个MaterialPageRoute实例,调用Navigator.push方法将新页面压到堆栈的顶部
class FirstScreen extends StatelessWidget {
@override
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。







既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)

资源分享



网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2020年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-QHjkUM6N-1712569520057)]
资源分享
[外链图片转存中…(img-VBtPWFWM-1712569520057)]
[外链图片转存中…(img-wTtsQkaV-1712569520058)]
[外链图片转存中…(img-wMoMf2WR-1712569520058)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2020年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
更多推荐



所有评论(0)