Skip to content

Commit d45bc4b

Browse files
committed
fix: Theme color support across all components
1 parent a565f69 commit d45bc4b

14 files changed

+473
-255
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# Changelog
22

3+
## [0.1.100]
4+
* **FIX**: Theme color support across all components
5+
* All adaptive components now properly use theme colors when no explicit color provided
6+
* iOS: Uses `CupertinoTheme.of(context).primaryColor`
7+
* Android: Uses `Theme.of(context).colorScheme.primary`
8+
* Material button styles now respect `elevatedButtonTheme`, `textButtonTheme`, etc.
9+
* **FIX**: iOS button width handling in Row/Flex layouts
10+
* iOS 26+ native buttons now properly size to content width
11+
* Removed forced full-width constraint in Swift implementation
12+
* Buttons work correctly with `mainAxisAlignment: MainAxisAlignment.spaceBetween`
13+
* **FIX**: Dark mode text color issues on iOS
14+
* Text now automatically switches to white in dark mode, black in light mode
15+
* Applied to all scaffold implementations (iOS 26+ and legacy)
16+
* **FIX**: Android TextField suffix spacing issue
17+
* Suffix widget now uses `suffixIcon` internally to prevent extra vertical space
18+
* Added `isDense: true` to reduce padding
19+
* **FIX**: Android AppBar back button visibility
20+
* Back button now shows even when title is not provided
21+
* **FIX**: Material context issues in AdaptiveScaffold
22+
* Scaffold now always used on Android to ensure Material context
23+
324
## [0.1.99]
425
* **NEW**: Added `AdaptiveBlurView` widget - iOS 26+ Liquid Glass blur effects
526
* iOS 26+: Native UIVisualEffectView with system blur styles (systemMaterial, systemThick, systemThin, etc.)

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
path: ".."
88
relative: true
99
source: path
10-
version: "0.1.98"
10+
version: "0.1.99"
1111
async:
1212
dependency: transitive
1313
description:

