You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App_New/lib/widgets/appbar/collapsing_toolbar.dart

206 lines
7.9 KiB
Dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import '../../core/dependencies.dart';
class CollapsingToolbar extends StatefulWidget {
final String title;
Widget child;
VoidCallback? search;
VoidCallback? report;
VoidCallback? logout;
VoidCallback? history;
VoidCallback? instructions;
VoidCallback? requests;
Widget? bottomChild;
Widget? trailing;
bool isClose;
bool isLeading;
CollapsingToolbar({
super.key,
required this.title,
required this.child,
this.search,
this.isClose = false,
this.bottomChild,
this.report,
this.logout,
this.history,
this.instructions,
this.requests,
this.isLeading = true,
this.trailing,
});
@override
State<CollapsingToolbar> createState() => _CollapsingToolbarState();
}
class _CollapsingToolbarState extends State<CollapsingToolbar> {
bool isCollapsed = false;
final ScrollController _controller = ScrollController();
double expandedHeight = 0;
double get maxCollapseOffset => expandedHeight - kToolbarHeight;
@override
void initState() {
super.initState();
_controller.addListener(() {
// If scrolling UP beyond collapsed point → force stop
print("the height is $maxCollapseOffset");
if (_controller.offset > maxCollapseOffset) {
_controller.jumpTo(maxCollapseOffset);
}
});
}
@override
Widget build(BuildContext context) {
expandedHeight = MediaQuery.of(context).size.height * 0.11.h;
AppState appState = getIt.get<AppState>();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body:
// Column(
// children: [
NestedScrollView(
controller: _controller,
floatHeaderSlivers: true,
physics: isCollapsed?NeverScrollableScrollPhysics():BouncingScrollPhysics(),
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverAppBar(
automaticallyImplyLeading: false,
pinned: true,
expandedHeight: MediaQuery.of(context).size.height * 0.11.h,
stretch: true,
systemOverlayStyle: SystemUiOverlayStyle(statusBarBrightness: Brightness.light),
surfaceTintColor: Colors.transparent,
backgroundColor: AppColors.bgScaffoldColor,
leading: widget.isLeading
? Transform.flip(
flipX: appState.isArabic(),
child: IconButton(
icon: Utils.buildSvgWithAssets(icon: widget.isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h),
padding: EdgeInsets.only(left: 12),
onPressed: () => Navigator.pop(context),
highlightColor: Colors.transparent,
),
)
: SizedBox.shrink(),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final double maxHeight = 100.h;
final double minHeight = kToolbarHeight;
double t = (constraints.maxHeight - minHeight) / (maxHeight - minHeight);
t = t - 1;
if (t < 0.7) t = 0.7;
t = t.clamp(0.0, 1.0);
final double fontSize = lerpDouble(14, 18, t)!;
final double bottomPadding = lerpDouble(0, 0, t)!;
final double leftPadding = lerpDouble(150, 24, t)!;
return Stack(
children: [
Align(
alignment: Alignment.lerp(
Alignment.center,
Alignment.bottomLeft,
t,
)!,
child: Padding(
padding: EdgeInsets.only(left: appState.isArabic() ? 0 : leftPadding, right: appState.isArabic() ? leftPadding : 0, bottom: bottomPadding),
child: Row(
spacing: 4.h,
children: [
Text(
widget.title,
maxLines: 1,
style: TextStyle(
fontSize: (27 - (5 * (2 - t))).f,
fontWeight: FontWeight.lerp(
FontWeight.w300,
FontWeight.w600,
t,
)!,
color: AppColors.blackColor,
letterSpacing: -0.5),
).expanded,
if (widget.logout != null) actionButton(context, t, title: "Logout".needTranslation, icon: AppAssets.logout).onPress(widget.logout!),
if (widget.report != null) actionButton(context, t, title: "Report".needTranslation, icon: AppAssets.report_icon).onPress(widget.report!),
if (widget.history != null) actionButton(context, t, title: "History".needTranslation, icon: AppAssets.insurance_history_icon).onPress(widget.history!),
if (widget.instructions != null) actionButton(context, t, title: "Instructions".needTranslation, icon: AppAssets.requests).onPress(widget.instructions!),
if (widget.requests != null) actionButton(context, t, title: "Requests".needTranslation, icon: AppAssets.insurance_history_icon).onPress(widget.requests!),
if (widget.search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(widget.search!).paddingOnly(right: 24),
if (widget.trailing != null) widget.trailing!,
],
)),
),
],
);
},
),
),
];
},
body: widget.child,
),
// ],
// ),
);
}
Widget actionButton(BuildContext context, double t, {required String title, required String icon}) {
return AnimatedSize(
duration: Duration(milliseconds: 150),
child: Container(
height: 40.h,
padding: EdgeInsets.all(8.w),
margin: EdgeInsets.only(right: 24.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.secondaryLightRedColor,
borderRadius: 10.r,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
spacing: 8.h,
children: [
Utils.buildSvgWithAssets(icon: icon, iconColor: AppColors.primaryRedColor),
if (t == 1)
Text(
title,
style: context.dynamicTextStyle(
color: AppColors.primaryRedColor,
letterSpacing: -0.4,
fontSize: (14 - (2 * (1 - t))).f,
fontWeight: FontWeight.lerp(
FontWeight.w300,
FontWeight.w500,
t,
)!,
),
),
],
),
),
);
}
}