最全10天学会flutter DAY7 flutter 玩转基础Widget,2024年最新2024Android面试总结

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

@override

void didChangeDependencies() {

super.didChangeDependencies();

debugPrint(“child didChangeDependencies…”);

}

///父widget状态改变的时候会调用该方法,比如父节点调用了setState

@override

void didUpdateWidget(Child oldWidget) {

super.didUpdateWidget(oldWidget);

debugPrint(“child didUpdateWidget…”);

}

///当State对象从树中被移除时,会调用此回调

@override

void deactivate() {

super.deactivate();

debugPrint(‘child deactivate…’);

}

///当State对象从树中被永久移除时调用;通常在此回调中释放资源

@override

void dispose() {

super.dispose();

debugPrint(‘child dispose…’);

}

}

执行的输出结果显示为:

  • 运行到显示

I/flutter (22218): parent initState…

I/flutter (22218): parent didChangeDependencies…

I/flutter (22218): parent build…

I/flutter (22218): child initState…

I/flutter (22218): child didChangeDependencies…

I/flutter (22218): child build…

  • 点击按钮会移除Child

I/flutter (22218): parent build…

I/flutter (22218): child deactivate…

I/flutter (22218): child dispose…

  • 将MyApp的代码由 child: isShowChild ? Child() : Text("演示移除Child"),改为 child: Child(),点击按钮时

I/flutter (22765): parent build…

I/flutter (22765): child didUpdateWidget…

I/flutter (22765): child build…

从这些实验中能够得出State的生命周期为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rwh5gNCi-1652105029912)(图片/生命周期.png)]

基础widget


文本显示

Text

Text是展示单一格式的文本Widget(Android TextView)。

import ‘package:flutter/material.dart’;

///

/// main方法 调用runApp传递Widget,这个Widget成为widget树的根

void main() => runApp(TextApp());

///

/// 1、单一文本Text

///

//创建一个无状态的Widget

class TextApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

//封装了应用程序实现Material Design所需要的一些widget

return MaterialApp(

title: “Text演示”, //标题,显示在recent时候的标题

//主页面

//Scaffold : Material Design布局结构的基本实现。

home: Scaffold(

//ToolBar/ActionBar

appBar: AppBar(title: Text(“Text”)),

body: Text(“Hello,Flutter”),

),

);

}

}

在使用Text显示文字时候,可能需要对文字设置各种不同的样式,类似Android的 android:textColor/Size

在Flutter中也拥有类似的属性

Widget _TextBody() {

return Text(

“Hello,Flutter”,

style: TextStyle(

//颜色

color: Colors.red,

//字号 默认14

fontSize: 18,

//粗细

fontWeight: FontWeight.w800,

//斜体

fontStyle: FontStyle.italic,

//underline:下划线,overline:上划线,lineThrough:删除线

decoration: TextDecoration.lineThrough,

decorationColor: Colors.black,

//solid:实线,double:双线,dotted:点虚线,dashed:横虚线,wavy:波浪线

decorationStyle: TextDecorationStyle.wavy),

);

}

class TextApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: “Text演示”,

home: Scaffold(

appBar: AppBar(title: Text(“Text”)),

body: _TextBody(),

),

);

}

}

RichText

如果需要显示更为丰富样式的文本(比如一段文本中文字不同颜色),可以使用RichText或者Text.rich

Widget _RichTextBody() {

var textSpan = TextSpan(

text: “Hello”,

style: TextStyle(color: Colors.red),

children: [

TextSpan(text: “Flu”, style: TextStyle(color: Colors.blue)),

TextSpan(text: “uter”, style: TextStyle(color: Colors.yellow)),

],

);

//Text.rich(textSpan);

return RichText(text: textSpan);

}

DefaultTextStyle

​ 在widget树中,文本的样式默认是可以被继承的,因此,如果在widget树的某一个节点处设置一个默认的文本样式,那么该节点的子树中所有文本都会默认使用这个样式。相当于在Android中定义 Theme

Widget _DefaultStyle(){

DefaultTextStyle(

//设置文本默认样式

style: TextStyle(

color:Colors.red,

fontSize: 20.0,

),

textAlign: TextAlign.start,

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

Text(“Hello Flutter!”),

Text(“Hello Flutter!”),

Text(“Hello Flutter!”,

style: TextStyle(

inherit: false, //不继承默认样式

color: Colors.grey

),

),

],

),

);

}

图片显示

“图文”:有文字显示Widget,又怎么少的了图片呢。

FlutterLogo

​ 这个Widget用于显示Flutter的logo…

