英文:
Flutter animated sliver header
问题
我正在尝试创建一个可以进行动画的个人资料页标头。
如果您考虑上面的图片,Section 1
是我们在完全展开的标头中看到的内容,Section 2
是我们想在固定模式下看到的内容。
现在,我想要过渡,将图像 - 紫色圆圈 - 移动到一侧,轻微缩小它,还要移动名称和链接。
我可以实现所有这些,但有一件事我不知道如何做:如何在展开视图中将它们居中显示。
由于我必须使用变换来移动小部件,所以不能简单地使用像列或中心这样的居中小部件。我也没有找到一种计算精确居中小部件位置的方法,因为它需要小部件的大小,而我没有这个信息。
英文:
I am trying to create a profile header sliver that can animate.
If you consider above image, Section 1
is what we see in the fully expanded sliver, and Section 2
is what we want to see in pinned mode.
Now I would like transition to move the image - purple circle - to the side, shrink it slightly, and also move the name and the links.
I can achieve all of that but one thing: How to center them in the expanded view.
As I have to use transform to move widgets around, I cannot simply use a centring widget like column or center. And I didn't find a way to calculate the exact position to center the widget, as it needs the size of the widget, that I don't have.
答案1
得分: 1
首先,我正在使用SliverPersistentHeaderDelegate
,它提供了shrinkOffset
,将在线性插值(lerp方法)中使用。
然后使用CompositedTransformTarget
小部件来跟随中心小部件。
在这个示例中,可以使用targetAnchor
和followerAnchor
,并使用t
/shrinkOffset
来维护其他动画。
class SFeb223 extends StatelessWidget {
const SFeb223({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
delegate: MySliverPersistentHeaderDelegate(),
pinned: true,
),
SliverToBoxAdapter(
child: SizedBox(
height: 1333,
),
)
],
),
);
}
}
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
final LayerLink layerLink = LayerLink();
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
double t = shrinkOffset / maxExtent;
return Material(
color: Colors.cyanAccent.withOpacity(.2),
child: Stack(
children: [
Align(
alignment:
Alignment.lerp(Alignment.center, Alignment.centerLeft, t)!,
child: CompositedTransformTarget(
link: layerLink,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: lerpDouble(100, kToolbarHeight - 10, t),
width: lerpDouble(100, kToolbarHeight - 10, t),
decoration: const ShapeDecoration(
shape: CircleBorder(),
color: Colors.deepPurple,
),
),
),
),
),
CompositedTransformFollower(
link: layerLink,
targetAnchor: Alignment.lerp(
Alignment.bottomCenter, Alignment.centerRight, t)!,
followerAnchor:
Alignment.lerp(Alignment.topCenter, Alignment.centerLeft, t)!,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Column(
children: [Text("Sheikh")],
),
),
),
),
],
),
);
}
@override
double get maxExtent => kToolbarHeight * 6;
@override
double get minExtent => kToolbarHeight;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
false;
}
英文:
Firstly I am using SliverPersistentHeaderDelegate
and it provides shrinkOffset
that will be used on linear interpolation(lerp method).
Then CompositedTransformTarget
widget to follow the center widget.
On this example play with targetAnchor
and followerAnchor
and use t
/shrinkOffset
to maintain other animation.
class SFeb223 extends StatelessWidget {
const SFeb223({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
delegate: MySliverPersistentHeaderDelegate(),
pinned: true,
),
SliverToBoxAdapter(
child: SizedBox(
height: 1333,
),
)
],
),
);
}
}
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
final LayerLink layerLink = LayerLink();
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
double t = shrinkOffset / maxExtent;
return Material(
color: Colors.cyanAccent.withOpacity(.2),
child: Stack(
children: [
Align(
alignment:
Alignment.lerp(Alignment.center, Alignment.centerLeft, t)!,
child: CompositedTransformTarget(
link: layerLink,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: lerpDouble(100, kToolbarHeight - 10, t),
width: lerpDouble(100, kToolbarHeight - 10, t),
decoration: const ShapeDecoration(
shape: CircleBorder(),
color: Colors.deepPurple,
),
),
),
),
),
CompositedTransformFollower(
link: layerLink,
targetAnchor: Alignment.lerp(
Alignment.bottomCenter, Alignment.centerRight, t)!,
followerAnchor:
Alignment.lerp(Alignment.topCenter, Alignment.centerLeft, t)!,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Column(
children: [Text("Sheikh")],
),
),
),
),
],
),
);
}
@override
double get maxExtent => kToolbarHeight * 6;
@override
double get minExtent => kToolbarHeight;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
false;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论