这遍文章主要是我的页面的个人中心页面.
下面是实现的心路历程
SliverAppBar
即使满足不了现有的需求,抱着学习的想法,对其进行学习一下,其主要效果是通过一下属性
// 属性,分别有不同的效果,不是主要介绍就不列举了
pinned: true,
floating: ture,
snap: true,
NestedScrollView | CustomScrollView |
---|---|
headerSliverBuilder构建 | slivers属性构建 |
--- | --- |
NestedScrollView 代码例子
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool b) {
return [
SliverAppBar(
pinned: true,
floating: false,
expandedHeight: 200,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 200,
child: Image.network(
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39c71164cc4a455b83ac6f579e2a39c1~tplv-k3u1fbpfcp-watermark.image',
fit: BoxFit.fill,
height: 220,
width: Get.width,
),
),
],
),
),
),
bottom: TabBar(
controller: tabController,
tabs: <Widget>[
new Tab(
text: "动态",
),
new Tab(
text: "文章",
),
new Tab(
text: "沸点",
),
new Tab(
text: "其他",
),
],
),
),
];
},
body: TabBarView(
controller: tabController,
children: <Widget>[
],
),
),
);
}
CustomScrollView 代码例子
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
elevation: 0,
expandedHeight: 220,
flexibleSpace: FlexibleSpaceBar(
title: Text('一天清晨'),
background: Image.network(
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39c71164cc4a455b83ac6f579e2a39c1~tplv-k3u1fbpfcp-watermark.image',
fit: BoxFit.cover,
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: TabBarDelegate(
child: TabBar(
labelColor: Colors.black,
controller: this.tabController,
tabs: <Widget>[
Tab(text: '动态'),
Tab(text: '文章'),
Tab(text: '沸点'),
Tab(text: '其他'),
],
),
),
),
SliverFillRemaining(
child: TabBarView(
controller: this.tabController,
children: <Widget>[
],
),
),
],
),
);
};
class TabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar child;
TabBarDelegate({@required this.child});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return this.child;
}
@override
double get maxExtent => this.child.preferredSize.height;
@override
double get minExtent => this.child.preferredSize.height;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
即使没有达到想要的效果,通过自定义头部组件是不是可以达到效果呢?因为在SliverPersistentHeaderDelegate里面的build方法有个shrinkOffset字段,这个是什么意思,打印一下看看:
这个值为滑动的偏移量的值, 这样就可以使用起来了, 利用透明度来完成一些操作,最终效果:
直接在TabBarDelegate类里面构建
Color headerTextColor(shrinkOffset, isIcon) {
if (shrinkOffset <= 50) {
return isIcon ? Colors.white : Colors.transparent;
} else {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255)
.clamp(0, 255)
.toInt();
return Colors.black.withAlpha(alpha);
}
}
int headerBgColor(shrinkOffset) {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255)
.clamp(0, 255)
.toInt();
return alpha;
}
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
height: this.maxExtent,
width: Get.width,
child: Stack(
fit: StackFit.expand,
children: [
Container(
child: Image.network(
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39c71164cc4a455b83ac6f579e2a39c1~tplv-k3u1fbpfcp-watermark.image',
fit: BoxFit.cover),
),
Positioned(
left: 0,
right: 0,
top: 0,
child: Container(
color: Colors.white
.withAlpha(this.headerBgColor(shrinkOffset)),
child: SafeArea(
bottom: false,
child: Container(
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: this
.headerTextColor(shrinkOffset, true),
),
onPressed: () => Navigator.pop(context),
),
Expanded(
child: Row(
children: [
Container(
height: 28,
width: 28,
margin: EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Colors.red.withAlpha(
this.headerBgColor(shrinkOffset)),
borderRadius: BorderRadius.circular(14)),
),
Text(
'一天清晨',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: headerTextColor(
shrinkOffset, false),
),
),
],
)),
IconButton(
icon: Icon(
Icons.share,
color: this
.headerTextColor(shrinkOffset, true),
),
onPressed: () {},
),
],
),
),
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
child: this.child,
decoration: BoxDecoration(color: Colors.blueGrey[100]),
)),
],
),
alignment: Alignment.bottomCenter,
);
}
@override
double get maxExtent => 500;
@override
double get minExtent => Get.context.mediaQueryPadding.top + 88;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
效果基本上都已经可以了,剩下的就是列表的构建,和基本信息的构建了,首先是基本信息的构建
Positioned(
bottom: 48,
left: 0,
right: 0,
child: Container(
width: Get.width,
height: 180,
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.only(left: 20, right: 20),
child: Column(
children: [
Padding(padding: EdgeInsets.only(top: 50)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'一天清晨',
style: TextStyle(
fontSize: 18, color: Colors.black),
),
Container(
margin: EdgeInsets.only(left: 10),
padding: EdgeInsets.symmetric(
horizontal: 5, vertical: 3),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10)),
child: Text(
'LV2',
style: TextStyle(
fontSize: 12,
color: Colors.white,
fontWeight: FontWeight.bold),
),
)
],
),
Text(
'一天清晨',
style:
TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
FlatButton(
onPressed: () {},
child: Text(
'编辑',
style: TextStyle(color: Colors.blue),
),
shape: StadiumBorder(),
padding: EdgeInsets.symmetric(horizontal: 10),
color: Colors.grey.withOpacity(0.2),
)
],
),
Padding(padding: EdgeInsets.only(top: 20)),
Row(
children: [
Container(
margin: EdgeInsets.only(left: 0),
child: Column(
children: [
Text(
'9999',
style: TextStyle(
fontSize: 14, color: Colors.black),
),
Text(
'关注',
style:
TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
Container(
margin: EdgeInsets.only(left: 40),
child: Column(
children: [
Text(
'9999',
style: TextStyle(
fontSize: 14, color: Colors.black),
),
Text(
'关注者',
style:
TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
Container(
margin: EdgeInsets.only(left: 40),
child: Column(
children: [
Text(
'99999',
style: TextStyle(
fontSize: 14, color: Colors.black),
),
Text(
'掘力值',
style: TextStyle(
fontSize: 12, color: Colors.grey),
),
],
))
],
)
],
),
)),
Positioned(
left: 0,
right: 0,
bottom: 190,
child: UnconstrainedBox(
alignment: Alignment.centerLeft,
child: Container(
width: 80,
height: 80,
margin: EdgeInsets.only(left: 20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(40),
border: Border.all(color: Colors.white, width: 4)),
),
)),
接下来就是列表页面的构建了,这部分就比较简单了,所以直接写一个 直接在SliverFillRemaining里面用我们之前封装好的CommonListWiget就好了
SliverFillRemaining(
child: TabBarView(
controller: tabController,
children: <Widget>[
CommonListWiget(
networkApi: (currentPage) async {
return ['1', '1', '1', '1'];
},
itemBuilder: (BuildContext context, int position) {
return itemWidget(true);
},
),
CommonListWiget(
networkApi: (currentPage) async {
return ['1', '1', '1', '1'];
},
itemBuilder: (BuildContext context, int position) {
return itemWidget(true);
},
),
CommonListWiget(
networkApi: (currentPage) async {
return ['1', '1', '1', '1'];
},
itemBuilder: (BuildContext context, int position) {
return itemWidget(true);
},
),
CommonListWiget(
networkApi: (currentPage) async {
return ['1', '1', '1', '1'];
},
itemBuilder: (BuildContext context, int position) {
return itemWidget(true);
},
),
],
),
),
over~~~