ios/Classes/iOS26ButtonView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class iOS26ButtonView: NSObject, FlutterPlatformView {
122122

123123
// Setup constraints
124124
_view.addSubview(button)
125+
126+
// Button should fill container width
125127
NSLayoutConstraint.activate([
126128
button.leadingAnchor.constraint(equalTo: _view.leadingAnchor),
127129
button.trailingAnchor.constraint(equalTo: _view.trailingAnchor),
@@ -130,6 +132,10 @@ class iOS26ButtonView: NSObject, FlutterPlatformView {
130132
button.heightAnchor.constraint(equalToConstant: getHeightForSize())
131133
])
132134

135+
// Low content hugging - button can expand if container wants
136+
button.setContentHuggingPriority(.defaultLow, for: .horizontal)
137+
button.setContentCompressionResistancePriority(.required, for: .horizontal)
138+
133139
// Add tap action
134140
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
135141

lib/src/widgets/adaptive_app.dart

Lines changed: 112 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -253,88 +253,119 @@ class AdaptiveApp extends StatelessWidget {
253253
final config =
254254
cupertino?.call(context, platform) ?? const CupertinoAppData();
255255

256-
// We need to wrap CupertinoApp in a builder to get system brightness
257-
// CupertinoApp doesn't have themeMode like MaterialApp, so we manually
258-
// detect brightness and apply the appropriate theme
259-
return Builder(
260-
builder: (context) {
261-
// Get system brightness to determine which theme to use
262-
final brightness = MediaQuery.platformBrightnessOf(context);
263-
final isDark =
264-
themeMode == ThemeMode.dark ||
265-
(themeMode != ThemeMode.light && brightness == Brightness.dark);
266-
267-
// Use dark theme if dark mode, otherwise light theme
268-
final effectiveLightTheme =
269-
cupertinoLightTheme ??
270-
const CupertinoThemeData(brightness: Brightness.light);
271-
final effectiveDarkTheme =
272-
cupertinoDarkTheme ??
273-
const CupertinoThemeData(brightness: Brightness.dark);
274-
275-
final theme = isDark ? effectiveDarkTheme : effectiveLightTheme;
276-
277-
if (isRouter) {
278-
return CupertinoApp.router(
279-
key: key,
280-
routerConfig: routerConfig,
281-
routeInformationProvider: routeInformationProvider,
282-
routeInformationParser: routeInformationParser,
283-
routerDelegate: routerDelegate,
284-
backButtonDispatcher: backButtonDispatcher,
285-
builder: builder,
286-
title: title,
287-
onGenerateTitle: onGenerateTitle,
288-
color: config.color,
289-
theme: theme,
290-
locale: locale,
291-
localizationsDelegates: localizationsDelegates,
292-
localeListResolutionCallback: localeListResolutionCallback,
293-
localeResolutionCallback: localeResolutionCallback,
294-
supportedLocales: supportedLocales,
295-
showPerformanceOverlay: config.showPerformanceOverlay,
296-
checkerboardRasterCacheImages: config.checkerboardRasterCacheImages,
297-
checkerboardOffscreenLayers: config.checkerboardOffscreenLayers,
298-
showSemanticsDebugger: config.showSemanticsDebugger,
299-
debugShowCheckedModeBanner: config.debugShowCheckedModeBanner,
300-
shortcuts: config.shortcuts,
301-
actions: config.actions,
302-
restorationScopeId: config.restorationScopeId,
303-
scrollBehavior: config.scrollBehavior,
304-
);
305-
}
306-
307-
return CupertinoApp(
308-
key: key,
309-
navigatorKey: navigatorKey,
310-
home: home,
311-
routes: routes,
312-
initialRoute: initialRoute,
313-
onGenerateRoute: onGenerateRoute,
314-
onGenerateInitialRoutes: onGenerateInitialRoutes,
315-
onUnknownRoute: onUnknownRoute,
316-
navigatorObservers: navigatorObservers,
317-
builder: builder,
318-
title: title,
319-
onGenerateTitle: onGenerateTitle,
320-
color: config.color,
321-
theme: theme,
322-
locale: locale,
323-
localizationsDelegates: localizationsDelegates,
324-
localeListResolutionCallback: localeListResolutionCallback,
325-
localeResolutionCallback: localeResolutionCallback,
326-
supportedLocales: supportedLocales,
327-
showPerformanceOverlay: config.showPerformanceOverlay,
328-
checkerboardRasterCacheImages: config.checkerboardRasterCacheImages,
329-
checkerboardOffscreenLayers: config.checkerboardOffscreenLayers,
330-
showSemanticsDebugger: config.showSemanticsDebugger,
331-
debugShowCheckedModeBanner: config.debugShowCheckedModeBanner,
332-
shortcuts: config.shortcuts,
333-
actions: config.actions,
334-
restorationScopeId: config.restorationScopeId,
335-
scrollBehavior: config.scrollBehavior,
256+
// Prepare light and dark themes
257+
// If Cupertino theme is not provided, try to derive primaryColor from Material theme
258+
final effectiveLightTheme = cupertinoLightTheme ??
259+
CupertinoThemeData(
260+
brightness: Brightness.light,
261+
primaryColor: materialLightTheme?.colorScheme.primary,
336262
);
337-
},
263+
final effectiveDarkTheme = cupertinoDarkTheme ??
264+
CupertinoThemeData(
265+
brightness: Brightness.dark,
266+
primaryColor: materialDarkTheme?.colorScheme.primary,
267+
);
268+
269+
// CupertinoApp doesn't have themeMode like MaterialApp
270+
// We need to wrap the app content in a builder to detect brightness and apply the theme
271+
Widget wrapWithThemeMode(BuildContext context, Widget? child) {
272+
// Determine if we should use dark mode
273+
Brightness effectiveBrightness;
274+
275+
if (themeMode == ThemeMode.dark) {
276+
effectiveBrightness = Brightness.dark;
277+
} else if (themeMode == ThemeMode.light) {
278+
effectiveBrightness = Brightness.light;
279+
} else {
280+
// ThemeMode.system - get from platform
281+
effectiveBrightness = MediaQuery.platformBrightnessOf(context);
282+
}
283+
284+
final isDark = effectiveBrightness == Brightness.dark;
285+
286+
// Apply the appropriate theme and ensure MediaQuery has correct brightness
287+
final theme = isDark ? effectiveDarkTheme : effectiveLightTheme;
288+
289+
return MediaQuery(
290+
data: MediaQuery.of(context).copyWith(
291+
platformBrightness: effectiveBrightness,
292+
),
293+
child: CupertinoTheme(
294+
data: theme,
295+
child: child!,
296+
),
297+
);
298+
}
299+
300+
// Combine user's builder with our theme builder
301+
final effectiveBuilder = builder != null
302+
? (BuildContext context, Widget? child) {
303+
// First apply our theme wrapper
304+
final themedChild = wrapWithThemeMode(context, child);
305+
// Then apply user's builder
306+
return builder!(context, themedChild);
307+
}
308+
: wrapWithThemeMode;
309+
310+
if (isRouter) {
311+
return CupertinoApp.router(
312+
key: key,
313+
routerConfig: routerConfig,
314+
routeInformationProvider: routeInformationProvider,
315+
routeInformationParser: routeInformationParser,
316+
routerDelegate: routerDelegate,
317+
backButtonDispatcher: backButtonDispatcher,
318+
builder: effectiveBuilder,
319+
title: title,
320+
onGenerateTitle: onGenerateTitle,
321+
color: config.color,
322+
theme: effectiveLightTheme, // Default theme (will be overridden by builder)
323+
locale: locale,
324+
localizationsDelegates: localizationsDelegates,
325+
localeListResolutionCallback: localeListResolutionCallback,
326+
localeResolutionCallback: localeResolutionCallback,
327+
supportedLocales: supportedLocales,
328+
showPerformanceOverlay: config.showPerformanceOverlay,
329+
checkerboardRasterCacheImages: config.checkerboardRasterCacheImages,
330+
checkerboardOffscreenLayers: config.checkerboardOffscreenLayers,
331+
showSemanticsDebugger: config.showSemanticsDebugger,
332+
debugShowCheckedModeBanner: config.debugShowCheckedModeBanner,
333+
shortcuts: config.shortcuts,
334+
actions: config.actions,
335+
restorationScopeId: config.restorationScopeId,
336+
scrollBehavior: config.scrollBehavior,
337+
);
338+
}
339+
340+
return CupertinoApp(
341+
key: key,
342+
navigatorKey: navigatorKey,
343+
home: home,
344+
routes: routes,
345+
initialRoute: initialRoute,
346+
onGenerateRoute: onGenerateRoute,
347+
onGenerateInitialRoutes: onGenerateInitialRoutes,
348+
onUnknownRoute: onUnknownRoute,
349+
navigatorObservers: navigatorObservers,
350+
builder: effectiveBuilder,
351+
title: title,
352+
onGenerateTitle: onGenerateTitle,
353+
color: config.color,
354+
theme: effectiveLightTheme, // Default theme (will be overridden by builder)
355+
locale: locale,
356+
localizationsDelegates: localizationsDelegates,
357+
localeListResolutionCallback: localeListResolutionCallback,
358+
localeResolutionCallback: localeResolutionCallback,
359+
supportedLocales: supportedLocales,
360+
showPerformanceOverlay: config.showPerformanceOverlay,
361+
checkerboardRasterCacheImages: config.checkerboardRasterCacheImages,
362+
checkerboardOffscreenLayers: config.checkerboardOffscreenLayers,
363+
showSemanticsDebugger: config.showSemanticsDebugger,
364+
debugShowCheckedModeBanner: config.debugShowCheckedModeBanner,
365+
shortcuts: config.shortcuts,
366+
actions: config.actions,
367+
restorationScopeId: config.restorationScopeId,
368+
scrollBehavior: config.scrollBehavior,
338369
);
339370
}
340371

0 commit comments

Comments
 (0)