← Назад к вопросам
Как организуешь код стайл в приложении?
1.2 Junior🔥 191 комментариев
#Архитектура Flutter#ООП и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ
Организация кода стайла в Flutter приложении — это критическая часть создания удобного и единообразного интерфейса. Существует несколько стратегий, каждая с плюсами и минусами.
Основная проблема: дублирование стилей
// Плохо — стили дублируются везде
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [BoxShadow(blurRadius: 8)],
),
child: Text(
'Button',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
)
Способ 1: Centralised Theme (встроенный ThemeData)
Самый стандартный подход, используется в Material Design:
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
textTheme: TextTheme(
headlineLarge: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black,
),
bodyMedium: TextStyle(
fontSize: 14,
color: Colors.grey[700],
),
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
),
),
)
// Использование в коде
Text('Hello', style: Theme.of(context).textTheme.headlineLarge)
TextField(
decoration: InputDecoration(hintText: 'Enter text'),
)
Способ 2: Custom Constants класс
Для более гибкого управления:
class AppStyles {
// Colors
static const primaryColor = Color(0xFF2196F3);
static const secondaryColor = Color(0xFF1E88E5);
static const backgroundColor = Color(0xFFF5F5F5);
static const errorColor = Color(0xFFD32F2F);
// Text Styles
static const headingStyle = TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFF212121),
);
static const bodyStyle = TextStyle(
fontSize: 14,
color: Color(0xFF616161),
);
// Padding & Margin
static const smallPadding = EdgeInsets.all(8);
static const mediumPadding = EdgeInsets.all(16);
static const largePadding = EdgeInsets.all(24);
// Border Radius
static const smallRadius = BorderRadius.all(Radius.circular(4));
static const mediumRadius = BorderRadius.all(Radius.circular(8));
static const largeRadius = BorderRadius.all(Radius.circular(16));
// Box Decorations
static final cardDecoration = BoxDecoration(
color: Colors.white,
borderRadius: mediumRadius,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: Offset(0, 2),
),
],
);
}
// Использование
Container(
padding: AppStyles.mediumPadding,
decoration: AppStyles.cardDecoration,
child: Text('Card', style: AppStyles.headingStyle),
)
Способ 3: Полнофункциональный Theme класс
Для сложных приложений с множеством тем:
class AppTheme {
static ThemeData lightTheme(BuildContext context) {
return ThemeData(
useMaterial3: true,
brightness: Brightness.light,
colorScheme: ColorScheme.light(
primary: Colors.blue,
secondary: Colors.teal,
surface: Colors.white,
error: Colors.red,
),
textTheme: _buildTextTheme(),
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
),
);
}
static ThemeData darkTheme(BuildContext context) {
return ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorScheme: ColorScheme.dark(
primary: Colors.blue[300],
secondary: Colors.teal[300],
surface: Colors.grey[900],
error: Colors.red[400],
),
textTheme: _buildTextTheme(),
);
}
static TextTheme _buildTextTheme() {
return TextTheme(
displayLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
headlineLarge: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
bodyLarge: TextStyle(fontSize: 16),
bodyMedium: TextStyle(fontSize: 14),
labelSmall: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
);
}
}
// Использование
MaterialApp(
theme: AppTheme.lightTheme(context),
darkTheme: AppTheme.darkTheme(context),
themeMode: ThemeMode.system,
)
Способ 4: Komponenty-based approach
Использование переиспользуемых компонентов:
class StyledButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
final ButtonStyle style;
const StyledButton({
required this.label,
required this.onPressed,
this.style = ButtonStyle.primary,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final colors = _getColorScheme(style);
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: colors.bgColor,
foregroundColor: colors.textColor,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: onPressed,
child: Text(label, style: theme.textTheme.labelLarge),
);
}
_ColorScheme _getColorScheme(ButtonStyle style) {
return switch (style) {
ButtonStyle.primary => _ColorScheme(
bgColor: Colors.blue,
textColor: Colors.white,
),
ButtonStyle.secondary => _ColorScheme(
bgColor: Colors.grey[200],
textColor: Colors.black,
),
ButtonStyle.danger => _ColorScheme(
bgColor: Colors.red,
textColor: Colors.white,
),
};
}
}
enum ButtonStyle { primary, secondary, danger }
class _ColorScheme {
final Color bgColor;
final Color textColor;
_ColorScheme({required this.bgColor, required this.textColor});
}
// Использование
StyledButton(
label: 'Click me',
onPressed: () {},
style: ButtonStyle.primary,
)
Способ 5: Использование Riverpod для темы
final themeModeProvider = StateProvider<ThemeMode>((ref) {
return ThemeMode.system;
});
final appThemeProvider = Provider<ThemeData>((ref) {
final themeMode = ref.watch(themeModeProvider);
return themeMode == ThemeMode.dark
? AppTheme.darkTheme()
: AppTheme.lightTheme();
});
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final appTheme = ref.watch(appThemeProvider);
final themeMode = ref.watch(themeModeProvider);
return MaterialApp(
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
themeMode: themeMode,
);
}
}
Лучшие практики
- Используйте цветовые переменные вместо хардкода
- Централизуйте стили в одном месте
- Создавайте переиспользуемые компоненты вместо дублирования
- Документируйте стили с примерами
- Тестируйте темы — светлую и тёмную
- Используйте Material Design 3 где возможно
- Избегайте глубокой вложенности в стилях
Правильная организация кода стайла улучшает читаемость, упрощает поддержку и ускоряет разработку.