diff --git a/lib/widgets/album/filter_bar.dart b/lib/widgets/album/filter_bar.dart index e3531bd58..d64ca99a2 100644 --- a/lib/widgets/album/filter_bar.dart +++ b/lib/widgets/album/filter_bar.dart @@ -4,7 +4,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class FilterBar extends StatelessWidget implements PreferredSizeWidget { - static const double preferredHeight = kMinInteractiveDimension; + static const double verticalPadding = 16; + static const double preferredHeight = AvesFilterChip.minChipHeight + verticalPadding; @override final Size preferredSize = const Size.fromHeight(preferredHeight); @@ -26,7 +27,7 @@ class FilterBar extends StatelessWidget implements PreferredSizeWidget { child: ListView.separated( scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(AvesFilterChip.buttonBorderWidth / 2) + const EdgeInsets.symmetric(horizontal: 6), + padding: const EdgeInsets.symmetric(horizontal: 8), itemBuilder: (context, index) { if (index >= filters.length) return null; final filter = filters[index]; diff --git a/lib/widgets/album/search/expandable_filter_row.dart b/lib/widgets/album/search/expandable_filter_row.dart index 68f5d004f..d5e0293fc 100644 --- a/lib/widgets/album/search/expandable_filter_row.dart +++ b/lib/widgets/album/search/expandable_filter_row.dart @@ -17,6 +17,9 @@ class ExpandableFilterRow extends StatelessWidget { @required this.onPressed, }); + static const double horizontalPadding = 8; + static const double verticalPadding = 8; + @override Widget build(BuildContext context) { if (filters.isEmpty) return const SizedBox.shrink(); @@ -48,12 +51,13 @@ class ExpandableFilterRow extends StatelessWidget { final filtersList = filters.toList(); final wrap = Container( key: ValueKey('wrap$title'), - padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.buttonBorderWidth / 2 + 6), + padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), // specify transparent as a workaround to prevent // chip border clipping when the floating app bar is fading color: Colors.transparent, child: Wrap( - spacing: 8, + spacing: horizontalPadding, + runSpacing: verticalPadding, children: filtersList .map((filter) => AvesFilterChip( filter: filter, @@ -67,19 +71,17 @@ class ExpandableFilterRow extends StatelessWidget { // specify transparent as a workaround to prevent // chip border clipping when the floating app bar is fading color: Colors.transparent, - height: kMinInteractiveDimension, + height: AvesFilterChip.minChipHeight, child: ListView.separated( scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(AvesFilterChip.buttonBorderWidth / 2) + const EdgeInsets.symmetric(horizontal: 6), + padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), itemBuilder: (context, index) { if (index >= filtersList.length) return null; final filter = filtersList[index]; - return Center( - child: AvesFilterChip( - filter: filter, - onPressed: onPressed, - ), + return AvesFilterChip( + filter: filter, + onPressed: onPressed, ); }, separatorBuilder: (context, index) => const SizedBox(width: 8), diff --git a/lib/widgets/album/search/search_delegate.dart b/lib/widgets/album/search/search_delegate.dart index 994f5cb22..b4cd54cdf 100644 --- a/lib/widgets/album/search/search_delegate.dart +++ b/lib/widgets/album/search/search_delegate.dart @@ -58,6 +58,7 @@ class ImageSearchDelegate extends SearchDelegate { valueListenable: expandedSectionNotifier, builder: (context, expandedSection, child) { return ListView( + padding: const EdgeInsets.only(top: 8), children: [ _buildFilterRow( context: context, diff --git a/lib/widgets/common/aves_filter_chip.dart b/lib/widgets/common/aves_filter_chip.dart index f34138795..7fa5ec9ca 100644 --- a/lib/widgets/common/aves_filter_chip.dart +++ b/lib/widgets/common/aves_filter_chip.dart @@ -13,7 +13,8 @@ class AvesFilterChip extends StatefulWidget { final FilterCallback onPressed; static final BorderRadius borderRadius = BorderRadius.circular(32); - static const double buttonBorderWidth = 2; + static const double outlineWidth = 2; + static const double minChipHeight = kMinInteractiveDimension; static const double minChipWidth = 80; static const double maxChipWidth = 160; static const double iconSize = 20; @@ -116,49 +117,59 @@ class _AvesFilterChipState extends State { ); } - final shape = RoundedRectangleBorder( - borderRadius: AvesFilterChip.borderRadius, - ); + final borderRadius = AvesFilterChip.borderRadius; - final button = ButtonTheme( - minWidth: 0, - child: Container( - constraints: const BoxConstraints( - minWidth: AvesFilterChip.minChipWidth, - maxWidth: AvesFilterChip.maxChipWidth, - ), - decoration: widget.decoration, - child: Tooltip( - message: filter.tooltip, - preferBelow: false, - child: FutureBuilder( - future: _colorFuture, - builder: (context, AsyncSnapshot snapshot) { - return OutlineButton( - onPressed: widget.onPressed != null ? () => widget.onPressed(filter) : null, - borderSide: BorderSide( - color: snapshot.hasData ? snapshot.data : Colors.transparent, - width: AvesFilterChip.buttonBorderWidth, - ), - padding: EdgeInsets.zero, - shape: shape, - child: content, - ); - }, + final chip = Container( + constraints: const BoxConstraints( + minWidth: AvesFilterChip.minChipWidth, + maxWidth: AvesFilterChip.maxChipWidth, + minHeight: AvesFilterChip.minChipHeight, + ), + decoration: widget.decoration, + child: Tooltip( + message: filter.tooltip, + preferBelow: false, + child: Material( + color: widget.decoration != null ? Colors.transparent : Theme.of(context).scaffoldBackgroundColor, + shape: RoundedRectangleBorder( + borderRadius: borderRadius, + ), + child: InkWell( + onTap: widget.onPressed != null ? () => widget.onPressed(filter) : null, + borderRadius: borderRadius, + child: FutureBuilder( + future: _colorFuture, + builder: (context, AsyncSnapshot snapshot) { + final outlineColor = snapshot.hasData ? snapshot.data : Colors.transparent; + return DecoratedBox( + decoration: BoxDecoration( + border: Border.all( + color: outlineColor, + width: AvesFilterChip.outlineWidth, + ), + borderRadius: borderRadius, + ), + position: DecorationPosition.foreground, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: content, + ), + ); + }, + ), ), ), ), ); - return button; - // TODO TLAD how to lerp between chip and grid tile -// return Hero( -// tag: filter, -// flightShuttleBuilder: (flight, animation, direction, fromHeroContext, toHeroContext) { -// final toHero = toHeroContext.widget as Hero; -// return Center(content: toHero.content); -// }, -// content: button, -// ); + // TODO TLAD only hero between `FilterBar` and chips that are tapped + return Hero( + tag: filter, + flightShuttleBuilder: (flight, animation, direction, fromHeroContext, toHeroContext) { + final toHero = toHeroContext.widget as Hero; + return Center(child: toHero.child); + }, + child: chip, + ); } } diff --git a/lib/widgets/filter_grid_page.dart b/lib/widgets/filter_grid_page.dart index d30ed273f..5e5886fa5 100644 --- a/lib/widgets/filter_grid_page.dart +++ b/lib/widgets/filter_grid_page.dart @@ -87,7 +87,7 @@ class FilterGridPage extends StatelessWidget { slivers: [ appBar, SliverPadding( - padding: const EdgeInsets.all(AvesFilterChip.buttonBorderWidth), + padding: const EdgeInsets.all(AvesFilterChip.outlineWidth), sliver: SliverGrid( delegate: SliverChildBuilderDelegate( (context, i) { diff --git a/lib/widgets/fullscreen/info/basic_section.dart b/lib/widgets/fullscreen/info/basic_section.dart index 4b259d509..eb9e720ba 100644 --- a/lib/widgets/fullscreen/info/basic_section.dart +++ b/lib/widgets/fullscreen/info/basic_section.dart @@ -57,9 +57,10 @@ class BasicSection extends StatelessWidget { ]..sort(); if (filters.isEmpty) return const SizedBox.shrink(); return Padding( - padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.buttonBorderWidth / 2) + const EdgeInsets.only(top: 8), + padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + const EdgeInsets.only(top: 8), child: Wrap( spacing: 8, + runSpacing: 8, children: filters .map((filter) => AvesFilterChip( filter: filter, diff --git a/lib/widgets/fullscreen/info/info_page.dart b/lib/widgets/fullscreen/info/info_page.dart index fa148f3d0..b3c278d54 100644 --- a/lib/widgets/fullscreen/info/info_page.dart +++ b/lib/widgets/fullscreen/info/info_page.dart @@ -169,7 +169,7 @@ class SectionRow extends StatelessWidget { final buildDivider = () => const SizedBox( width: dim, child: Divider( - thickness: AvesFilterChip.buttonBorderWidth, + thickness: AvesFilterChip.outlineWidth, color: Colors.white70, ), ); diff --git a/lib/widgets/fullscreen/info/location_section.dart b/lib/widgets/fullscreen/info/location_section.dart index 68b4f8d70..180f1442d 100644 --- a/lib/widgets/fullscreen/info/location_section.dart +++ b/lib/widgets/fullscreen/info/location_section.dart @@ -110,9 +110,10 @@ class _LocationSectionState extends State { ), if (filters.isNotEmpty) Padding( - padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.buttonBorderWidth / 2) + const EdgeInsets.only(top: 8), + padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + const EdgeInsets.only(top: 8), child: Wrap( spacing: 8, + runSpacing: 8, children: filters .map((filter) => AvesFilterChip( filter: filter, diff --git a/lib/widgets/stats/filter_table.dart b/lib/widgets/stats/filter_table.dart index af99dd800..2a747f013 100644 --- a/lib/widgets/stats/filter_table.dart +++ b/lib/widgets/stats/filter_table.dart @@ -36,7 +36,7 @@ class FilterTable extends StatelessWidget { final lineHeight = 16 * textScaleFactor; return Padding( - padding: const EdgeInsetsDirectional.only(start: AvesFilterChip.buttonBorderWidth / 2 + 6, end: 8), + padding: const EdgeInsetsDirectional.only(start: AvesFilterChip.outlineWidth / 2 + 6, end: 8), child: LayoutBuilder( builder: (context, constraints) { final showPercentIndicator = constraints.maxWidth - (chipWidth + countWidth) > percentIndicatorMinWidth; @@ -48,7 +48,8 @@ class FilterTable extends StatelessWidget { final percent = count / maxCount; return TableRow( children: [ - Align( + Container( + padding: const EdgeInsets.only(bottom: 8), alignment: AlignmentDirectional.centerStart, child: AvesFilterChip( filter: filter,