Fix mode-button gradient to fade via alpha instead of a color mix

Interpolating RGB between activeTint and inactiveColor produced a
visibly muddy intermediate color that read as a hard cut inside the
button rather than a soft fade. Switched to a pure alpha gradient of
inactiveColor itself (0.0 -> 0.85): at alpha 0 it exactly matches the
header container's own tint sitting behind it, so the seam disappears
entirely, and the color only ever mixes with itself. Also pushed the
stop from 30% to 45% of the button's width for more breathing room
before the solid fill starts.
This commit is contained in:
Constantin Leue
2026-08-07 22:27:49 +02:00
parent da4797131c
commit 4485c1644e
+20 -18
View File
@@ -46,8 +46,7 @@ class TopModeBar extends ConsumerWidget {
/// Leistenkante (HTML-Demonstrator: `#topBarWrap{padding:5px 10px}`) - der
/// inaktive Button verzichtet bewusst darauf, siehe Klassendoku oben.
static const _outerPaddingH = 10.0;
// Halbiert (Nutzerwunsch: vertikaler Innenabstand noch zu gross) - der
// aktive Moduswechsel-Button und der mittlere Inhalt (Wind-Pille/
// Der aktive Moduswechsel-Button und der mittlere Inhalt (Wind-Pille/
// Suchleiste/Flugmodus) bleiben oben/unten um diesen Betrag von der
// Leistenkante eingerueckt, siehe Klassendoku.
static const _outerPaddingV = 5.0;
@@ -113,7 +112,6 @@ class TopModeBar extends ConsumerWidget {
_ModeButton(
label: 'Plan',
isActive: !isFly,
activeTint: activeTint,
inactiveColor: DmcColors.planModeColor,
isLeftButton: true,
onTap: () => context.read<AppModeCubit>().toPlan(),
@@ -132,7 +130,6 @@ class TopModeBar extends ConsumerWidget {
_ModeButton(
label: 'Fly',
isActive: isFly,
activeTint: activeTint,
inactiveColor: DmcColors.flyModeColor,
isLeftButton: false,
onTap: () {
@@ -161,7 +158,6 @@ class _ModeButton extends StatelessWidget {
const _ModeButton({
required this.label,
required this.isActive,
required this.activeTint,
required this.inactiveColor,
required this.isLeftButton,
required this.onTap,
@@ -169,11 +165,6 @@ class _ModeButton extends StatelessWidget {
final String label;
final bool isActive;
/// Aktuelle Kopfleisten-Toenung (TopModeBar.activeTint) - dient nur als
/// Startfarbe des Farbverlaufs im inaktiven Zustand (siehe unten), der
/// aktive Button hat ohnehin keinen eigenen Hintergrund.
final Color activeTint;
final Color inactiveColor;
/// true = Plan-Button (linkes Ende der Leiste), false = Fly-Button
@@ -207,20 +198,31 @@ class _ModeButton extends StatelessWidget {
decoration: isActive
? null
: BoxDecoration(
// Kurzer Farbverlauf von der Kopfleisten-eigenen Toenung zur
// vollen Button-Farbe statt einer harten Kante an der
// Nahtstelle zum mittleren Inhalt (Nutzerwunsch: "linearer
// kurzer Farbverlauf zwischen button und rest header") - nur
// die ersten 30% der Breite blenden ein, der Rest bleibt
// solide, damit der Text weiterhin auf vollem Kontrast sitzt.
// Farbverlauf von der Kopfleisten-eigenen Toenung zur vollen
// Button-Farbe statt einer harten Kante an der Nahtstelle zum
// mittleren Inhalt (Nutzerwunsch: "linearer kurzer
// Farbverlauf zwischen button und rest header"). Reiner
// Alpha-Verlauf DERSELBEN inactiveColor (0.0 -> 0.85) statt
// einer RGB-Ueberblendung zwischen zwei verschiedenen Farben -
// Letzteres erzeugte einen sichtbar "verschmutzten"
// Zwischenton, der wie eine harte Kante mitten im Button
// wirkte, statt wie ein weiches Einblenden (Nutzer-Feedback:
// "der Verlauf schneidet in den Knopf rein"). Bei Alpha 0
// liegt exakt die Toenung des umgebenden TopModeBar-
// Containers darunter (dieselbe activeTint-Farbe, derselbe
// Alpha-Wert 0.55, siehe dortige Decoration), der Uebergang
// an der Nahtstelle ist dadurch von selbst nahtlos. Stop bei
// 45% statt vorher 30% laesst mehr Abstand, bevor die
// Volltonflaeche des eigentlichen Knopfes beginnt (ebenfalls
// Nutzer-Feedback).
gradient: LinearGradient(
begin: isLeftButton ? Alignment.centerRight : Alignment.centerLeft,
end: isLeftButton ? Alignment.centerLeft : Alignment.centerRight,
colors: [
activeTint.withValues(alpha: 0.55),
inactiveColor.withValues(alpha: 0.0),
inactiveColor.withValues(alpha: 0.85),
],
stops: const [0.0, 0.3],
stops: const [0.0, 0.45],
),
),
child: Text(