A head unit is a large screen sitting an arm's length further away than a phone, and Plezy drew phone-sized controls on it: the primary button measured 8.3 mm against the 64 dp a car needs. The whole surface is now scaled - 1.35 by default, adjustable in Appearance - by giving the app a smaller logical viewport and scaling the result back, so text, spacing and touch targets grow together instead of a font size being nudged in isolation. The scale sits above the messenger and the root Scaffold so snackbars and dialogs are scaled too, and insets are divided back into the scaled space so a system bar still reserves its physical size. A scaled surface is also a short one: the setup screen's fixed offsets and the now-playing transport are laid out to survive it, and a mistyped scale in a hand-edited settings file is clamped rather than failing startup.
35 lines
1.7 KiB
Dart
35 lines
1.7 KiB
Dart
import 'package:flutter/widgets.dart';
|
|
|
|
/// Reserves the system bottom inset — Android's navigation bar, iOS's home
|
|
/// indicator — at the end of a scroll view.
|
|
///
|
|
/// Plezy always runs edge-to-edge on Android: `targetSdk` is 36, and Android
|
|
/// 15 enforces edge-to-edge for apps targeting 35+ while Android 16 removes
|
|
/// the opt-out entirely. So `MediaQuery.padding.bottom` is a real overlap on
|
|
/// phones (~48dp with 3-button navigation, less with gesture navigation) and
|
|
/// every full-screen pushed route has to consume it.
|
|
///
|
|
/// The convention is to bake the inset into the scroll *content* rather than
|
|
/// wrapping the scroll view in a [SafeArea]: content keeps painting under the
|
|
/// bar, and only the scroll extent grows so the last row can be scrolled clear
|
|
/// of it. See `media_detail_screen.dart` and `discover_screen.dart` for the
|
|
/// hand-rolled precedents this widget replaces.
|
|
///
|
|
/// Collapses to zero height wherever the bottom padding is already zero, so it
|
|
/// needs no platform branching: desktop and Android TV report no inset, tvOS
|
|
/// has it zeroed by `_FormFactorScale`, and inside `MainScreen`'s tab bodies
|
|
/// Flutter's [Scaffold] has already stripped it because a `bottomNavigationBar`
|
|
/// is present.
|
|
///
|
|
/// Reading the padding from this widget's own [BuildContext] — instead of the
|
|
/// enclosing screen's — keeps it correct below any ancestor that removes
|
|
/// padding, and limits inset-driven rebuilds to the spacer itself.
|
|
class SliverSystemBottomInset extends StatelessWidget {
|
|
const SliverSystemBottomInset({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SliverPadding(padding: .only(bottom: MediaQuery.paddingOf(context).bottom));
|
|
}
|
|
}
|