Flutter 制作一個抽屜菜單
大家好我是米卡,這次我們來講一下如何在Flutter中制作一個抽屜菜單吧~
什么是抽屜菜單呢?
其實在APP中,抽屜菜單就是當手指在屏幕橫向滑動時候,左邊屏幕會滑出或者滑入一個View的東西,就像一個抽屜。下面是我在網上找的一個示例圖,和現在正跑在我的模擬器上的目標圖。
在Android或者IOS上,要實現這種側滑抽屜空間,可以使用外部庫來達到效果,不過Flutter本身已經給我們提供了 Drawer 這個UI組件,來使你更輕松地達到這個效果。
Drawer及UserAccountsDrawerHeader可用屬性
Drawer屬性 | 說明 |
---|---|
elevation | 背景高度 |
child | 子組件 |
semanticLabel | 標簽 |
UserAccountsDrawerHeader屬性 | 說明 |
---|---|
decoration | 頭部裝飾 |
margin | 外邊距 默認8.0 |
currentAccountPicture | 主圖像 |
otherAccountsPictures | 副圖像 |
accountName | 標題 |
accountEmail | 副標題 |
onDetailsPressed | 點擊監聽 |
實現
首先我默認大家已經搭建好了Flutter的環境並已經初步寫了一個簡單的Widget => Home用於容納我們的布局
import 'package:coco/components/drawer.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Coco',
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
'/': (context) => HomeIn(),
},
theme: ThemeData(
primarySwatch: Colors.blue,
highlightColor: Color.fromRGBO(255, 255, 255, 0.5),
splashColor: Colors.white70,
accentColor: Color.fromRGBO(178, 222, 225, 1.0),
),
);
}
}
class HomeIn extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Home();
}
}
class Home extends StatefulWidget {
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
drawer: DrawerHead() // 抽取控件
),
);
}
}
在展示的這段代碼中,除與抽屜菜單無關的代碼博主都已去除,以免影響同學們的閱讀,這段代碼可以允許運行在你的工程的lib下的main.dart中,但要注意lib文件夾內還有一個components文件夾,其下存在drawer.dart文件(抽取出來的抽屜控件)。
文件結構
...
/android
/ios
/lib
/components
drawer.dart
main.dart
main.dart中,保留了注釋的地方就是我們抽出來的drawer控件,這里講個題外話,Flutter的寫法和我們前端寫UI的方式是兩種方法,Flutter本身是一個APP上的開源UI工具包,意思是書寫它你需要使用它本身的API控件去寫,這會很容易導致嵌套地獄,在Flutter中你經常能夠看到向右的金字塔狀代碼。但是這其實也是Flutter給我們帶來的信息:希望你能將你的代碼保持足夠的細度,這有助於你減少嵌套層數,也可以提醒你及時考慮組件的抽取以及復用,抽取的這方面就不用贅述了,相信大家都有足夠的經驗與習慣來處理,我們回到正題。
事實上,在Scaffold中使用了drawer后,里面的內容(或者說Widget)就已經是以一個抽屜控件的形式展示了,大家可以試着只在darwer.dart文件中返回一個Text('jobs')來查看會出現的樣子,那么我們接下來要做的只是讓這個Widget更加像一個抽屜組件而已。
為了避免可能冗余的文字描述,關於這一段的注釋我已經全部打在了上面,方便大家學習。
drawer.dart
import 'package:flutter/material.dart';
class DrawerHead extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer( // 重要的Drawer組件
child: ListView( // Flutter 可滾動組件
padding: EdgeInsets.zero, // padding為0
children: <Widget>[
UserAccountsDrawerHeader(
// UserAccountsDrawerHeader 可以設置用戶頭像、用戶名、Email 等信息,顯示一個符合紙墨設計規范的 drawer header。
// 標題
accountName: Text('Jobsofferings',
style: TextStyle(fontWeight: FontWeight.bold)),
// 副標題
accountEmail: Text('https://juejin.im/user/5eaee21f5188256da0323bf9'),
// Emails
currentAccountPicture: CircleAvatar(
// 使用網絡加載圖像
backgroundImage: NetworkImage(
'https://images.cnblogs.com/cnblogs_com/JobsOfferings/1363202/o_preview.jpg'),
),
// 圓角頭像
decoration: BoxDecoration(
color: Colors.yellow[400],
image: DecorationImage(
image: NetworkImage(
'http://pic.netbian.com/uploads/allimg/190510/221228-15574975489aa1.jpg'),
fit: BoxFit.cover, // 一種圖像的布局方式
colorFilter: ColorFilter.mode(
Colors.grey[400].withOpacity(0.6),
BlendMode.hardLight))),
// BoxDecoration 用於制作背景
),
// ListTile是下方的幾個可點按List
ListTile(
// List標題
title: Text('details', textAlign: TextAlign.right),
trailing: Icon(
Icons.favorite, // Icon種類
color: Colors.black12, // Icon顏色
size: 22.0, // Icon大小
),
// 點按時間,這里可以做你想做的事情,如跳轉、判斷等等
// 此處博主只使用了 Navigator.pop(context) 來手動關閉Drawer
onTap: () => Navigator.pop(context),
),
ListTile(
title: Text('Favorite', textAlign: TextAlign.right),
trailing: Icon(
Icons.favorite,
color: Colors.black12,
size: 22.0,
),
onTap: () => Navigator.pop(context),
),
ListTile(
title: Text('Settings', textAlign: TextAlign.right),
trailing: Icon(
Icons.favorite,
color: Colors.black12,
size: 22.0,
),
onTap: () => Navigator.pop(context),
),
],
),
);
}
}