Ontwikkel een responsieve Flutter UI met dynamische thema's en animaties
description
Met deze prompt krijg ik een concreet voorbeeld van een geavanceerde Flutter UI die zich aanpast aan verschillende apparaten en gebruikersvoorkeuren. Het helpt me om visueel aantrekkelijke apps te maken met dynamische themawisselingen en animaties zonder zelf complexe code te moeten schrijven, wat tijd bespaart en de kwaliteit verhoogt.
prompt
Help me bij het ontwikkelen van een Flutter UI die responsief is en dynamische themawisselingen ondersteunt. Gebruik als basis de volgen ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder vind je een voorbeeld van een Flutter UI die responsief is en dynamisch thema wisselt met een vloeiende animatie. We gebruiken een `ChangeNotifier` voor het beheer van het thema en een `AnimatedSwitcher` of `AnimatedTheme` voor de animatie bij het wisselen.
### Stap 1: Maak een `ThemeNotifier` om het thema te beheren
```dart
import 'package:flutter/material.dart';
class ThemeNotifier extends ChangeNotifier {
bool isDarkMode = false;
void toggleTheme() {
isDarkMode = !isDarkMode;
notifyListeners();
}
ThemeData get currentTheme => isDarkMode ? ThemeData.dark() : ThemeData.light();
}
```
### Stap 2: Wrap je app in een `ChangeNotifierProvider` en gebruik `AnimatedTheme`
```dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => ThemeNotifier(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final themeNotifier = Provider.of<ThemeNotifier>(context);
return MaterialApp(
title: 'Responsieve Themawissel',
theme: themeNotifier.currentTheme,
home: HomeScreen(),
);
}
}
```
### Stap 3: De `HomeScreen` met knop en animatie
```dart
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final themeNotifier = Provider.of<ThemeNotifier>(context);
return Scaffold(
appBar: AppBar(
title: Text('Thema wisselen'),
),
body: Center(
child: AnimatedSwitcher(
duration: Duration(milliseconds: 500),
switchInCurve: Curves.easeInOut,
child: Column(
key: ValueKey<bool>(themeNotifier.isDarkMode),
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Huidig thema: ${themeNotifier.isDarkMode ? 'Donker' : 'Licht'}',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
themeNotifier.toggleTheme();
},
child: Text('Thema wisselen'),
),
],
),
),
),
);
}
}
```
### Extra tips voor responsiviteit:
- Gebruik `MediaQuery.of(context).size` om layout aan te passen.
- Maak gebruik van `Flexible`, `Expanded` en `LayoutBuilder` voor dynamische layouts.
- Overweeg ook om schaalbare fonts te gebruiken (`MediaQuery.textScaleFactor`) voor betere leesbaarheid op verschillende schermen.
---
### Samenvatting
Dit voorbeeld gebruikt `ChangeNotifier` voor het thema, `Provider` voor state management, en `AnimatedSwitcher` voor vloeiende animaties bij het wisselen van thema. Het resultaat is een responsieve app die soepel schakelt tussen licht en donker thema met een mooie overgang.
provider: deepseek
model: deepseek-chat
Hier is een complete implementatie voor een responsieve Flutter UI met dynamische themawisselingen:
## 1. Pubspec.yaml dependencies
```yaml
dependencies:
flutter:
sdk: flutter
provider: ^6.0.5
```
## 2. Thema Service (Theme Service)
```dart
import 'package:flutter/material.dart';
class ThemeService with ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
ThemeMode get themeMode => _themeMode;
bool get isDarkMode => _themeMode == ThemeMode.dark;
void toggleTheme() {
_themeMode = _themeMode == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
notifyListeners();
}
}
```
## 3. Hoofd Applicatie
```dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'theme_service.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => ThemeService(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final themeService = Provider.of<ThemeService>(context);
return MaterialApp(
title: 'Responsieve Thema App',
theme: ThemeData.light().copyWith(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
useMaterial3: true,
),
darkTheme: ThemeData.dark().copyWith(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
useMaterial3: true,
),
themeMode: themeService.themeMode,
home: const HomeScreen(),
);
}
}
```
## 4. Home Screen met Animatie
```dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'theme_service.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
late Animation<Color?> _colorAnimation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
_scaleAnimation = Tween<double>(begin: 1.0, end: 0.8).animate(
CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
),
);
_colorAnimation = ColorTween(
begin: Colors.blue,
end: Colors.orange,
).animate(_animationController);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _toggleThemeWithAnimation() {
_animationController.forward().then((_) {
final themeService = Provider.of<ThemeService>(context, listen: false);
themeService.toggleTheme();
_animationController.reverse();
});
}
@override
Widget build(BuildContext context) {
final themeService = Provider.of<ThemeService>(context);
final isDarkMode = themeService.isDarkMode;
return Scaffold(
appBar: AppBar(
title: const Text('Responsieve Thema App'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Animated content
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform.scale(
scale: _scaleAnimation.value,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: _colorAnimation.value,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Icon(
isDarkMode ? Icons.nightlight : Icons.wb_sunny,
size: 64,
color: Colors.white,
),
),
);
},
),
const SizedBox(height: 40),
// Responsive button
LayoutBuilder(
builder: (context, constraints) {
final buttonWidth = constraints.maxWidth > 600
? 300.0
: double.infinity;
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: buttonWidth,
child: ElevatedButton(
onPressed: _toggleThemeWithAnimation,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 24,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: Text(
isDarkMode ? 'Licht Thema' : 'Donker Thema',
key: ValueKey<bool>(isDarkMode),
style: const TextStyle(fontSize: 18),
),
),
),
);
},
),
const SizedBox(height: 20),
// Additional responsive content
ResponsiveWidget(
largeScreen: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(15),
),
child: const Text(
'Dit is extra content voor grote schermen',
textAlign: TextAlign.center,
),
),
smallScreen: const SizedBox.shrink(),
),
],
),
),
);
}
}
```
## 5. Responsive Widget
```dart
class ResponsiveWidget extends StatelessWidget {
final Widget largeScreen;
final Widget mediumScreen;
final Widget smallScreen;
const ResponsiveWidget({
super.key,
required this.largeScreen,
required this.smallScreen,
this.mediumScreen = const SizedBox.shrink(),
});
static bool isSmallScreen(BuildContext context) {
return MediaQuery.of(context).size.width < 768;
}
static bool isMediumScreen(BuildContext context) {
return MediaQuery.of(context).size.width >= 768 &&
MediaQuery.of(context).size.width < 1200;
}
static bool isLargeScreen(BuildContext context) {
return MediaQuery.of(context).size.width >= 1200;
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 1200) {
return largeScreen;
} else if (constraints.maxWidth >= 768) {
return mediumScreen;
} else {
return smallScreen;
}
},
);
}
}
```
## Belangrijke kenmerken:
1. **Responsiviteit**: Gebruik van `LayoutBuilder` en `MediaQuery` voor verschillende schermgroottes
2. **Vloeiende animaties**: `AnimationController` met `CurvedAnimation` en `ColorTween`
3. **Dynamische thema's**: Provider pattern voor state management
4. **AnimatedSwitcher**: Voor soepele tekstovergangen
5. **Material 3**: Moderne design principes met `useMaterial3: true`
Deze implementatie zorgt voor een professionele, responsieve UI met vloeiende thema-overgangen en animaties!