From ae0d55c00f5e44b1335c6cd6991377a1483da2d9 Mon Sep 17 00:00:00 2001 From: freetlab Date: Sat, 25 Jul 2026 22:27:28 +0200 Subject: [PATCH] fix(android): target API level 35 as required by Google Play Play rejected version code 54 for still targeting 34. From API 35 Android forces edge-to-edge: content is drawn behind the system bars and it is up to each screen to keep clear of them. Seven screens had no SafeArea and their bottom action button would have ended up under the gesture bar, so FondoFarolero gains a respetarBarras flag that insets the content while the background still paints full bleed. The seventeen screens that already handle it are untouched. The navigation bar colour is ignored under edge-to-edge, so its icons are now forced light to stay visible over the dark background. Verified on the merged manifest: targetSdkVersion 35, and the release bundle builds. The visual result has not been checked on a device. --- android/app/build.gradle.kts | 5 ++++- lib/main.dart | 4 ++++ lib/pantallas/pantalla_ajustes.dart | 1 + lib/pantallas/pantalla_crear_partida.dart | 1 + lib/pantallas/pantalla_gestor_host.dart | 1 + lib/pantallas/pantalla_notas.dart | 1 + lib/pantallas/pantalla_notas_online.dart | 1 + lib/pantallas/pantalla_resultado.dart | 1 + lib/pantallas/pantalla_votacion_cliente.dart | 1 + lib/tema/componentes_farolero.dart | 14 +++++++++++++- 10 files changed, 28 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index c688138..0dd9198 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -30,7 +30,10 @@ android { defaultConfig { applicationId = "es.freetimelab.farolero.game" minSdk = 24 - targetSdk = 34 + // Google Play exige 35 como mínimo. A partir de aquí Android impone el + // dibujado de borde a borde: el contenido va detrás de las barras del + // sistema y son las pantallas las que deben apartarse. + targetSdk = 35 versionCode = flutter.versionCode versionName = flutter.versionName } diff --git a/lib/main.dart b/lib/main.dart index afbec72..affb250 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,6 +20,10 @@ void main() { statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.light, systemNavigationBarColor: TemaApp.colorFondo, + // Con el dibujado de borde a borde de Android 15 el color de la barra de + // navegación se ignora y queda transparente sobre un fondo oscuro, así + // que sus iconos tienen que ser claros para verse. + systemNavigationBarIconBrightness: Brightness.light, ), ); runApp(const FaroleroApp()); diff --git a/lib/pantallas/pantalla_ajustes.dart b/lib/pantallas/pantalla_ajustes.dart index 2294a34..0035f77 100644 --- a/lib/pantallas/pantalla_ajustes.dart +++ b/lib/pantallas/pantalla_ajustes.dart @@ -28,6 +28,7 @@ class _PantallaAjustesState extends State { appBar: AppBar(title: Text(l10n.settingsTitle)), body: FondoFarolero( intenso: true, + respetarBarras: true, child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( diff --git a/lib/pantallas/pantalla_crear_partida.dart b/lib/pantallas/pantalla_crear_partida.dart index cf7a32f..8274415 100644 --- a/lib/pantallas/pantalla_crear_partida.dart +++ b/lib/pantallas/pantalla_crear_partida.dart @@ -345,6 +345,7 @@ class _PantallaCrearPartidaState extends State { appBar: AppBar(title: Text(l10n.createGame)), body: FondoFarolero( intenso: true, + respetarBarras: true, child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(18, 18, 18, 28), child: Column( diff --git a/lib/pantallas/pantalla_gestor_host.dart b/lib/pantallas/pantalla_gestor_host.dart index fa75e8d..95da5e9 100644 --- a/lib/pantallas/pantalla_gestor_host.dart +++ b/lib/pantallas/pantalla_gestor_host.dart @@ -309,6 +309,7 @@ class _PantallaGestorHostState extends State { ), body: FondoFarolero( intenso: true, + respetarBarras: true, child: Padding( padding: const EdgeInsets.all(16), child: Column( diff --git a/lib/pantallas/pantalla_notas.dart b/lib/pantallas/pantalla_notas.dart index 774491e..e1d31bc 100644 --- a/lib/pantallas/pantalla_notas.dart +++ b/lib/pantallas/pantalla_notas.dart @@ -89,6 +89,7 @@ class _PantallaNotasState extends State { ), body: FondoFarolero( intenso: true, + respetarBarras: true, child: _jugadorSeleccionadoId == null ? _construirSelectorJugador(partida) : _construirNotas(partida), diff --git a/lib/pantallas/pantalla_notas_online.dart b/lib/pantallas/pantalla_notas_online.dart index 9b9e8df..b083f73 100644 --- a/lib/pantallas/pantalla_notas_online.dart +++ b/lib/pantallas/pantalla_notas_online.dart @@ -118,6 +118,7 @@ class _PantallaNotasOnlineState extends State { ), body: FondoFarolero( intenso: true, + respetarBarras: true, child: _autor == null ? _buildSelector(context) : _buildNotas(context), ), ), diff --git a/lib/pantallas/pantalla_resultado.dart b/lib/pantallas/pantalla_resultado.dart index f384032..eb63f9a 100644 --- a/lib/pantallas/pantalla_resultado.dart +++ b/lib/pantallas/pantalla_resultado.dart @@ -66,6 +66,7 @@ class _PantallaResultadoState extends State ), body: FondoFarolero( intenso: true, + respetarBarras: true, child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(32), diff --git a/lib/pantallas/pantalla_votacion_cliente.dart b/lib/pantallas/pantalla_votacion_cliente.dart index 7e37794..7634b32 100644 --- a/lib/pantallas/pantalla_votacion_cliente.dart +++ b/lib/pantallas/pantalla_votacion_cliente.dart @@ -102,6 +102,7 @@ class _PantallaVotacionClienteState extends State { ), body: FondoFarolero( intenso: true, + respetarBarras: true, child: Padding( padding: const EdgeInsets.all(16), child: Column( diff --git a/lib/tema/componentes_farolero.dart b/lib/tema/componentes_farolero.dart index 8699271..599435b 100644 --- a/lib/tema/componentes_farolero.dart +++ b/lib/tema/componentes_farolero.dart @@ -139,10 +139,20 @@ class FondoFarolero extends StatelessWidget { final Widget child; final bool intenso; + /// Aparta el contenido de las barras del sistema. + /// + /// A partir de targetSdk 35 la app dibuja de borde a borde, así que sin esto + /// lo que quede abajo —normalmente el botón de acción— acaba debajo de la + /// barra de gestos. El fondo se sigue pintando entero; solo se aparta el + /// contenido. Las pantallas que ya envuelven su contenido en SafeArea no + /// necesitan activarlo. + final bool respetarBarras; + const FondoFarolero({ super.key, required this.child, this.intenso = false, + this.respetarBarras = false, }); @override @@ -163,7 +173,9 @@ class FondoFarolero extends StatelessWidget { ), ), ), - Positioned.fill(child: child), + Positioned.fill( + child: respetarBarras ? SafeArea(child: child) : child, + ), ], ), );