fixes for font scale

This commit is contained in:
Thibault Deckers 2023-03-19 12:18:06 +01:00
parent 96005031c7
commit c6230df01d
18 changed files with 125 additions and 88 deletions

View file

@ -23,6 +23,7 @@ import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/container.dart';
import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
@ -220,7 +221,8 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
}
double get appBarContentHeight {
double height = kToolbarHeight;
final textScaleFactor = context.read<MediaQueryData>().textScaleFactor;
double height = kToolbarHeight * textScaleFactor;
if (settings.useTvLayout) {
height += CaptionedButton.getTelevisionButtonHeight(context);
}
@ -228,7 +230,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
height += FilterBar.preferredHeight;
}
if (context.read<Query>().enabled) {
height += EntryQueryBar.preferredHeight;
height += EntryQueryBar.getPreferredHeight(textScaleFactor);
}
return height;
}
@ -375,12 +377,14 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
final browsingQuickActions = settings.collectionBrowsingQuickActions;
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
(action) => _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
(action) => FontSizeIconTheme(
child: _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
),
);
return [
...quickActionButtons,
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<EntrySetAction>(
// key is expected by test driver
key: const Key('appbar-menu-button'),

View file

@ -10,8 +10,6 @@ class EntryQueryBar extends StatefulWidget {
final ValueNotifier<String> queryNotifier;
final FocusNode focusNode;
static const preferredHeight = kToolbarHeight;
const EntryQueryBar({
super.key,
required this.queryNotifier,
@ -20,6 +18,8 @@ class EntryQueryBar extends StatefulWidget {
@override
State<EntryQueryBar> createState() => _EntryQueryBarState();
static double getPreferredHeight(double textScaleFactor) => QueryBar.getPreferredHeight(textScaleFactor);
}
class _EntryQueryBarState extends State<EntryQueryBar> {
@ -52,8 +52,9 @@ class _EntryQueryBarState extends State<EntryQueryBar> {
@override
Widget build(BuildContext context) {
final textScaleFactor = context.select<MediaQueryData, double>((mq) => mq.textScaleFactor);
return Container(
height: EntryQueryBar.preferredHeight,
height: EntryQueryBar.getPreferredHeight(textScaleFactor),
alignment: Alignment.topCenter,
child: Selector<Selection<AvesEntry>, bool>(
selector: (context, selection) => !selection.isSelecting,

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class InteractiveAppBarTitle extends StatelessWidget {
final GestureTapCallback? onTap;
@ -19,7 +20,7 @@ class InteractiveAppBarTitle extends StatelessWidget {
child: Container(
alignment: AlignmentDirectional.centerStart,
color: Colors.transparent,
height: kToolbarHeight,
height: kToolbarHeight * context.select<MediaQueryData, double>((mq) => mq.textScaleFactor),
child: child,
),
);

View file

@ -0,0 +1,22 @@
import 'package:flutter/widgets.dart';
// scale icons according to text scale
class FontSizeIconTheme extends StatelessWidget {
final Widget child;
const FontSizeIconTheme({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
final iconTheme = IconTheme.of(context);
return IconTheme(
data: iconTheme.copyWith(
size: iconTheme.size! * MediaQuery.textScaleFactorOf(context),
),
child: child,
);
}
}

View file

@ -32,24 +32,3 @@ class MenuRow extends StatelessWidget {
);
}
}
// scale icons according to text scale
class MenuIconTheme extends StatelessWidget {
final Widget child;
const MenuIconTheme({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
final iconTheme = IconTheme.of(context);
return IconTheme(
data: iconTheme.copyWith(
size: iconTheme.size! * MediaQuery.textScaleFactorOf(context),
),
child: child,
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
@ -24,6 +25,8 @@ class QueryBar extends StatefulWidget {
@override
State<QueryBar> createState() => _QueryBarState();
static double getPreferredHeight(double textScaleFactor) => kToolbarHeight * textScaleFactor;
}
class _QueryBarState extends State<QueryBar> {
@ -53,45 +56,50 @@ class _QueryBarState extends State<QueryBar> {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyMedium!,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: TextField(
controller: _controller,
focusNode: widget.focusNode,
decoration: InputDecoration(
icon: Padding(
padding: widget.leadingPadding ?? const EdgeInsetsDirectional.only(start: 16),
child: Icon(widget.icon ?? AIcons.filter),
),
hintText: widget.hintText ?? MaterialLocalizations.of(context).searchFieldLabel,
hintStyle: Theme.of(context).inputDecorationTheme.hintStyle,
),
textInputAction: TextInputAction.search,
onChanged: (s) => _debouncer(() => queryNotifier.value = s.trim()),
enabled: widget.editable,
),
),
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 16),
child: ValueListenableBuilder<TextEditingValue>(
valueListenable: _controller,
builder: (context, value, child) => AnimatedSwitcher(
duration: Durations.appBarActionChangeAnimation,
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation,
child: SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
child: child,
child: FontSizeIconTheme(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: TextField(
controller: _controller,
focusNode: widget.focusNode,
decoration: InputDecoration(
icon: Padding(
padding: widget.leadingPadding ?? const EdgeInsetsDirectional.only(start: 16),
// set theme at this level because `InputDecoration` defines its own `IconTheme` with a fixed size
child: FontSizeIconTheme(
child: Icon(widget.icon ?? AIcons.filter),
),
),
hintText: widget.hintText ?? MaterialLocalizations.of(context).searchFieldLabel,
hintStyle: Theme.of(context).inputDecorationTheme.hintStyle,
),
child: value.text.isNotEmpty ? clearButton : const SizedBox(),
textInputAction: TextInputAction.search,
onChanged: (s) => _debouncer(() => queryNotifier.value = s.trim()),
enabled: widget.editable,
),
),
),
],
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 16),
child: ValueListenableBuilder<TextEditingValue>(
valueListenable: _controller,
builder: (context, value, child) => AnimatedSwitcher(
duration: Durations.appBarActionChangeAnimation,
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation,
child: SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
child: child,
),
),
child: value.text.isNotEmpty ? clearButton : const SizedBox(),
),
),
),
],
),
),
);
}

View file

@ -55,7 +55,7 @@ class AvesAppBar extends StatelessWidget {
child: Column(
children: [
SizedBox(
height: kToolbarHeight,
height: kToolbarHeight * context.select<MediaQueryData, double>((mq) => mq.textScaleFactor),
child: Row(
children: [
leading != null

View file

@ -14,6 +14,7 @@ import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/collection/filter_bar.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
@ -127,7 +128,7 @@ class AvesFilterChip extends StatefulWidget {
}
return PopupMenuItem(
value: action,
child: MenuIconTheme(
child: FontSizeIconTheme(
child: MenuRow(text: text, icon: action.getIcon()),
),
);

View file

@ -8,6 +8,7 @@ import 'package:aves/model/source/collection_source.dart';
import 'package:aves/services/analysis_service.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/behaviour/pop/scope.dart';
@ -49,7 +50,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
appBar: AppBar(
title: const Text('Debug'),
actions: [
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<AppDebugAction>(
// key is expected by test driver
key: const Key('appbar-menu-button'),

View file

@ -7,6 +7,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/collection/collection_grid.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -81,7 +82,7 @@ class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
autofocus: true,
),
),
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<String>(
itemBuilder: (context) {
return [

View file

@ -13,7 +13,7 @@ import 'package:aves/model/vaults/details.dart';
import 'package:aves/model/vaults/vaults.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
@ -209,12 +209,16 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
}) {
return [
if (widget.moveType != null)
..._quickActions.where(isVisible).map((action) => IconButton(
icon: action.getIcon(),
onPressed: () => onActionSelected(action),
tooltip: action.getText(context),
)),
MenuIconTheme(
..._quickActions.where(isVisible).map(
(action) => FontSizeIconTheme(
child: IconButton(
icon: action.getIcon(),
onPressed: () => onActionSelected(action),
tooltip: action.getText(context),
),
),
),
FontSizeIconTheme(
child: PopupMenuButton<ChipSetAction>(
itemBuilder: (context) {
return _menuActions.where((v) => v == null || isVisible(v)).map((action) {

View file

@ -11,6 +11,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
@ -171,12 +172,13 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
}
double get appBarContentHeight {
double height = kToolbarHeight;
final textScaleFactor = context.read<MediaQueryData>().textScaleFactor;
double height = kToolbarHeight * textScaleFactor;
if (settings.useTvLayout) {
height += CaptionedButton.getTelevisionButtonHeight(context);
}
if (context.read<Query>().enabled) {
height += FilterQueryBar.preferredHeight;
height += FilterQueryBar.getPreferredHeight(textScaleFactor);
}
return height;
}
@ -226,7 +228,12 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
return InteractiveAppBarTitle(
onTap: appMode.canNavigate ? _goToSearch : null,
child: SourceStateAwareAppBarTitle(
title: Text(widget.title),
title: Text(
widget.title,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,
),
source: source,
),
);
@ -313,12 +320,14 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
final isSelecting = selection.isSelecting;
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
(action) => _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)),
(action) => FontSizeIconTheme(
child: _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)),
),
);
return [
...quickActionButtons,
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<ChipSetAction>(
itemBuilder: (context) {
final generalMenuItems = ChipSetActions.general.where(isVisible).map(

View file

@ -9,8 +9,6 @@ class FilterQueryBar<T extends CollectionFilter> extends StatelessWidget {
final ValueNotifier<String> queryNotifier;
final FocusNode focusNode;
static const preferredHeight = kToolbarHeight;
const FilterQueryBar({
super.key,
required this.queryNotifier,
@ -19,8 +17,9 @@ class FilterQueryBar<T extends CollectionFilter> extends StatelessWidget {
@override
Widget build(BuildContext context) {
final textScaleFactor = context.select<MediaQueryData, double>((mq) => mq.textScaleFactor);
return Container(
height: FilterQueryBar.preferredHeight,
height: getPreferredHeight(textScaleFactor),
alignment: Alignment.topCenter,
child: Selector<Selection<FilterGridItem<T>>, bool>(
selector: (context, selection) => !selection.isSelecting,
@ -33,4 +32,6 @@ class FilterQueryBar<T extends CollectionFilter> extends StatelessWidget {
),
);
}
static double getPreferredHeight(double textScaleFactor) => QueryBar.getPreferredHeight(textScaleFactor);
}

View file

@ -18,6 +18,7 @@ import 'package:aves/theme/icons.dart';
import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/insets.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
@ -567,7 +568,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
PopupMenuItem<MapClusterAction> _buildMenuItem(MapClusterAction action) {
return PopupMenuItem(
value: action,
child: MenuIconTheme(
child: FontSizeIconTheme(
child: MenuRow(
text: action.getText(context),
icon: action.getIcon(),

View file

@ -6,6 +6,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -69,7 +70,7 @@ class _FilePickerPageState extends State<FilePickerPage> {
appBar: AppBar(
title: Text(_getTitle(context)),
actions: [
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<_PickerAction>(
itemBuilder: (context) {
return [

View file

@ -11,6 +11,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/insets.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
@ -127,7 +128,7 @@ class _SettingsPageState extends State<SettingsPage> with FeedbackMixin {
onPressed: () => _goToSearch(context),
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
),
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<SettingsAction>(
itemBuilder: (context) {
return [

View file

@ -9,6 +9,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/app_bar/sliver_app_bar_title.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
@ -72,7 +73,7 @@ class InfoAppBar extends StatelessWidget {
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
),
if (entry.canEdit)
MenuIconTheme(
FontSizeIconTheme(
child: PopupMenuButton<EntryAction>(
itemBuilder: (context) => [
...commonActions.map((action) => _toMenuItem(context, action, enabled: actionDelegate.canApply(entry, action))),

View file

@ -16,6 +16,7 @@ import 'package:aves/widgets/common/action_controls/quick_choosers/tag_button.da
import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
import 'package:aves/widgets/common/action_controls/togglers/mute.dart';
import 'package:aves/widgets/common/action_controls/togglers/play.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/container.dart';
import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
import 'package:aves/widgets/common/basic/popup/menu_button.dart';
@ -240,7 +241,7 @@ class ViewerButtonRowContent extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: padding / 2),
child: OverlayButton(
scale: scale,
child: MenuIconTheme(
child: FontSizeIconTheme(
child: AvesPopupMenuButton<EntryAction>(
key: const Key('entry-menu-button'),
itemBuilder: (context) {