So I have a pretty simple issue. I have an image. Lets say its 'assets/images/user.png'. I want that image to appear in the top left of the app (In the middle of the white circle). When the user scrolls downward, the title, and description both disappear and then the Go Premium button get pinned to the top. I want a user png to appear in the TOP LEFT corner in the MIDDlE of the white circle, and then when the user scrolls down, I want the user png to go down a bit and position itself to the left of the Go Premium button, in the small gap. I want this to work for different phones too, so hardcoding is allowed IF it would work for a smaller phone. Thanks!
Here is an image of my app before scroll:
Here is one after scroll:
CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor:
const Color.fromARGB(12, 14, 13, 3).withOpacity(1),
centerTitle: false,
bottom: PreferredSize(
preferredSize: const Size.fromHeight(0),
child: SizedBox(
width: size.width * .7,
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
backgroundColor: Color.fromARGB(255, 255, 0, 0)),
child: const Text(
'Go Premium!',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold),
),
),
),
),
pinned: true,
expandedHeight: 165,
titleSpacing: 15,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: Stack(
children: [
Positioned(
top: -size.width * .08,
left: -size.width * .08,
child: Transform.translate(
offset: const Offset(-30, -30),
child: const CircleButton(),
),
),
Positioned(
left: size.width * .2,
top: size.height * .09,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('JustLift',
style: TextStyle(
color:
Color.fromARGB(255, 252, 250, 250),
fontWeight: FontWeight.bold,
fontSize: 50)),
Text(
element,
style: TextStyle(
color: Color.fromARGB(255, 158, 154, 154),
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
],
),
),
],
),
),
),
You can use lerp method from SliverPersistentHeaderDelegate
. Try to play with widget
class CustomSliverPersistentHeaderDelegate
extends SliverPersistentHeaderDelegate {
final VoidCallback onTap;
CustomSliverPersistentHeaderDelegate({required this.onTap});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
final t = shrinkOffset / maxExtent;
final avatarSize = lerpDouble(100, 48, t);
return Material(
color: Colors.black,
child: Stack(
children: [
Positioned(
top: lerpDouble(maxExtent / 2, -60, t),
left: 0,
right: 0,
child: Text(
'Hello',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
),
),
),
Positioned(
top: lerpDouble(-20, 0, t),
left: lerpDouble(-20, 4, t),
child: Container(
width: avatarSize,
height: avatarSize,
decoration: const ShapeDecoration(
shape: CircleBorder(),
color: Colors.red,
),
),
),
Positioned(
bottom: 8,
left: 0,
right: 0,
child: Center(
child: ElevatedButton(
onPressed: onTap,
child: Text('Button'),
),
),
),
],
),
);
}
@override
double get maxExtent => 200;
@override
double get minExtent => kToolbarHeight;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
And use like
return Scaffold(
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
delegate: CustomSliverPersistentHeaderDelegate(
onTap: () {},
),
),
SliverToBoxAdapter(
child: SizedBox(
height: 2222,
),
)
],
));
If you need more accuracy on overlapping, You can use CompositedTransformTarget