本篇文章中心思想
很高興,大家早上好,每天醒來要做到第一件事情就是寫文章,今天我們要實現到主要內容有如下技術點:StatelessWidget,Scaffold,appBar,Container,ListView,itemBuilder,BottomNavigationBar。每一個都是Flutter到技術點,我相信大家看到這些方法並不陌生,因為之前到文章都有說到,效果圖如下,很簡單到設計,基本小到APP也就這個結構吧,底部一個操作欄,點選進入每個頁面,然後處理了返回按鈕邏輯,進入詳情頁面,雙擊底部按鈕返回到首頁。我會把所有程式碼都貼出來,大家複製可以直接使用。
看看整體到專案結構圖吧
專案結構圖
main.dart檔案到講解:
這個檔案很簡單,正常到一個啟動檔案,運用到了StatelessWidget框架。和MaterialApp效果。
import 'package:flutter/material.dart';import 'package:nested_navigation_demo_flutter/app.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: App(), ); }}
App.dart檔案介紹:
這個檔案頭部匯入包,程式碼裡面也有註釋,大家可以自己看看。
import 'package:flutter/material.dart';import 'package:nested_navigation_demo_flutter/bottom_navigation.dart';import 'package:nested_navigation_demo_flutter/tab_navigator.dart';//APP首頁顯示class App extends StatefulWidget { //建立一個有狀態到元件 @override State<StatefulWidget> createState() => AppState();}class AppState extends State<App> { //tab到item欄目,定義到列舉型別 TabItem _currentTab = TabItem.red; //頁面 Map<TabItem, GlobalKey<NavigatorState>> _navigatorKeys = { TabItem.red: GlobalKey<NavigatorState>(), TabItem.green: GlobalKey<NavigatorState>(), TabItem.blue: GlobalKey<NavigatorState>(), }; //選中到欄目 void _selectTab(TabItem tabItem) { if (tabItem == _currentTab) { // pop to first route _navigatorKeys[tabItem].currentState.popUntil((route) => route.isFirst); } else { setState(() => _currentTab = tabItem); } } @override Widget build(BuildContext context) { //導航返回攔截處理 return WillPopScope( //是一個回撥函式,當用戶點選返回按鈕時被呼叫 onWillPop: () async {//async關鍵字宣告該函式內部有程式碼需要延遲執行 //但是要使用await,必須在有async標記的函式中執行,否則這個await會報錯: final isFirstRouteInCurrentTab = !await _navigatorKeys[_currentTab].currentState.maybePop(); if (isFirstRouteInCurrentTab) { // 如果不在“主要”標籤上 if (_currentTab != TabItem.red) { // 選擇“主”標籤 _selectTab(TabItem.red); // 由應用程式處理的後退按鈕 return false; } } // 如果我們在第一條路線上,讓系統處理後退按鈕 return isFirstRouteInCurrentTab; }, child: Scaffold( body: Stack(children: <Widget>[ _buildOffstageNavigator(TabItem.red), _buildOffstageNavigator(TabItem.green), _buildOffstageNavigator(TabItem.blue), ]), bottomNavigationBar: BottomNavigation( currentTab: _currentTab, onSelectTab: _selectTab, ), ), ); } Widget _buildOffstageNavigator(TabItem tabItem) { return Offstage( offstage: _currentTab != tabItem, child: TabNavigator( navigatorKey: _navigatorKeys[tabItem], tabItem: tabItem, ), ); }}
bottom_navigation.dart檔案介紹
import 'package:flutter/material.dart';enum TabItem { red, green, blue }//底部按鈕Map<TabItem, String> tabName = { TabItem.red: 'red', TabItem.green: 'green', TabItem.blue: 'blue',};//map集合Map<TabItem, MaterialColor> activeTabColor = { TabItem.red: Colors.red, TabItem.green: Colors.green, TabItem.blue: Colors.blue,};class BottomNavigation extends StatelessWidget { BottomNavigation({this.currentTab, this.onSelectTab}); final TabItem currentTab; final ValueChanged<TabItem> onSelectTab; @override Widget build(BuildContext context) { //BottomNavigationBar元件 return BottomNavigationBar( type: BottomNavigationBarType.fixed, items: [ _buildItem(tabItem: TabItem.red), _buildItem(tabItem: TabItem.green), _buildItem(tabItem: TabItem.blue), ], onTap: (index) => onSelectTab( TabItem.values[index], ), ); } BottomNavigationBarItem _buildItem({TabItem tabItem}) { String text = tabName[tabItem]; IconData icon = Icons.layers; return BottomNavigationBarItem( icon: Icon( icon, color: _colorTabMatching(item: tabItem), ), title: Text( text, style: TextStyle( color: _colorTabMatching(item: tabItem), ), ), ); } Color _colorTabMatching({TabItem item}) { return currentTab == item ? activeTabColor[item] : Colors.grey; }}
詳情頁面到介紹color_detail_page.dart
import 'package:flutter/material.dart';//詳情頁面class ColorDetailPage extends StatelessWidget { ColorDetailPage({this.color, this.title, this.materialIndex: 500}); final MaterialColor color; final String title; final int materialIndex; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: color, title: Text( '$title[$materialIndex]', ), ), body: Container( color: color[materialIndex], ), ); }}
列表效果colors_list_page.dart
import 'package:flutter/material.dart';class ColorsListPage extends StatelessWidget { ColorsListPage({this.color, this.title, this.onPush}); final MaterialColor color; final String title; final ValueChanged<int> onPush; @override Widget build(BuildContext context) { //腳手架 return Scaffold( //標題欄 appBar: AppBar( title: Text( title, ), backgroundColor: color, ), //內容Container是一個組合類容器 body: Container( color: Colors.white, child: _buildList(), )); } final List<int> materialIndices = [900, 800, 700, 600, 500, 400, 300, 200, 100, 50]; Widget _buildList() { //ListView就是我們常見的列表元件 return ListView.builder( //item數量 itemCount: materialIndices.length, //item構建者 itemBuilder: (BuildContext content, int index) { int materialIndex = materialIndices[index]; //內容Container是一個組合類容器 return Container( color: color[materialIndex], child: ListTile( title: Text('$materialIndex', style: TextStyle(fontSize: 24.0)), trailing: Icon(Icons.chevron_right), onTap: () => onPush(materialIndex), ), ); }); }}
路由頁面tab_navigator.dart
最新評論