added time-to-take-action 3s option;
use stretch over bouncing overscroll; fixed time shift wheel scroll bar
This commit is contained in:
parent
512c507942
commit
44ed934a8c
8 changed files with 65 additions and 46 deletions
|
@ -10,6 +10,8 @@ extension ExtraAccessibilityTimeout on AccessibilityTimeout {
|
|||
return context.l10n.settingsSystemDefault;
|
||||
case AccessibilityTimeout.appDefault:
|
||||
return context.l10n.settingsDefault;
|
||||
case AccessibilityTimeout.s3:
|
||||
return context.l10n.timeSeconds(3);
|
||||
case AccessibilityTimeout.s10:
|
||||
return context.l10n.timeSeconds(10);
|
||||
case AccessibilityTimeout.s30:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
enum AccessibilityAnimations { system, disabled, enabled }
|
||||
|
||||
enum AccessibilityTimeout { system, appDefault, s10, s30, s60, s120 }
|
||||
enum AccessibilityTimeout { system, appDefault, s3, s10, s30, s60, s120 }
|
||||
|
||||
enum AvesThemeColorMode { monochrome, polychrome }
|
||||
|
||||
|
|
|
@ -81,14 +81,13 @@ class _FilterBarState extends State<FilterBar> {
|
|||
color: Colors.transparent,
|
||||
height: FilterBar.preferredHeight,
|
||||
child: NotificationListener<ScrollNotification>(
|
||||
// cancel notification bubbling so that the draggable scrollbar
|
||||
// cancel notification bubbling so that the draggable scroll bar
|
||||
// does not misinterpret filter bar scrolling for collection scrolling
|
||||
onNotification: (notification) => true,
|
||||
child: AnimatedList(
|
||||
key: _animatedListKey,
|
||||
initialItemCount: widget.filters.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
itemBuilder: (context, index, animation) {
|
||||
if (index >= widget.filters.length) return const SizedBox();
|
||||
|
|
|
@ -105,6 +105,8 @@ mixin FeedbackMixin {
|
|||
return Duration(milliseconds: millis);
|
||||
case AccessibilityTimeout.appDefault:
|
||||
return appDefaultDuration;
|
||||
case AccessibilityTimeout.s3:
|
||||
return const Duration(seconds: 3);
|
||||
case AccessibilityTimeout.s10:
|
||||
return const Duration(seconds: 10);
|
||||
case AccessibilityTimeout.s30:
|
||||
|
|
|
@ -41,39 +41,51 @@ class _WheelSelectorState<T> extends State<WheelSelector<T>> {
|
|||
const background = Colors.transparent;
|
||||
final foreground = DefaultTextStyle.of(context).style.color!;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: SizedBox(
|
||||
width: itemSize.width,
|
||||
height: itemSize.height * 3,
|
||||
child: ShaderMask(
|
||||
shaderCallback: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
background,
|
||||
foreground,
|
||||
foreground,
|
||||
background,
|
||||
],
|
||||
).createShader,
|
||||
child: ListWheelScrollView(
|
||||
controller: _controller,
|
||||
physics: const FixedExtentScrollPhysics(parent: BouncingScrollPhysics()),
|
||||
diameterRatio: 1.2,
|
||||
itemExtent: itemSize.height,
|
||||
squeeze: 1.3,
|
||||
onSelectedItemChanged: (i) => valueNotifier.value = values[i],
|
||||
children: values
|
||||
.map((i) => SizedBox.fromSize(
|
||||
size: itemSize,
|
||||
child: Text(
|
||||
'$i',
|
||||
textAlign: widget.textAlign,
|
||||
style: widget.textStyle,
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
return NotificationListener<ScrollNotification>(
|
||||
// cancel notification bubbling so that the dialog scroll bar
|
||||
// does not misinterpret wheel scrolling for dialog content scrolling
|
||||
onNotification: (notification) => true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: SizedBox(
|
||||
width: itemSize.width,
|
||||
height: itemSize.height * 3,
|
||||
child: ShaderMask(
|
||||
shaderCallback: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
background,
|
||||
foreground,
|
||||
foreground,
|
||||
background,
|
||||
],
|
||||
).createShader,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
thumbVisibility: MaterialStateProperty.all(false),
|
||||
),
|
||||
),
|
||||
child: ListWheelScrollView(
|
||||
controller: _controller,
|
||||
physics: const FixedExtentScrollPhysics(parent: BouncingScrollPhysics()),
|
||||
diameterRatio: 1.2,
|
||||
itemExtent: itemSize.height,
|
||||
squeeze: 1.3,
|
||||
onSelectedItemChanged: (i) => valueNotifier.value = values[i],
|
||||
children: values
|
||||
.map((i) => SizedBox.fromSize(
|
||||
size: itemSize,
|
||||
child: Text(
|
||||
'$i',
|
||||
textAlign: widget.textAlign,
|
||||
style: widget.textStyle,
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -78,7 +78,6 @@ class ExpandableFilterRow extends StatelessWidget {
|
|||
height: AvesFilterChip.minChipHeight,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||
itemBuilder: (context, index) {
|
||||
return index < filterList.length ? _buildFilterChip(filterList[index]) : const SizedBox();
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class AvesDialog extends StatelessWidget {
|
||||
final String? title;
|
||||
final ScrollController? scrollController;
|
||||
final ScrollController scrollController;
|
||||
final List<Widget>? scrollableContent;
|
||||
final bool hasScrollBar;
|
||||
final double horizontalContentPadding;
|
||||
|
@ -16,16 +16,17 @@ class AvesDialog extends StatelessWidget {
|
|||
static const double controlCaptionPadding = 16;
|
||||
static const double borderWidth = 1.0;
|
||||
|
||||
const AvesDialog({
|
||||
AvesDialog({
|
||||
super.key,
|
||||
this.title,
|
||||
this.scrollController,
|
||||
ScrollController? scrollController,
|
||||
this.scrollableContent,
|
||||
this.hasScrollBar = true,
|
||||
this.horizontalContentPadding = defaultHorizontalContentPadding,
|
||||
this.content,
|
||||
required this.actions,
|
||||
}) : assert((scrollableContent != null) ^ (content != null));
|
||||
}) : assert((scrollableContent != null) ^ (content != null)),
|
||||
scrollController = scrollController ?? ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -56,10 +57,8 @@ class AvesDialog extends StatelessWidget {
|
|||
}
|
||||
|
||||
if (scrollableContent != null) {
|
||||
final _scrollController = scrollController ?? ScrollController();
|
||||
|
||||
Widget child = ListView(
|
||||
controller: _scrollController,
|
||||
controller: scrollController,
|
||||
shrinkWrap: true,
|
||||
children: scrollableContent!,
|
||||
);
|
||||
|
@ -76,7 +75,14 @@ class AvesDialog extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
child: Scrollbar(
|
||||
controller: _scrollController,
|
||||
controller: scrollController,
|
||||
notificationPredicate: (notification) {
|
||||
// as of Flutter v3.0.1, the `Scrollbar` does not only respond to the nearest `ScrollView`
|
||||
// despite the `defaultScrollNotificationPredicate` checking notification depth,
|
||||
// as the notifications coming from the controller in `ListWheelScrollView` in `WheelSelector` still have a depth of 0.
|
||||
// Cancelling notification bubbling seems ineffective, so we check the metrics type as a workaround.
|
||||
return defaultScrollNotificationPredicate(notification) && notification.metrics is! FixedExtentMetrics;
|
||||
},
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -54,7 +54,6 @@ class _CrumbLineState extends State<CrumbLine> {
|
|||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: _controller,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
itemBuilder: (context, index) {
|
||||
Widget _buildText(String text) => Padding(
|
||||
|
|
Loading…
Reference in a new issue