Widget flutterLogo() {

return FlutterLogo(

//大小

size: 100,

//logo颜色 默认为 Colors.blue

colors: Colors.red,

//markOnly:只显示logo,horizontal:logo右边显示flutter文字,stacked:logo下面显示文字

style: FlutterLogoStyle.stacked,

//logo上文字颜色

textColor: Colors.blue,

);

}

Icon

主要用于显示内置图标的Widget

Widget icon() {

return Icon(

//使用预定义Material icons

// https://docs.flutter.io/flutter/material/Icons-class.html

Icons.add,

size: 100,

color: Colors.red);

}

Image

显示图片的Widget。图片常用的格式主要有bmp,jpg,png,gif,webp等,Android中并不是天生支持gif和webp动图,但是这一特性在flutter中被很好的支持了。

| 方式 | 解释 |

| — | — |

| Image() | 使用ImageProvider提供图片,如下方法本质上也是使用的这个方法 |

| Image.asset | 加载资源图片 |

| Image.file | 加载本地图片文件 |

| Image.network | 加载网络图片 |

| Image.memory | 加载内存图片 |

Iamge.asset

在工程目录下创建目录,如:assets,将图片放入此目录。打开项目根目录:pubspec.yaml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ilqKvFsm-1652105029913)(图片/基础Widget_AssetsImag.png)]

return MaterialApp(

title: “Image演示”,

home: Scaffold(

appBar: AppBar(title: Text(“Image”)),

body: Image.asset(“assets/banner.jpeg”),

),

);

Image.file

在sd卡中放入一张图片。然后利用path_provider库获取sd卡根目录(Dart库版本可以在:https://pub.dartlang.org/packages查询)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NURxRVFK-1652105029914)(图片/基础Widget_FileProvider.png)]

注意权限

class ImageState extends State {

Image image;

@override

void initState() {

super.initState();

getExternalStorageDirectory().then((path) {

setState(() {

image = Image.file(File(“ p a t h . p a t h {path.path} path.path{Platform.pathSeparator}banner.jpeg”));

});

});

}

@override

Widget build(BuildContext context) {

return MaterialApp(

title: “Image演示”,

home: Scaffold(

appBar: AppBar(title: Text(“Image”)),

body: image,

),

);

}

}

Image.network

直接给网络地址即可。

Flutter 1.0,加载https时候经常出现证书错误。必须断开AS打开app

Image.memory

Future<List> _imageByte() async {

String path = (await getExternalStorageDirectory()).path;

return await File(“ p a t h path path{Platform.pathSeparator}banner.jpeg”).readAsBytes();

}

class ImageState extends State {

Image image;

@override

void initState() {

super.initState();

_imageByte().then((bytes) {

setState(() {

image = Image.memory(bytes);

});

});

}

@override

Widget build(BuildContext context) {

return MaterialApp(

title: “Image演示”,

home: Scaffold(

appBar: AppBar(title: Text(“Image”)),

body: image,

),

);

}

}

fit属性相当于android中的scaletype,定义如下:

| fit | 说明 | 效果 |

| — | — | — |

| BoxFit.fill | 填充,忽略原有的宽高比,填满为止 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6mrpsBu-1652105029915)(图片/基础Widget_Image_Fill.png)] |

| BoxFit.contain | 包含,不改变原有比例让容器包含整个图片,容器多余部分填充背景 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBcXaz3K-1652105029916)(图片/基础Widget_Image_Contain.png)] |

| BoxFit.cover | 覆盖,不改变原有比例,让图片充满整个容器,图片多余部分裁剪 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZ0c91K3-1652105029917)(图片/基础Widget_Image_Cover.png)] |

| BoxFit.fitWidth | 横向图片填充 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyoRkEkC-1652105029917)(图片/基础Widget_Image_FitWidth.png)] |

| BoxFit.fitHeight | 纵向图片填充 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RLaJsaOq-1652105029918)(图片/基础Widget_Image_FitHeight.png)] |

| BoxFit.none | 原始大小居中 | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhqvKLzm-1652105029919)(图片/基础Widget_Image_none.png)] |

| BoxFit.scaleDown | 图片大小小于容器事相当于none,图片大小大于容器时缩小图片大小实现contain | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UI08cwJt-1652105029919)(图片/基础Widget_Image_ScaleDown.png)] |

CircleAvatar

主要用来显示用户的头像,任何图片都会被剪切为圆形。

CircleAvatar(

//图片提供者 ImageProvider

backgroundImage: AssetImage(“assets/banner.jpeg”),

//半径,控制大小

radius: 50.0,

);

FadeInImage

当使用默认Image widget显示图片时,您可能会注意到它们在加载完成后会直接显示到屏幕上。这可能会让用户产生视觉突兀。如果最初显示一个占位符,然后在图像加载完显示时淡入,我们可以使用FadeInImage来达到这个目的!

