0
0
Fluttermobile~20 mins

InheritedWidget concept in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Theme Color Changer
A simple app screen that uses InheritedWidget to share a theme color across widgets. The user can tap a button to change the color, and all widgets using the shared color update automatically.
Target UI
┌─────────────────────────────┐
│       Theme Color Changer    │
├─────────────────────────────┤
│                             │
│   Current Color: [ColorBox] │
│                             │
│   [Change Color Button]      │
│                             │
│   Text using theme color     │
│                             │
└─────────────────────────────┘
Create a custom InheritedWidget to hold a Color value.
Provide a way to update the color from a button tap.
Widgets that read the color should rebuild automatically when it changes.
Display a colored box showing the current color.
Display a button labeled 'Change Color' that cycles through a list of colors.
Starter Code
Flutter
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Color _color = Colors.blue;

  void _changeColor() {
    // TODO: Implement color change logic
  }

  @override
  Widget build(BuildContext context) {
    return ColorProvider(
      color: _color,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Theme Color Changer')),
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                // TODO: Add ColorBox widget here
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: _changeColor,
                  child: const Text('Change Color'),
                ),
                const SizedBox(height: 20),
                // TODO: Add Text widget that uses the color from ColorProvider
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class ColorProvider extends InheritedWidget {
  final Color color;

  const ColorProvider({required this.color, required super.child, super.key});

  static ColorProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ColorProvider>();
  }

  @override
  bool updateShouldNotify(ColorProvider oldWidget) {
    return oldWidget.color != color;
  }
}
Task 1
Task 2
Task 3
Solution
Flutter
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final List<Color> _colors = [Colors.blue, Colors.red, Colors.green, Colors.orange];
  int _currentIndex = 0;

  void _changeColor() {
    setState(() {
      _currentIndex = (_currentIndex + 1) % _colors.length;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ColorProvider(
      color: _colors[_currentIndex],
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Theme Color Changer')),
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                ColorBox(),
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: _changeColor,
                  child: const Text('Change Color'),
                ),
                const SizedBox(height: 20),
                ThemedText(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class ColorProvider extends InheritedWidget {
  final Color color;

  const ColorProvider({required this.color, required super.child, super.key});

  static ColorProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ColorProvider>();
  }

  @override
  bool updateShouldNotify(ColorProvider oldWidget) {
    return oldWidget.color != color;
  }
}

class ColorBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final color = ColorProvider.of(context)?.color ?? Colors.black;
    return Container(
      width: 100,
      height: 100,
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: Colors.black26),
      ),
    );
  }
}

class ThemedText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final color = ColorProvider.of(context)?.color ?? Colors.black;
    return Text(
      'This text uses the theme color',
      style: TextStyle(fontSize: 18, color: color),
    );
  }
}

We created a ColorProvider class that extends InheritedWidget. It holds a Color value and notifies dependents when the color changes.

The MyApp stateful widget manages the current color index and cycles through a list of colors when the button is pressed. It rebuilds the ColorProvider with the new color.

The ColorBox and ThemedText widgets read the current color from ColorProvider.of(context). Because they depend on the inherited widget, they rebuild automatically when the color changes.

This shows how InheritedWidget shares data down the widget tree and triggers rebuilds efficiently.

Final Result
Completed Screen
┌─────────────────────────────┐
│       Theme Color Changer    │
├─────────────────────────────┤
│                             │
│   Current Color: [████████] │
│                             │
│   [Change Color Button]      │
│                             │
│   This text uses the theme   │
│   color                     │
│                             │
└─────────────────────────────┘
User taps 'Change Color' button.
The colored box changes to the next color in the list.
The text color updates to match the new theme color.
Stretch Goal
Add a reset button that sets the color back to the first color in the list.
💡 Hint
Add another ElevatedButton labeled 'Reset' that calls setState to set _currentIndex to 0.