1.图片自适应
2.自适应标签
3.上拉刷新和下拉加载
4.底部的点赞按钮可以去掉或者自己修改样式,我这里使用的like_button库
注:本文使用的库:为啥这么多呢,因为我把图片缓存这样东西都加上了,单纯的瀑布流就用waterfall_flow
waterfall_flow: ^3.0.1
extended_image: any
extended_sliver: any
ff_annotation_route_library: any
http_client_helper: any
intl: any
like_button: any
loading_more_list: any
pull_to_refresh_notification: any
url_launcher: any
1.图片自适应:
Widget image = Stack(
children: [
ExtendedImage.network(
item.imageUrl,
shape: BoxShape.rectangle,
//clearMemoryCacheWhenDispose: true,
border: Border.all(color: Colors.grey.withOpacity(0.4), width: 1.0),
borderRadius: const BorderRadius.all(
Radius.circular(10.0),
),
loadStateChanged: (ExtendedImageState value) {
if (value.extendedImageLoadState == LoadState.loading) {
Widget loadingWidget = Container(
alignment: Alignment.center,
color: Colors.grey.withOpacity(0.8),
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor:
AlwaysStoppedAnimation(Theme.of©.primaryColor),
),
);
if (!konwSized) {
//todo: not work in web
loadingWidget = AspectRatio(
aspectRatio: 1.0,
child: loadingWidget,
);
}
return loadingWidget;
} else if (value.extendedImageLoadState == LoadState.completed) {
item.imageRawSize = Size(
value.extendedImageInfo.image.width.toDouble(),
value.extendedImageInfo.image.height.toDouble());
}
return null;
},
),
Positioned(
top: 5.0,
right: 5.0,
child: Container(
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.6),
border: Border.all(color: Colors.grey.withOpacity(0.4), width: 1.0),
borderRadius: const BorderRadius.all(
Radius.circular(5.0),
),
),
child: Text(
‘${index + 1}’,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: fontSize, color: Colors.white),
),
),
)
],
);
if (konwSized) {
image = AspectRatio(
aspectRatio: item.imageSize.width / item.imageSize.height,
child: image,
);
} else if (item.imageRawSize != null) {
image = AspectRatio(
aspectRatio: item.imageRawSize.width / item.imageRawSize.height,
child: image,
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
image,
const SizedBox(
height: 5.0,
),
buildTagsWidget(item),
const SizedBox(
height: 5.0,
),
buildBottomWidget(item),
],
);
}
2.自适应标签:
Widget buildTagsWidget(
TuChongItem item, {
int maxNum = 6,
}) {
const double fontSize = 12.0;
return Wrap(
runSpacing: 5.0,
spacing: 5.0,
children: item.tags.take(maxNum).map((String tag) {
final Color color = item.tagColors[item.tags.indexOf(tag)];
return Container(
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
color: color,
border: Border.all(color: Colors.grey.withOpacity(0.4), width: 1.0),
borderRadius: const BorderRadius.all(
Radius.circular(5.0),
),
),
child: Text(
tag,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: fontSize,
color: color.computeLuminance() < 0.5
-
? Colors.white
- Colors.black),
),
);
}).toList());
}
3.上拉刷新和下拉加载
class PullToRefreshHeader extends StatelessWidget {
const PullToRefreshHeader(this.info, this.lastRefreshTime, {this.color});
final PullToRefreshScrollNotificationInfo info;
final DateTime lastRefreshTime;
final Color color;
@override
Widget build(BuildContext context) {
if (info == null) {
return Container();
}
String text = ‘’;
if (info.mode == RefreshIndicatorMode.armed) {
text = ‘Release to refresh’;
} else if (info.mode == RefreshIndicatorMode.refresh ||
info.mode == RefreshIndicatorMode.snap) {
text = ‘Loading…’;
} else if (info.mode == RefreshIndicatorMode.done) {
text = ‘Refresh completed.’;
} else if (info.mode == RefreshIndicatorMode.drag) {
text = ‘Pull to refresh’;
} else if (info.mode == RefreshIndicatorMode.canceled) {
text = ‘Cancel refresh’;
}
final TextStyle ts = const TextStyle(
color: Colors.grey,
).copyWith(fontSize: 13);
final double dragOffset = info?.dragOffset ?? 0.0;
final DateTime time = lastRefreshTime ?? DateTime.now();
final double top = -hideHeight + dragOffset;
return Container(
height: dragOffset,
color: color ?? Colors.transparent,
//padding: EdgeInsets.only(top: dragOffset / 3),
//padding: EdgeInsets.only(bottom: 5.0),
child: Stack(
children: [
Positioned(
left: 0.0,
right: 0.0,
top: top,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
alignment: Alignment.centerRight,
child: RefreshImage(top),
margin: const EdgeInsets.only(right: 12.0),
),
),
Column(
children: [
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://img-blog.csdnimg.cn/img_convert/66bdbe3bb542a9ddd89de0d3d228d81a.jpeg)
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
的学习,对自己的提升是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
[外链图片转存中…(img-dHg589jI-1712272082495)]
在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。
[外链图片转存中…(img-1tScUwcD-1712272082495)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。