theme_extension.1.dart 3.05 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flutter code sample for ThemeExtension

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

@immutable
class MyColors extends ThemeExtension<MyColors> {
  const MyColors({
13 14
    required this.brandColor,
    required this.danger,
15 16
  });

17 18
  final Color? brandColor;
  final Color? danger;
19 20

  @override
21
  MyColors copyWith({Color? brandColor, Color? danger}) {
22
    return MyColors(
23 24
      brandColor: brandColor ?? this.brandColor,
      danger: danger ?? this.danger,
25 26 27 28 29 30 31 32 33
    );
  }

  @override
  MyColors lerp(ThemeExtension<MyColors>? other, double t) {
    if (other is! MyColors) {
      return this;
    }
    return MyColors(
34 35
      brandColor: Color.lerp(brandColor, other.brandColor, t),
      danger: Color.lerp(danger, other.danger, t),
36 37 38 39 40
    );
  }

  // Optional
  @override
41
  String toString() => 'MyColors(brandColor: $brandColor, danger: $danger)';
42 43 44 45 46 47 48 49 50
}

void main() {
  // Slow down time to see lerping.
  timeDilation = 5.0;
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
51
  const MyApp({super.key});
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

  static const String _title = 'Flutter Code Sample';

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

class _MyAppState extends State<MyApp> {
  bool isLightTheme = true;

  void toggleTheme() {
    setState(() => isLightTheme = !isLightTheme);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: MyApp._title,
      theme: ThemeData.light().copyWith(
71
        extensions: <ThemeExtension<dynamic>>[
72
          const MyColors(
73 74
            brandColor: Color(0xFF1E88E5),
            danger: Color(0xFFE53935),
75
          ),
76
        ],
77 78
      ),
      darkTheme: ThemeData.dark().copyWith(
79
        extensions: <ThemeExtension<dynamic>>[
80
          const MyColors(
81 82
            brandColor: Color(0xFF90CAF9),
            danger: Color(0xFFEF9A9A),
83
          ),
84
        ],
85 86 87 88 89 90 91 92 93 94 95 96
      ),
      themeMode: isLightTheme ? ThemeMode.light : ThemeMode.dark,
      home: Home(
        isLightTheme: isLightTheme,
        toggleTheme: toggleTheme,
      ),
    );
  }
}

class Home extends StatelessWidget {
  const Home({
97
    super.key,
98 99
    required this.isLightTheme,
    required this.toggleTheme,
100
  });
101 102 103 104 105 106 107 108 109 110 111 112

  final bool isLightTheme;
  final void Function() toggleTheme;

  @override
  Widget build(BuildContext context) {
    final MyColors myColors = Theme.of(context).extension<MyColors>()!;
    return Material(
      child: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
113
            Container(width: 100, height: 100, color: myColors.brandColor),
114
            const SizedBox(width: 10),
115
            Container(width: 100, height: 100, color: myColors.danger),
116 117 118 119 120 121 122 123 124 125 126
            const SizedBox(width: 50),
            IconButton(
              icon: Icon(isLightTheme ? Icons.nightlight : Icons.wb_sunny),
              onPressed: toggleTheme,
            ),
          ],
        )
      ),
    );
  }
}