| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import 'dart:math' as math;
- import 'package:flutter/material.dart';
- import 'package:flutter_lucide/flutter_lucide.dart';
- import 'app_sidebar.dart';
- import '../../utils/constants.dart';
- import '../../theme/app_colors.dart';
- /// 应用布局组件
- class AppLayout extends StatelessWidget {
- final Widget child;
- final bool showSidebar;
- final double? maxContentWidth;
- final EdgeInsets? contentPadding;
- final String? appBarTitle;
- const AppLayout({
- Key? key,
- required this.child,
- this.showSidebar = true,
- this.maxContentWidth,
- this.contentPadding,
- this.appBarTitle,
- }) : super(key: key);
- @override
- Widget build(BuildContext context) {
- final screenWidth = MediaQuery.of(context).size.width;
- final isMobile = screenWidth < AppConstants.mobileBreakpoint;
- final isTablet = screenWidth >= AppConstants.mobileBreakpoint &&
- screenWidth < AppConstants.tabletBreakpoint;
- final isLargeDesktop = screenWidth >= AppConstants.desktopBreakpoint;
- // 根据屏幕尺寸确定最大宽度
- final effectiveMaxWidth = maxContentWidth ??
- (isMobile
- ? double.infinity
- : isTablet
- ? 1320.0
- : isLargeDesktop
- ? 1760.0
- : 1520.0);
- // 根据屏幕尺寸确定内边距
- final effectivePadding = contentPadding ??
- EdgeInsets.symmetric(
- horizontal: isMobile
- ? 16
- : isTablet
- ? 32
- : isLargeDesktop
- ? 56
- : 44,
- vertical: isMobile
- ? 16
- : isTablet
- ? 28
- : isLargeDesktop
- ? 40
- : 32,
- );
- // 构建内容包装器
- Widget buildContent() {
- return LayoutBuilder(
- builder: (context, constraints) {
- final double targetWidth =
- math.min(effectiveMaxWidth, constraints.maxWidth);
- final content = Container(
- width: targetWidth.isFinite ? targetWidth : null,
- padding: effectivePadding,
- child: ConstrainedBox(
- constraints: BoxConstraints(
- minWidth: targetWidth.isFinite ? targetWidth : 0,
- maxWidth: effectiveMaxWidth,
- ),
- child: child,
- ),
- );
- // 对于宽屏需要居中显示内容
- if (constraints.maxWidth > effectiveMaxWidth) {
- return Align(
- alignment: Alignment.topCenter,
- child: content,
- );
- }
- return content;
- },
- );
- }
- if (!showSidebar) {
- return Scaffold(
- body: Container(
- decoration: const BoxDecoration(
- color: AppColors.background,
- ),
- child: SingleChildScrollView(
- child: Align(
- alignment: Alignment.topCenter,
- child: buildContent(),
- ),
- ),
- ),
- );
- }
- // 移动端使用抽屉式导航
- if (isMobile) {
- return Scaffold(
- appBar: AppBar(
- title: Text(appBarTitle ?? AppConstants.appName),
- backgroundColor: Colors.white,
- foregroundColor: AppColors.textPrimary,
- elevation: 0,
- leading: Builder(
- builder: (context) => IconButton(
- icon: const Icon(LucideIcons.menu),
- onPressed: () => Scaffold.of(context).openDrawer(),
- ),
- ),
- ),
- drawer: const AppSidebar(),
- body: Container(
- decoration: const BoxDecoration(
- color: AppColors.background,
- ),
- child: SingleChildScrollView(
- child: Align(
- alignment: Alignment.topCenter,
- child: buildContent(),
- ),
- ),
- ),
- );
- }
- // 桌面端使用固定侧边栏
- return Scaffold(
- body: Row(
- children: [
- // 侧边栏
- const AppSidebar(),
- // 主内容区
- Expanded(
- child: Container(
- decoration: const BoxDecoration(
- color: AppColors.background,
- ),
- child: Align(
- alignment: Alignment.topCenter,
- child: buildContent(),
- ),
- ),
- ),
- ],
- ),
- );
- }
- }
|