I'm currently developing a flutter mobile app by using sliver appbar and I want to add some widget to collapsed app bar.and also make background color to gradient. when I tried to add by using leading property it creates overflow and also the widget displays in the flexspacebar.
The above image is before scroll.
and this one is after scroll and I want to add some widget in the center of the blue part.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rehove/Widgets/sliver_card.dart';
import '../Widgets/action_button.dart';
class UserScreen extends StatelessWidget {
const UserScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
TextTheme _textTheme = Theme.of(context).textTheme;
return
AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light
),
child: Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
collapsedHeight: 320,
pinned: true,
leadingWidth: 200,
leading: Padding(
padding: EdgeInsets.only(left:32),
child: GestureDetector(
onTap:()=>{
Navigator.pop(context)
},
child: Row(
children: [
Icon(Icons.arrow_back_ios),
Text('Back',style: _textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16
),)
],
),
),
),
expandedHeight: 450,
flexibleSpace: FlexibleSpaceBar(
background: Stack(
children: [
Image.asset('assets/images/user.png',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
Align(
alignment:Alignment.bottomCenter,
child: Container(
height: 102,
width: double.infinity,
color:Color(0xffD9D9D9).withOpacity(0.6),
child:Padding(
padding:const EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Liya Dereje',style: _textTheme.bodyLarge?.copyWith(
color: Color(0xffffffff),
fontWeight: FontWeight.w500,
fontSize: 20
),),
Text('[email protected]',style: _textTheme.bodyLarge?.copyWith(
color: Color(0xfff7f7f7),
fontWeight: FontWeight.w500,
fontSize: 12
),)
],
),
ActionButton(label: 'Edit Profile',
height: 38,
width: 20,
onPressed: () { },)
],
),
)
),
)
]
),
),
),
SliverToBoxAdapter(
child:Column(children: [
const SizedBox(height: 40,),
Row(
children: [
const Expanded(child: Divider(thickness: 1,)),
Text('Setting',style: _textTheme.bodySmall?.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400
),),
const Expanded(child: Divider(thickness: 1,)),
],
),
const SizedBox(height: 16,),
SliverCard(icon: Icons.notifications_outlined,title: 'Notification',amount: '4',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.donut_small,title: 'Reports',amount: '4',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.email_outlined,title: 'Email',amount: '5',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.description_outlined,title: 'Terms of',amount: '3',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.accessibility_new_rounded,title: 'Accessibility',amount: '4',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.logout,title: 'Logout',amount: '4',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.email_outlined,title: 'Email',amount: '5',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.description_outlined,title: 'Terms of',amount: '3',),
const SizedBox(height: 10,),
SliverCard(icon: Icons.accessibility_new_rounded,title: 'Accessibility',amount: '4',),
const SizedBox(height: 10,),
],
)
)
],
),
)
);
}
}
CodePudding user response:
Add another Stack
that wraps your FlexibleSpaceBar
and the widget you want in the middle when collapsed. Try this:
flexibleSpace: Stack(
children: [
Positioned.fill(
child: Align(
alignment: Alignment.center,
child: Text('I\'m in the center'),
),
),
FlexibleSpaceBar(
background: Stack(children: [
Image.asset(
'assets/images/user.png',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 102,
width: double.infinity,
color: Color(0xffD9D9D9).withOpacity(0.6),
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'Liya Dereje',
style: _textTheme.bodyLarge?.copyWith(
color: Color(0xffffffff),
fontWeight: FontWeight.w500,
fontSize: 20),
),
Text(
'[email protected]',
style: _textTheme.bodyLarge?.copyWith(
color: Color(0xfff7f7f7),
fontWeight: FontWeight.w500,
fontSize: 12),
)
],
),
ActionButton(
label: 'Edit Profile',
height: 38,
width: 20,
onPressed: () {},
)
],
),
)),
)
]),
),
],
),
CodePudding user response:
Step 1: First declare the varibale
bool lastStatus = true;
ScrollController? _nestedScrollController;
Step 2:
void _scrollListener() {
if (_isShrink != lastStatus) {
setState(() {
lastStatus = _isShrink;
});
}
}
bool get _isShrink {
return _nestedScrollController != null &&
_nestedScrollController!.hasClients &&
_nestedScrollController!.offset > (30.h - kToolbarHeight);
}
put above method inside the class
Step 3:
@override
void dispose() {
_nestedScrollController?.removeListener(_scrollListener);
_nestedScrollController?.dispose();
super.dispose();
}
@override
void initState() {
_nestedScrollController =
ScrollController(initialScrollOffset: 33.h - kToolbarHeight)
..addListener(_scrollListener);
}
Put the above method inside the init and dispose
Step 4:
Scaffold(
resizeToAvoidBottomInset: false,
body: NestedScrollView(
controller: _nestedScrollController,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
TransitionsAppsBar(
isShrink: _isShrink,
….
…
),
];
},
body: child…
Step 5: Use require code inside the below class
class TransitionsAppsBar extends StatelessWidget {
final bool isShrink;
final VoidCallback? onBackTap;
final VoidCallback? onInfoTap;
final VoidCallback? onTap;
final VoidCallback onAlertTap;
final GroupDetailsDTO? groupInfo;
final bool isOverDue;
const TransitionsAppsBar({
Key? key,
this.isShrink = true,
this.onBackTap,
this.onInfoTap,
this.groupInfo,
this.onTap,
this.isOverDue = false,
required this.onAlertTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<GroupBloc, GroupState>(
builder: (context, state) {
return SliverAppBar(
elevation: 2,
backgroundColor: AppTheme.secondaryColor,
pinned: true,
collapsedHeight: kToolbarHeight (isOverDue ? 25 : 0),
centerTitle: true,
titleSpacing: 0,
leadingWidth: 21.w,
automaticallyImplyLeading: false,
bottom: !isOverDue
? null
: PreferredSize(
child: GestureDetector(
onTap: onAlertTap,
child: Container(
color: AppTheme.primaryColor_100,
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
Assets.icOverdue,
height: 20,
width: 20,
color: AppTheme.whiteColor,
),
const SizedBox(width: 4),
Text(
StringConstants.groupIsInactive,
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: AppTheme.whiteColor),
),
const SizedBox(width: 4),
Text(
StringConstants.learnMore,
style:
Theme.of(context).textTheme.caption!.copyWith(
color: AppTheme.whiteColor,
decoration: TextDecoration.underline,
),
),
],
),
),
),
preferredSize: const Size.fromHeight(0),
),
title: GestureDetector(
onTap: onTap,
child: Visibility(
visible: isShrink,
child: Container(
color: Colors.transparent,
width: 100.w,
height: kToolbarHeight,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
groupInfo?.name ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style:
Theme.of(context).textTheme.caption!.copyWith(
fontSize: 14,
color: AppTheme.whiteColor,
overflow: TextOverflow.ellipsis,
),
),
),
if (groupInfo?.isOverdue ?? false) ...[
const SizedBox(width: 8),
GestureDetector(
onTap: onAlertTap,
child: Image.asset(
Assets.icOverdue,
height: 20,
width: 20,
),
),
]
],
),
if ((groupInfo?.id ?? 0) != 0)
Text(
"${(groupInfo?.memberDetails.length ?? 0).toString()} ${StringConstants.loopers}",
style: Theme.of(context)
.textTheme
.caption!
.copyWith(fontSize: 14, color: AppTheme.whiteColor),
)
else
Container(),
],
),
),
),
),
leading: Stack(
alignment: Alignment.centerLeft,
children: [
Container(
margin: EdgeInsets.only(left: 5.h),
child: Visibility(
visible: isShrink,
child: ((groupInfo?.id ?? 0) != 0)
? ProfilePic(
imageUrl: groupInfo?.image,
name: (groupInfo?.name.length ?? 0) <= 3 ||
groupInfo!.isIndividualGroup
? groupInfo?.name
: groupInfo?.name.characters.take(3).toString(),
picType: groupInfo!.isIndividualGroup
? StringConstants.systemGroup
: StringConstants.group,
)
: Container(),
),
),
BackButtonWidget(onBackTap: onBackTap),
],
),
expandedHeight: 30.h,
flexibleSpace: FlexibleSpaceBar(
background: Center(
child: Visibility(
visible: !isShrink,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 12.h),
child: ((groupInfo?.id ?? 0) != 0)
? ProfilePic(
imageUrl: groupInfo?.image,
name: (groupInfo?.name.length ?? 0) <= 3 ||
groupInfo!.isIndividualGroup
? groupInfo?.name
: groupInfo?.name.characters.take(3).toString(),
picType: groupInfo!.isIndividualGroup
? StringConstants.systemGroup
: StringConstants.group,
sizeMultiplier: 2.5.h,
)
: Container(),
),
SizedBox(height: 2.h),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 12),
child: Text(
groupInfo?.name ?? "",
maxLines: 2,
style:
Theme.of(context).textTheme.subtitle2!.copyWith(
color: AppTheme.whiteColor,
overflow: TextOverflow.ellipsis,
),
),
),
),
if (groupInfo?.isOverdue ?? false)
Padding(
padding: const EdgeInsets.only(right: 12, left: 8),
child: GestureDetector(
onTap: onAlertTap,
child: Image.asset(
Assets.icOverdue,
height: 20,
width: 20,
),
),
)
else
const SizedBox(width: 12),
],
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
(groupInfo?.memberDetails ?? [])
.getMemberNames(groupInfo?.adminId ?? 0),
style: Theme.of(context)
.textTheme
.caption
?.copyWith(color: AppTheme.whiteColor),
),
),
],
),
),
)),
actions: [
Visibility(
visible: !groupInfo!.isIndividualGroup &&
!state.isFetchingGroupDetails,
child: GestureDetector(
onTap: onInfoTap,
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Image.asset(
Assets.icInfoGroup,
height: 25,
width: 25,
color: AppTheme.whiteColor,
),
),
),
)
],
);
},
);
}
}