image = FadeInImage.memoryNetwork(

placeholder: kTransparentImage,

image: ‘https://flutter.io/images/homepage/header-illustration.png’,

);

按钮

Material widget库中提供了多种按钮Widget如RaisedButton、FlatButton、OutlineButton等,它们都是直接或间接对RawMaterialButton的包装定制,所以他们大多数属性都和RawMaterialButton一样。所有Material 库中的按钮都有如下相同点:

  1. 按下时都会有“水波动画”。

  2. 有一个onPressed属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

RaisedButton

"漂浮"按钮,它默认带有阴影和灰色背景

RaisedButton(

child: Text(“normal”),

onPressed: () => {},

)

FlatButton

扁平按钮,默认背景透明并不带阴影

FlatButton(

child: Text(“normal”),

onPressed: () => {},

)

OutlineButton

默认有一个边框,不带阴影且背景透明。

OutlineButton(

child: Text(“normal”),

onPressed: () => {},

)

IconButton

可点击的Icon

IconButton(

icon: Icon(Icons.thumb_up),

onPressed: () => {},

)

按钮外观可以通过其属性来定义,不同按钮属性大同小异

const FlatButton({

@required this.onPressed, //按钮点击回调

this.textColor, //按钮文字颜色

this.disabledTextColor, //按钮禁用时的文字颜色

this.color, //按钮背景颜色

this.disabledColor,//按钮禁用时的背景颜色

this.highlightColor, //按钮按下时的背景颜色

this.splashColor, //点击时,水波动画中水波的颜色

this.colorBrightness,//按钮主题,默认是浅色主题

this.padding, //按钮的填充

this.shape, //外形

@required this.child, //按钮的内容

})

FlatButton(

onPressed: () => {},

child: Text(“Raised”),

//蓝色

color: Colors.blue,

//水波

splashColor: Colors.yellow,

//深色主题,这样文字颜色会变成白色

colorBrightness: Brightness.dark,

//圆角按钮

shape: RoundedRectangleBorder(

borderRadius: BorderRadius.circular(50)

),

)

RaisedButton,默认配置有阴影,因此在配置RaisedButton 时,拥有一系列 elevation 属性的配置

const RaisedButton({

this.elevation = 2.0, //正常状态下的阴影

this.highlightElevation = 8.0,//按下时的阴影

this.disabledElevation = 0.0,// 禁用时的阴影

}

输入框

import ‘package:flutter/material.dart’;

void main() => runApp(Demo1());

class Demo1 extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: “Demo1”,

home: Scaffold(

appBar: AppBar(

title: Text(“登录”),

),

//线性布局,垂直方向

body: Column(

children: [

TextField(

//自动获得焦点

autofocus: true,

decoration: InputDecoration(

labelText: “用户名”,

hintText: “用户名或邮箱”,

prefixIcon: Icon(Icons.person)),

),

TextField(

//隐藏正在编辑的文本

obscureText: true,

decoration: InputDecoration(

labelText: “密码”,

hintText: “您的登录密码”,

prefixIcon: Icon(Icons.lock)),

),

],

),

),

);

}

}

这个效果非常的“系统”,我们可能大多数情况下需要将下划线更换为矩形边框,这时候可能就需要组合widget来完成:

//容器 设置一个控件的尺寸、背景、margin

Container(

margin: EdgeInsets.all(32),

child: TextField(

keyboardType: TextInputType.emailAddress,

decoration: InputDecoration(

labelText: “用户名”,

hintText: “用户名或邮箱”,

prefixIcon: Icon(Icons.person),

border: InputBorder.none //隐藏下划线

)),

//装饰

decoration: BoxDecoration(

// 边框浅灰色,宽度1像素

border: Border.all(color: Colors.red[200], width: 1.0),

//圆角

borderRadius: BorderRadius.circular(5.0),

),

)

焦点控制

​ FocusNode: 与Widget绑定,代表了这个Widget的焦点

​ FocusScope: 焦点控制范围

文末

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Icons.person),

border: InputBorder.none //隐藏下划线

)),

//装饰

decoration: BoxDecoration(

// 边框浅灰色,宽度1像素

border: Border.all(color: Colors.red[200], width: 1.0),

//圆角

borderRadius: BorderRadius.circular(5.0),

),

)

焦点控制

​ FocusNode: 与Widget绑定,代表了这个Widget的焦点

​ FocusScope: 焦点控制范围

文末

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

[外链图片转存中…(img-wESSoLea-1715406833117)]

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-tqDAO7eb-1715406833118)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值