2026-10-18 21:46:55 +02:00
|
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
|
import 'package:material_ui/material_ui.dart';
|
|
|
|
|
|
|
|
|
|
/// A floating action button that slides away while the person scrolls down,
|
|
|
|
|
/// reading onwards, and comes back as soon as they scroll up. [builder]
|
|
|
|
|
/// builds the screen around the button it is handed (as its scaffold's
|
|
|
|
|
/// floating action button); the scrolling in that screen moves it.
|
|
|
|
|
///
|
|
|
|
|
/// While hidden, the button can't be tapped through its fading ghost. A list
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
/// short enough not to scroll keeps it in view: it covers nothing there, and
|
|
|
|
|
/// so does [pinned].
|
2026-10-18 21:46:55 +02:00
|
|
|
class const ScrollHidingFab({
|
|
|
|
|
/// The button; none when null, as in windows that put the action in the
|
|
|
|
|
/// app bar instead.
|
|
|
|
|
required final Widget? fab,
|
|
|
|
|
|
|
|
|
|
/// The screen, given the button to place.
|
|
|
|
|
required final Widget Function(BuildContext context, Widget? fab) builder,
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
|
|
|
|
|
/// Whether the button stays whatever the scrolling, as while it is a field
|
|
|
|
|
/// being written in, which mustn't slide away under the person's typing.
|
|
|
|
|
final bool pinned = false,
|
2026-10-18 21:46:55 +02:00
|
|
|
super.key,
|
|
|
|
|
}) extends StatefulWidget {
|
|
|
|
|
@override
|
|
|
|
|
State<ScrollHidingFab> createState() => _ScrollHidingFabState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _ScrollHidingFabState() extends State<ScrollHidingFab> {
|
|
|
|
|
var _visible = true;
|
|
|
|
|
|
|
|
|
|
bool _onScroll(UserScrollNotification notification) {
|
|
|
|
|
// Only the screen's own vertical scrolling: a sideways swipe between
|
|
|
|
|
// tabs moves nothing.
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
if (notification.metrics.axis != Axis.vertical || widget.pinned) {
|
2026-10-18 21:46:55 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
final visible = switch (notification.direction) {
|
|
|
|
|
// A list that doesn't scroll covers nothing behind the button, and an
|
|
|
|
|
// overscroll bounce there mustn't hide it.
|
|
|
|
|
ScrollDirection.reverse => notification.metrics.maxScrollExtent <= 0,
|
|
|
|
|
ScrollDirection.forward => true,
|
|
|
|
|
ScrollDirection.idle => _visible,
|
|
|
|
|
};
|
|
|
|
|
if (visible != _visible) {
|
|
|
|
|
setState(() => _visible = visible);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
final fab = widget.fab;
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
final visible = _visible || widget.pinned;
|
2026-10-18 21:46:55 +02:00
|
|
|
return NotificationListener<UserScrollNotification>(
|
|
|
|
|
onNotification: _onScroll,
|
|
|
|
|
child: widget.builder(
|
|
|
|
|
context,
|
|
|
|
|
fab == null
|
|
|
|
|
? null
|
|
|
|
|
: AnimatedSlide(
|
|
|
|
|
duration: const Duration(milliseconds: 200),
|
|
|
|
|
curve: Curves.easeOut,
|
|
|
|
|
// Twice its own height clears the window's edge whatever
|
|
|
|
|
// the button's size.
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
offset: visible ? Offset.zero : const Offset(0, 2),
|
2026-10-18 21:46:55 +02:00
|
|
|
child: AnimatedOpacity(
|
|
|
|
|
duration: const Duration(milliseconds: 200),
|
fix(learn,ui): the open assistant field holds still: no flicker, no sliding away, no resizing under the keyboard (ADR 0021, D69)
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-04 21:15:48 +01:00
|
|
|
opacity: visible ? 1 : 0,
|
|
|
|
|
child: IgnorePointer(ignoring: !visible, child: fab),
|
2026-10-18 21:46:55 +02:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|