fix(ui): New app bar now properly supports long titles

pull/132/head
Inex Code 2022-10-06 10:38:29 +03:00
parent 8aaf62ca5c
commit 2fc20f43c3
2 changed files with 123 additions and 33 deletions

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart';
import 'package:selfprivacy/ui/helpers/widget_size.dart';
class BrandHeroScreen extends StatelessWidget {
const BrandHeroScreen({
@ -32,44 +33,17 @@ class BrandHeroScreen extends StatelessWidget {
color: Theme.of(context).colorScheme.onBackground,
);
final bool hasHeroIcon = heroIcon != null || this.heroIconWidget != null;
const EdgeInsetsGeometry heroTitlePadding = EdgeInsets.only(
bottom: 12.0,
top: 16.0,
);
return Scaffold(
floatingActionButton: hasFlashButton ? const BrandFab() : null,
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: hasHeroIcon ? 160.0 : 96.0,
pinned: true,
stretch: true,
leading: hasBackButton
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: onBackButtonPressed ??
() => Navigator.of(context).pop(),
)
: null,
flexibleSpace: FlexibleSpaceBar(
title: Text(
heroTitle,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
),
expandedTitleScale: 1.2,
centerTitle: true,
collapseMode: CollapseMode.pin,
titlePadding: heroTitlePadding,
background: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (hasHeroIcon) heroIconWidget,
],
),
),
HeroSliverAppBar(
heroTitle: heroTitle,
hasHeroIcon: hasHeroIcon,
hasBackButton: hasBackButton,
onBackButtonPressed: onBackButtonPressed,
heroIconWidget: heroIconWidget,
),
if (heroSubtitle != null)
SliverPadding(
@ -100,3 +74,74 @@ class BrandHeroScreen extends StatelessWidget {
);
}
}
class HeroSliverAppBar extends StatefulWidget {
const HeroSliverAppBar({
required this.heroTitle,
required this.hasHeroIcon,
required this.hasBackButton,
required this.onBackButtonPressed,
required this.heroIconWidget,
final super.key,
});
final String heroTitle;
final bool hasHeroIcon;
final bool hasBackButton;
final VoidCallback? onBackButtonPressed;
final Widget heroIconWidget;
@override
State<HeroSliverAppBar> createState() => _HeroSliverAppBarState();
}
class _HeroSliverAppBarState extends State<HeroSliverAppBar> {
Size _size = Size.zero;
@override
Widget build(final BuildContext context) => SliverAppBar(
expandedHeight:
widget.hasHeroIcon ? 148.0 + _size.height : 72.0 + _size.height,
primary: true,
pinned: true,
stretch: true,
leading: widget.hasBackButton
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: widget.onBackButtonPressed ??
() => Navigator.of(context).pop(),
)
: null,
flexibleSpace: FlexibleSpaceBar(
title: LayoutBuilder(
builder: (final context, final constraints) => SizedBox(
width: constraints.maxWidth - 72.0,
child: WidgetSize(
onChange: (final Size size) => setState(() => _size = size),
child: Text(
widget.heroTitle,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
overflow: TextOverflow.fade,
textAlign: TextAlign.center,
),
),
),
),
expandedTitleScale: 1.2,
centerTitle: true,
collapseMode: CollapseMode.pin,
titlePadding: const EdgeInsets.only(
bottom: 12.0,
top: 16.0,
),
background: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 72.0),
if (widget.hasHeroIcon) widget.heroIconWidget,
],
),
),
);
}

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
class WidgetSize extends StatefulWidget {
const WidgetSize({
required this.onChange,
required this.child,
final super.key,
});
final Widget child;
final Function onChange;
@override
State<WidgetSize> createState() => _WidgetSizeState();
}
class _WidgetSizeState extends State<WidgetSize> {
@override
Widget build(final BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
return Container(
key: widgetKey,
child: widget.child,
);
}
var widgetKey = GlobalKey();
Size? oldSize;
void postFrameCallback(_) {
final context = widgetKey.currentContext;
if (context == null) {
return;
}
;
final newSize = context.size;
if (oldSize == newSize) {
return;
}
oldSize = newSize;
widget.onChange(newSize);
}
}