Тема флаттера не применяется к новому экрану

#flutter #dart #themes #navigator

Вопрос:

Ниже приведен простой экран с тремя кнопками с разными цветными темами, что я хочу, чтобы при нажатии любой кнопки на экране деталей использовалась эта тема.

кроме того, я не знаю, как изменить тему MaterialAppWidget, потому что она используется в других местах, просто этот экран сведений должен быть тематическим в соответствии с тем, какая кнопка была открыта.

 import 'package:flutter/material.dart';

main() => runApp(const App());

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: const HomeScreen(),
        theme: ThemeData(
          primaryColor: Colors.orange,
          colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.orange),
        ),
      );
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Wrap(
          spacing: 20,
          direction: Axis.vertical,
          children: const [
            ThemedButton(
              materialColor: Colors.red,
            ),
            ThemedButton(
              materialColor: Colors.green,
            ),
            ThemedButton(
              materialColor: Colors.brown,
            ),
          ],
        ),
      ),
    );
  }
}

class ThemedButton extends StatelessWidget {
  final MaterialColor materialColor;

  const ThemedButton({
    Key? key,
    required this.materialColor,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: Theme.of(context).copyWith(
        primaryColor: materialColor,
        colorScheme: ColorScheme.fromSwatch(primarySwatch: materialColor),
      ),
      child: ElevatedButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => const DetailScreen(),
            ),
          );
        },
        child: const Text('Go to Detail Screen'),
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  const DetailScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
    );
  }
}
 

Ответ №1:

Сработало бы что-то подобное для вас?

 class ThemedButton extends StatelessWidget {
  
  final MaterialColor materialColor;
  const ThemedButton({Key? key, required this.materialColor}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: ElevatedButton.styleFrom(
        primary: materialColor
      ),
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => Theme(
              data: Theme.of(context).copyWith(
                primaryColor: materialColor,
                colorScheme: ColorScheme.fromSwatch(primarySwatch: materialColor),
              ),
              child: const DetailScreen()
            )
          ),
        );
      },
      child: const Text('Go to Detail Screen'),
    );
  }
}
 

Я оборачиваю кнопку с повышением в виджет конструктора, чтобы использовать новую тему BuildContext для передачи.

Комментарии:

1. он работает так, как я хочу, но можете ли вы объяснить, почему мне нужно использовать конструктор, потому что, как я читал, этот конструктор используется, когда у нас нет контекста, который мы хотим использовать, но у меня уже есть тематический контекст, ThemedButton а также почему мне нужно возобновить Theme , если у родительского виджета уже применена тема

2. Я понял, что есть немного лучший способ сделать это, поэтому отредактировал свой ответ! Насколько я понимаю, переход на новый экран приведет к возвращению к вашей глобальной теме в приложении Material. У вас уже есть правильная идея, вам просто нужно было завернуть виджет темы в функцию конструктора MaterialPageRoute