我正在创建一个看起来像仪表板的 Flutter Web 项目。它有一个侧面导航和一个显示不同屏幕的主体区域。
为了实现这一点,我使用 Expanded 将我的屏幕分为两部分并给它们一个 flex 值。 为了显示不同的屏幕,我使用了 IndexedStack。
这是我的 main.dart 文件:
import 'package:flutter/material.dart';
import 'package:xxx/screens/courses/courses_screen.dart';
import 'package:xxx/side_navigation/menu_item.dart';
import 'package:xxx/componnents/header.dart';
import 'package:websafe_svg/websafe_svg.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
scaffoldBackgroundColor: Color(0xfffafafa),
fontFamily: 'Poppins',
),
home: MainScreenLayout(),
);
}
}
class MainScreenLayout extends StatefulWidget {
@override
_MainScreenLayoutState createState() => _MainScreenLayoutState();
}
class _MainScreenLayoutState extends State<MainScreenLayout> {
int selectedIndex = 0;
int hoverIndex = -1;
Color bgColor = Colors.transparent;
final List<MenuItem> menus = <MenuItem>[
MenuItem(label: 'Home', icon: Icons.home, screen: Container()),
MenuItem(label: 'Courses', icon: Icons.add, screen: Container()),
MenuItem(label: 'Students', icon: Icons.face_outlined, screen: Container()),
MenuItem(label: 'Home', icon: Icons.home, screen: Container()),
MenuItem(label: 'Courses', icon: Icons.add, screen: Container()),
MenuItem(label: 'Students', icon: Icons.face_outlined, screen: Container()),
];
final List<Widget> _screens = [
Container(
child: Image.asset(
'assets/try.png',
width: 100,
height: 100,
),
),
CoursesScreen(),
Container(
child: WebsafeSvg.asset('assets/folder_icon.svg'),
),
];
void _changeBg(int index) {
setState(() {
hoverIndex = index;
});
}
void _resetBg() {
setState(() {
hoverIndex = -1;
});
}
@override
Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width;
return Scaffold(
body: Row(
children: [
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
color: Color(0xffffffff),
borderRadius: BorderRadius.only(
topRight: Radius.circular(_width * 0.03),
bottomRight: Radius.circular(_width * 0.03),
),
),
child: Column(
children: <Widget>[
SizedBox(
height: 50,
),
Flexible(
child: ListView.builder(
itemCount: menus.length,
itemBuilder: (BuildContext context, int index) {
return MouseRegion(
onHover: (event) {
_changeBg(index);
},
onExit: (event) {
_resetBg();
},
child: MenuItemLayout(
bgColor: hoverIndex == index
? Color(0xfffafafa)
: Colors.transparent,
menuItem: menus[index],
isSelected: selectedIndex == index ? true : false,
onTap: () {
setState(() {
selectedIndex = index;
});
},
),
);
},
),
),
],
),
),
),
Expanded(
flex: 7,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Header(
label: menus[selectedIndex].label,
),
Expanded(
child: Container(
child: IndexedStack(
index: selectedIndex,
children: _screens,
),
),
),
],
),
)
],
),
);
}
}
这是其中一个屏幕(CourseScreen)的代码
import 'package:flutter/material.dart';
import 'package:vjti_dashboard/componnents/responsive.dart';
import 'package:vjti_dashboard/screens/courses/courses_card.dart';
import 'package:vjti_dashboard/screens/courses/courses_model.dart';
class CoursesScreen extends StatelessWidget {
final List<CoursesModel> allCourses = [
CoursesModel(courseId: '123', courseName: 'Ecommerce'),
CoursesModel(courseId: '123', courseName: 'Big Data Analytics'),
CoursesModel(courseId: '123', courseName: 'User Experience Design'),
CoursesModel(courseId: '123', courseName: 'Technical Seminar'),
CoursesModel(courseId: '123', courseName: 'Elective 1'),
];
@override
Widget build(BuildContext context) {
return ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
Sample(
headingLabel: 'First Year',
allCourses: allCourses,
courseColor: Color(0xffEEF1E6),
),
Sample(
headingLabel: 'Second Year',
allCourses: allCourses,
courseColor: Color(0xffF9F1D6),
),
Sample(
headingLabel: 'Third Year',
allCourses: allCourses,
courseColor: Color(0xffE2F0CB),
),
],
);
}
}
class Sample extends StatelessWidget {
final String headingLabel;
final Color courseColor;
final List<CoursesModel> allCourses;
const Sample({Key key, this.allCourses, this.headingLabel, this.courseColor})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: () {},
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color(0xffd6d6d6),
width: 1.0,
),
),
),
child: Text(headingLabel),
),
),
GridView.count(
primary: false,
physics: ScrollPhysics(), // to disable GridView's scrolling
shrinkWrap: true,
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 0),
crossAxisSpacing: 20,
childAspectRatio: 3 / 1,
mainAxisSpacing: 20,
crossAxisCount: Responsive.isDesktop(context)
? 4
: Responsive.isTablet(context)
? 3
: 2,
children: List.generate(
allCourses.length,
(index) {
return CourseCard(
coursesModel: allCourses[index],
containerColor: courseColor,
);
},
),
),
],
),
);
}
}
侧边导航按其应有的方式工作,并且在导航停留在左侧时加载了不同的页面。 当我点击 CourseScreen 上的任何小部件时,我想打开另一个屏幕来替换 CourseScreen,但导航应该仍然存在。
我怎样才能做到这一点?
注意:我是 flutter 的新手,我编写的大部分代码都不完美,可能不是一个好方法。如果您能指出上述文件中的错误代码,我将不胜感激。
谢谢!!!