콘솔 종류의 프로그램을 만들경우 가장 기본적으로 필요한 것이 Side Bar 메뉴입니다.
콘솔 필요그램이 작업이 필요해서 간단히 작업해 보았습니다.
Flutter Awsome 등에도 비슷한 프로젝트가 다수 검색되기 때문에 이들 중 괜찮아 보이는 프로젝트의 코드를 사용하시는 것도 방법일 것 같습니다.
하지만 저는 여러가지를 찾아보다가 pub.dev 에 있는 sidebarx 플러그인을 사용하기로 했습니다.
https://pub.dev/packages/sidebarx
sidebarx | Flutter Package
flutter multiplatform navigation sidebar / side navigationbar / drawer widget
pub.dev
이런 플러그인들이 많아진다는 것은 flutter 를 사용하는 입장에서 매우 반가운 일인것 같습니다.
우선 앱의 기본 프레임워크가 필요합니다.
저는 GetX를 사용하는 프로젝트를 좋아하기 때문에 GetMaterialApp으로 시작해 보겠습니다.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Test Console',
debugShowCheckedModeBanner: false,
theme: AppTheme.basic,
initialBinding: InitBinding(),
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => const Home(),
),
GetPage(name: '/user', page: () => UserInfo(),
),
],
);
}
}
이제 앱이 시작되었으니 Home 에 해당하는 코드를 넣어볼게요.
Home은 Scaffold로 구성이 되어 있습니다.
앱웹을 지원하기 위해 화면사이즈가 600보다 작을 경우에는 small screen으로 인식하고 앱바를 보여줄수 있도록 하였습니다.
그리고 Side + Screen을 Row로 구성하여 메뉴가 변경될때 스크린만 변경되는 형태로 작업하면 될것 같습니다.
class _HomeState extends State<Home> {
final _controller = SidebarXController(selectedIndex: 0, extended: true);
final _key = GlobalKey<ScaffoldState>();
final PageIndexController pageIndexController = Get.find();
@override
Widget build(BuildContext context) {
return Builder(
builder: (context) {
final isSmallScreen = MediaQuery.of(context).size.width < 600;
return Scaffold(
key: _key,
appBar: isSmallScreen
? AppBar(
backgroundColor: canvasColor,
title: Text(pageIndexController.getTitleByIndex(_controller.selectedIndex)),
leading: IconButton(
onPressed: () {
_controller.setExtended(true);
_key.currentState?.openDrawer();
},
icon: const Icon(Icons.menu),
),
)
: null,
drawer: MenuSideBar(controller: _controller,),
body: Row(
children: [
if (!isSmallScreen) MenuSideBar(controller: _controller),
Expanded(
child: Center(
child: MainScreen(
controller: _controller,
),
),
),
],
),
);
}
);
}
}
화면은 MenuSideBar와 MainScreen으로 구성되어 있습니다.
먼저 MenuSideBar를 보겠습니다.
class MenuSideBar extends StatelessWidget {
const MenuSideBar({Key? key, required SidebarXController controller})
: _controller = controller,
super(key: key);
final SidebarXController _controller;
@override
Widget build(BuildContext context) {
return SidebarX(
controller: _controller,
theme: SidebarXTheme(
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: canvasColor,
borderRadius: BorderRadius.circular(20),
),
hoverColor: scaffoldBackgroundColor,
textStyle: TextStyle(color: Colors.white.withOpacity(0.7)),
selectedTextStyle: const TextStyle(color: Colors.white),
itemTextPadding: const EdgeInsets.only(left: 30),
selectedItemTextPadding: const EdgeInsets.only(left: 30),
itemDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: canvasColor),
),
selectedItemDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: actionColor.withOpacity(0.37),
),
gradient: const LinearGradient(
colors: [accentCanvasColor, canvasColor],
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.28),
blurRadius: 30,
)
],
),
iconTheme: IconThemeData(
color: Colors.white.withOpacity(0.7),
size: 20,
),
selectedIconTheme: const IconThemeData(
color: Colors.white,
size: 20,
),
),
extendedTheme: const SidebarXTheme(
width: 200,
decoration: BoxDecoration(
color: canvasColor,
),
),
footerDivider: divider,
headerBuilder: (context, extended) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 50,
child: Padding(
padding: const EdgeInsets.only(top: 16, bottom: 16, right: 16),
child: Image.asset('icons/icon_no_background.png'),
),
),
// Text('hibike console', style: TextStyle(fontSize: 17),)
],
);
},
items: [
SidebarXItem(
icon: Icons.home,
label: 'Home',
onTap: () {
debugPrint('Home');
},
),
const SidebarXItem(
icon: Icons.search,
label: 'Search',
),
const SidebarXItem(
icon: Icons.people,
label: 'People',
),
const SidebarXItem(
icon: Icons.favorite,
label: 'Favorite',
),
const SidebarXItem(
iconWidget: FlutterLogo(size: 20),
label: 'Flutter',
),
],
);
}
}
SideBarX에서 제공하는 필드중에 필요한 필드들로 간단히 세팅해 보았습니다.
MainScreen은 선택된 메뉴의 이름을 보여주는 간단한 코드입니다.
class MainScreen extends StatelessWidget {
MainScreen({Key? key, required this.controller,}) : super(key: key);
final SidebarXController controller;
final PageIndexController pageIndexController = Get.find();
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
final pageTitle = pageIndexController.getTitleByIndex(controller.selectedIndex);
switch (controller.selectedIndex) {
case 0:
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemBuilder: (context, index) => Container(
height: 100,
width: double.infinity,
margin: const EdgeInsets.only(bottom: 10, right: 10, left: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Theme.of(context).canvasColor,
boxShadow: const [BoxShadow()],
),
),
);
default:
return Text(
pageTitle,
style: theme.textTheme.headline5,
);
}
},
);
}
}
여기까지 작업된 화면입니다. 전체화면에 메뉴가 잘 보이고 있습니다.
메뉴를 접은 상태입니다. 아이콘이 깔끔하게 잘 나오고 있네요
화면의 사이즈를 줄여보았습니다. 앱바가 나오면서 선택된 메뉴가 잘 보이고 있네요.
이제 페이지 별로 필요한 작업을 하면 간단한 나만의 콘솔을 만들 수 있을 것 같습니다.
'Flutter Web' 카테고리의 다른 글
[Flutter Web] PaginatedDataTable Row Height 조정 (0) | 2022.08.25 |
---|---|
[Flutter Web] "Failed to load network image" CORS 해결 (0) | 2022.08.16 |
[Flutter Web] Firestore Database 연동하기 (0) | 2022.08.15 |
[Flutter Web] Firebase 연동하기 (feat. Flutterfire Cli) (0) | 2022.08.15 |