MST

星途 面试题库

面试题:Flutter Cupertino组件的主题定制与适配

在一个大型Flutter项目中,需要对Cupertino组件进行主题定制,使其在不同设备(如iPhone不同型号)上都能有最佳视觉效果,同时还要适配暗黑模式。请阐述实现这一需求的整体思路和关键步骤,包括如何自定义Cupertino主题颜色、字体等,以及如何监听系统模式变化并做出相应调整。
15.7万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

整体思路

  1. 主题定制:通过创建自定义的CupertinoThemeData来定制组件的外观,确保在不同iPhone型号上有最佳视觉效果。
  2. 暗黑模式适配:监听系统模式变化,根据变化动态切换CupertinoThemeData

关键步骤

  1. 自定义Cupertino主题颜色、字体
    • 创建一个继承自InheritedWidget的主题类,例如CustomCupertinoTheme
    class CustomCupertinoTheme extends InheritedWidget {
      final CupertinoThemeData data;
      CustomCupertinoTheme({required this.data, required Widget child})
          : super(child: child);
      static CustomCupertinoTheme of(BuildContext context) {
        return context.dependOnInheritedWidgetOfExactType<CustomCupertinoTheme>()!;
      }
      @override
      bool updateShouldNotify(covariant CustomCupertinoTheme oldWidget) {
        return data != oldWidget.data;
      }
    }
    
    • main.dart中,根据不同设备尺寸初始化CupertinoThemeData
    Widget build(BuildContext context) {
      final size = MediaQuery.of(context).size;
      CupertinoThemeData themeData;
      if (size.width < 375) {
        // 例如小屏幕iPhone
        themeData = CupertinoThemeData(
          primaryColor: Colors.blue,
          textTheme: CupertinoTextThemeData(
            textStyle: TextStyle(fontSize: 14),
          ),
        );
      } else {
        // 其他尺寸
        themeData = CupertinoThemeData(
          primaryColor: Colors.deepOrange,
          textTheme: CupertinoTextThemeData(
            textStyle: TextStyle(fontSize: 16),
          ),
        );
      }
      return CustomCupertinoTheme(
        data: themeData,
        child: const MyApp(),
      );
    }
    
  2. 监听系统模式变化并做出相应调整
    • 使用MediaQuery.of(context).platformBrightness获取当前系统亮度模式。
    • 通过WidgetsBindingObserver监听系统模式变化。
    class MyApp extends StatefulWidget {
      const MyApp({Key? key}) : super(key: key);
      @override
      _MyAppState createState() => _MyAppState();
    }
    class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
      Brightness _brightness = MediaQuery.of(context).platformBrightness;
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
      @override
      void didChangePlatformBrightness() {
        setState(() {
          _brightness = MediaQuery.of(context).platformBrightness;
        });
      }
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
      @override
      Widget build(BuildContext context) {
        CupertinoThemeData themeData;
        if (_brightness == Brightness.dark) {
          themeData = CupertinoThemeData(
            primaryColor: Colors.white,
            textTheme: CupertinoTextThemeData(
              textStyle: TextStyle(fontSize: 16, color: Colors.white),
            ),
          );
        } else {
          themeData = CupertinoThemeData(
            primaryColor: Colors.blue,
            textTheme: CupertinoTextThemeData(
              textStyle: TextStyle(fontSize: 16, color: Colors.black),
            ),
          );
        }
        return CustomCupertinoTheme(
          data: themeData,
          child: CupertinoApp(
            home: HomePage(),
          ),
        );
      }
    }
    
  3. 使用自定义主题: 在需要使用主题的地方,通过CustomCupertinoTheme.of(context).data获取主题数据。
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final theme = CustomCupertinoTheme.of(context).data;
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        backgroundColor: theme.primaryColor,
        middle: Text('Home', style: theme.textTheme.navTitleTextStyle),
      ),
      child: Center(
        child: Text('Content', style: theme.textTheme.textStyle),
      ),
    );
  }
}