added bottom widget to SliverScreen

This commit is contained in:
Vadim 2024-10-24 12:09:11 +02:00
parent 756c179567
commit 3870dfeb28
2 changed files with 24 additions and 13 deletions

View file

@ -1,15 +1,18 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/text_height.dart';
class SliverScreen extends StatelessWidget { class SliverScreen extends StatelessWidget {
final Widget title; final Widget title;
final List<Widget> appBarActions; final List<Widget> appBarActions;
final PreferredSizeWidget? bottom;
final List<Widget> slivers; final List<Widget> slivers;
const SliverScreen({ const SliverScreen({
required this.title, required this.title,
this.appBarActions = const [], this.appBarActions = const [],
this.bottom,
required this.slivers, required this.slivers,
super.key, super.key,
}); });
@ -24,7 +27,7 @@ class SliverScreen extends StatelessWidget {
slivers: <Widget>[ slivers: <Widget>[
SliverAppBar.large( SliverAppBar.large(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
expandedHeight: Dimens.sliverAppBarExpandedHeight, expandedHeight: Dimens.sliverAppBarExpandedHeight + (bottom?.preferredSize.height ?? 0.0),
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(
centerTitle: false, centerTitle: false,
titlePadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), titlePadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
@ -37,10 +40,12 @@ class SliverScreen extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
child: _Title( child: _Title(
actionsCount: appBarActions.length + (Navigator.of(context).canPop() ? 1 : 0), actionsCount: appBarActions.length + (Navigator.of(context).canPop() ? 1 : 0),
bottomSize: bottom?.preferredSize.height ?? 0.0,
child: title, child: title,
), ),
), ),
), ),
bottom: bottom,
actions: [ actions: [
...appBarActions, ...appBarActions,
if (Navigator.of(context).canPop()) if (Navigator.of(context).canPop())
@ -62,35 +67,37 @@ class SliverScreen extends StatelessWidget {
class _Title extends StatelessWidget { class _Title extends StatelessWidget {
final Widget child; final Widget child;
final int actionsCount; final int actionsCount;
final double bottomSize;
final double actionsPadding; final double actionsPadding;
const _Title({ const _Title({
required this.actionsCount, required this.actionsCount,
required this.bottomSize,
required this.child, required this.child,
}) : actionsPadding = Dimens.grid48 * actionsCount - Dimens.paddingM; }) : actionsPadding = Dimens.grid48 * actionsCount - Dimens.paddingM;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final settings = context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!; final settings = context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!;
final titleScale = _titleScale(settings); final extentScale =
((settings.maxExtent - settings.currentExtent) / (settings.maxExtent - settings.minExtent)).clamp(0.0, 1.0);
final titleScale = Tween<double>(begin: 1.5, end: 1.0).transform(extentScale);
final maxFromTextToAppbar = settings.maxExtent - settings.minExtent - Dimens.paddingM; final maxFromTextToAppbar = settings.maxExtent - settings.minExtent - Dimens.paddingM;
final currentFromTextToAppbar = settings.currentExtent - settings.minExtent - Dimens.paddingM; final currentFromTextToAppbar = settings.currentExtent - settings.minExtent - Dimens.paddingM;
final actionsPaddingScale = (1 - currentFromTextToAppbar / maxFromTextToAppbar).clamp(0.0, 1.0); final actionsPaddingScale = (1 - currentFromTextToAppbar / maxFromTextToAppbar).clamp(0.0, 1.0);
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) => SizedBox( builder: (context, constraints) => Padding(
height: settings.minExtent - MediaQuery.paddingOf(context).top, padding: EdgeInsets.only(bottom: (Dimens.paddingM * (1 - actionsPaddingScale) + bottomSize) / titleScale),
child: SizedBox(
height: DefaultTextStyle.of(context).style.lineHeight * 2,
width: constraints.maxWidth - (actionsPadding * actionsPaddingScale) / titleScale, width: constraints.maxWidth - (actionsPadding * actionsPaddingScale) / titleScale,
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: FractionalOffset(0.0, 0.5 + 0.5 * (1 - extentScale)),
child: child, child: child,
), ),
), ),
),
); );
} }
double _titleScale(FlexibleSpaceBarSettings s) {
final extentScale = ((s.maxExtent - s.currentExtent) / (s.maxExtent - s.minExtent)).clamp(0.0, 1.0);
return Tween<double>(begin: 1.5, end: 1.0).transform(extentScale);
}
} }

View file

@ -34,3 +34,7 @@ Size textSize(
)..layout(maxWidth: maxWidth); )..layout(maxWidth: maxWidth);
return titlePainter.size; return titlePainter.size;
} }
extension TextLineHeight on TextStyle {
double get lineHeight => fontSize! * height!;
}