

(main.dart) และหน้ารายละเอียด (detail_page.dart) แต่ก่อนหน้านั้นเรามาเตรียมสีที่จะใช้ กับข้อมูลกันก่อน
color_palette.dart โลด| import 'package:flutter/material.dart'; | |
| class ColorPalette { | |
| static Color grey10 = Color(0xFFf2f6f5); | |
| static Color grey30 = Color(0xFFc8dad3); | |
| static Color grey60 = Color(0xFF93b5b3); | |
| static Color grey90 = Color(0xFF63707e); | |
| } |
icon_data.dart| import 'dart:core'; | |
| import 'package:flutter/cupertino.dart'; | |
| import 'package:flutter/material.dart'; | |
| class IconModel { | |
| final String title; | |
| final IconData icon; | |
| IconModel({this.title, this.icon}); | |
| } | |
| final List<IconModel> iconList = [ | |
| IconModel(title: 'Motorcycle', icon: Icons.motorcycle), | |
| IconModel(title: 'Car', icon: Icons.directions_car), | |
| IconModel(title: 'Train', icon: Icons.directions_railway), | |
| IconModel(title: 'Laptop',icon: Icons.laptop_windows), | |
| IconModel(title: 'Home',icon: Icons.home), | |
| ]; |
IconModel โดยข้อมูลแต่ละอันจะประกอบไปด้วยชื่อ title กับไอคอน icon และสร้างข้อมูลต่อ เป็น List ของ IconModel เก็บไว้ในตัวแปร iconListmain.dart| import 'package:flutter/material.dart'; | |
| import 'package:icon_showcase_design_part/color_palette.dart'; | |
| import 'package:icon_showcase_design_part/icon_data.dart'; | |
| import 'package:icon_showcase_design_part/detail_page.dart'; | |
| void main() => runApp(MyApp()); | |
| class MyApp extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| title: 'Icon Showcase', | |
| theme: ThemeData( | |
| primarySwatch: Colors.blue, | |
| ), | |
| home: MyHomePage(title: 'Icon Showcase'), | |
| debugShowCheckedModeBanner: false, | |
| ); | |
| } | |
| } | |
| class MyHomePage extends StatefulWidget { | |
| MyHomePage({Key key, this.title}) : super(key: key); | |
| final String title; | |
| @override | |
| _MyHomePageState createState() => _MyHomePageState(); | |
| } | |
| class _MyHomePageState extends State<MyHomePage> { | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: ColorPalette.grey90, | |
| appBar: AppBar( | |
| backgroundColor: Colors.transparent, | |
| elevation: 0.0, | |
| title: Text( | |
| widget.title, | |
| style: TextStyle(color: ColorPalette.grey10), | |
| ), | |
| leading: Icon( | |
| Icons.menu, | |
| color: ColorPalette.grey10, | |
| ), | |
| ), | |
| body: ListView.builder( | |
| itemCount: iconList.length, | |
| itemBuilder: (context, index) => InkWell( | |
| onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context)=> DetailPage(iconData: iconList[index],))), | |
| child: Card( | |
| color: ColorPalette.grey10, | |
| margin: EdgeInsets.all(10), | |
| elevation: 10.0, | |
| shape: RoundedRectangleBorder( | |
| borderRadius: BorderRadius.circular(25.0)), | |
| child: Padding( | |
| padding: const EdgeInsets.all(30.0), | |
| child: ListTile( | |
| leading: Icon( | |
| iconList[index].icon, | |
| size: 45.0, | |
| color: ColorPalette.grey60, | |
| ), | |
| title: Text(iconList[index].title,style: TextStyle(color: Colors.black87, fontSize: 20.0),), | |
| ), | |
| ), | |
| ), | |
| ), | |
| )); | |
| } | |
| } |
class _MyHomePageState
Scaffold เราจะตั้งสีพื้นหลัง ทั้งหมดเป็น ColorPalette.grey90
Appbar เราก็ทำให้สีพื้นหลังโปร่งใสซะ และไม่ให้มันเกิดเงา ก็ตั้ง elevation เป็น 0.0 แล้วเพิ่ม leading เป็น icon menu จะได้ดูเหมือนมีฟีเจอร์อื่น แต่เราจะไม่ได้ใส่เมนูลงไปจริงๆ
ListView ที่ประกอบไปด้วย Card ที่สร้างมาจากข้อมูลของเรา เราจะใช้ ListView.builder ให้มันสร้าง Card แล้วในจะใส่ ListTile เข้าไป เพื่อจัดวางข้อมูลของเรา
Widget child เข้าไปก็ใช้งานได้ทันที ถ้าอยากปรับความมนของขอบก็ส่ง shape: เข้าไปได้เลยCard แล้ว เราอยากจัดองค์ประกอบแบบง่ายๆก็ใช้ Widget ListTile
Widget child ของเราเข้าไปตรงนั้นเลย (ปล.ไม่จำเป็นต้องอยู่ใน Card นะ แค่ส่วนใหญ่ชอบใช้คู่กัน)padding เพื่อให้องค์ประกอบออกมากำลังดี ได้ผลลัพธ์สุดท้ายดังนี้
detail_page.dart กันเลย| import 'package:icon_showcase_design_part/color_palette.dart'; | |
| import 'package:icon_showcase_design_part/icon_data.dart'; | |
| import 'package:flutter/material.dart'; | |
| class DetailPage extends StatefulWidget { | |
| final IconModel iconData; | |
| DetailPage({Key key, @required this.iconData}) : super(key: key); | |
| @override | |
| _DetailPageState createState() => _DetailPageState(); | |
| } | |
| class _DetailPageState extends State<DetailPage> { | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: ColorPalette.grey90, | |
| body: SafeArea( | |
| child: Card( | |
| margin: EdgeInsets.all(10), | |
| clipBehavior: Clip.antiAlias, | |
| elevation: 0.0, | |
| color: ColorPalette.grey10, | |
| shape: RoundedRectangleBorder( | |
| borderRadius: BorderRadius.circular(25.0)), | |
| child: Stack(children: <Widget>[ | |
| Positioned.fill( | |
| bottom: -90, | |
| right: -90, | |
| child: Align( | |
| alignment: Alignment.bottomRight, | |
| child: Icon( | |
| widget.iconData.icon, | |
| size: 400, | |
| color: ColorPalette.grey30, | |
| ))), | |
| Container( | |
| width: MediaQuery.of(context).size.width, | |
| height: 500, | |
| child: Padding( | |
| padding: const EdgeInsets.only(left: 20.0, top: 20.0), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: <Widget>[ | |
| InkWell( | |
| onTap: () { | |
| Navigator.of(context).pop(true); | |
| return Future.value(false); | |
| }, | |
| child: Icon( | |
| Icons.arrow_back, | |
| )), | |
| Text(widget.iconData.title,style: TextStyle(color: Colors.black87, fontSize: 60.0),), | |
| ]))), | |
| ])), | |
| ), | |
| ); | |
| } | |
| } |
Scaffold เราจะไม่มี appbar ดังนั้นที่ body เราจะหุ้ม widget ด้วย SafeArea

Widget Stack

Navigator ใน main.dart ให้ push หน้า detail_page.dart และในหน้า detail_page.dart ก็ใส่ pop จะได้กลับหน้าหลักได้

