/ 生活中常部分app底部導航樣式 /
從智能手機的普及我們的生活 , 手機已經為我們生活提供了方便 . 購買手機后系統默認安裝了很多款app , 隨便點開一款手機app 進入應用首頁映入眼簾的就是底部導航 . 可以說手機app為我們生活提供了方便 , 同時app里面的底部導航為我們更好的使用應用 . 市面上的app底部導航切換樣式都差不多 (分底部Tab 導航欄 和 舵式導航欄) . 點擊底部導航選項可以切換到不同功能模塊的 , 讓用戶在使用的時候更加清楚要導航的功能 .
/ app底部導航構造 /

導航選項純圖示
![]()
![]()
導航純文本


導航圖文混排
![]()
![]()
/ Flutter 實作底部導航 /
BottomNavigationBarItem
服務于 BottomNavigationBar . 包括屬性icon (選項圖示)、title (選項包括文本的widget被棄用)、label (導航欄文本值)、backgroundColor、tooltip (長按時選項頂部彈出提示 , 長按選項時選項樣式不會發生改變)

在flutter sdk 大于1.19.0的版本上使用該引數 , 拋出如下例外 :


backgroundColor 選項有漸變和移動效果狀態下的背景顏色
BottomNavigationBar 引數 BottomNavigationBarType 是 BottomNavigationBarType.shifting 生效. 會覆寫導航欄BottomNavigationBar背景顏色 . 訪問B站查看效果

tooltip 長按選項彈出提示 訪問B站查看效果

BottomNavigationBar
底部導航 可以自定義 選項文本、圖示樣式 . 長按點擊彈出提示 . 可以使用flutter自帶的icon 切換圖示的樣式 .

items / BottomNavigationBarItem 集合
flutter自帶的Icon


class StartPage extends StatefulWidget {
StartPage({Key? key, this.title}) : super(key: key);
final String? title;
@override
_StartPageState createState() => _StartPageState();
}
class _StartPageState extends State<StartPage> {
GlobalKey<StackWState> _stackGk = GlobalKey<StackWState>();
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BotNavBar(
stackValue: (int currentIndex, List<int> tabInt) {
_stackGk.currentState!.changeStack(currentIndex, tabInt);
},
),
body: StackWidget(
key: _stackGk,
));
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter_bottom_navigator/base/presenter/IPresenter.dart';
import 'package:flutter_bottom_navigator/base/view/BaseView.dart';
import 'package:flutter_bottom_navigator/base/view/IView.dart';
class StackWidget extends BaseView {
final int? currentIndex;
final List<int>? tabInt;
StackWidget({this.currentIndex, this.tabInt, Key? key}) : super(key: key);
@override
BaseViewState<IPresenter<IView>, BaseView> getState() {
return StackWState();
}
}
class StackWState extends BaseViewState<IPresenter, StackWidget> {
int _currentIndex = 0;
List<int>? _tabInt;
final List<Widget> _children = [
Center(
child: Text('Page1'),
),
Center(
child: Text('Page2'),
),
];
@override
void initState() {
// TODO: implement initState
super.initState();
_tabInt = widget.tabInt == null ? [0] : widget.tabInt;
}
void changeStack(int currentIndex, List<int> tabInt) {
setState(() {});
_currentIndex = currentIndex;
_tabInt = tabInt;
}
//Page的顯示和隱藏
_child(int _index) {
return Offstage(
offstage: !(_currentIndex == _index),
child: _tabInt!.contains(_index) ? _children[_index] : Container(),
);
}
@override
buildWidget() {
// TODO: implement buildWidget
return Stack(
children: <Widget>[
_child(0),
_child(1),
],
);
}
}
import 'package:flutter/material.dart';
class BotNavBar extends StatefulWidget {
final ValueChanged? stackValue;
BotNavBar({Key? key, this.stackValue}) : super(key: key);
@override
_BotNavBarState createState() => _BotNavBarState();
}
class _BotNavBarState extends State<BotNavBar> {
List<int> tabInt = [0];
int _currentIndex = 0;
late var _tabImages;
@override
void initState() {
// TODO: implement initState
super.initState();
_tabImages = [
_singleTabImage('home'),
_singleTabImage('type'),
_singleTabImage('mine'),
];
}
BottomNavigationBarItem _singleBotNavItem(_index) {
return BottomNavigationBarItem(
icon: _getTabIcon(
_index,
),
backgroundColor: Colors.red,
tooltip: '$_index tooltips',
//title: Text('$_index title'),
label: '$_index label');
}
_singleTabImage(_labelPng) {
return [
Icon(Icons.message),
Icon(Icons.message),
];
}
Widget _getTabIcon(int curIndex) {
if (curIndex == _currentIndex) {
return _tabImages[curIndex][0];
}
return _tabImages[curIndex][1];
}
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onTabTapped,
currentIndex: _currentIndex,
backgroundColor: Colors.white,
selectedItemColor: Colors.blue,
unselectedItemColor: Color(0xffAFB1BD),
elevation: 6.0,
selectedIconTheme: IconThemeData(color: Colors.green),
unselectedIconTheme: IconThemeData(color: Colors.red),
selectedLabelStyle: TextStyle(inherit: true),
//fixedColor: Colors.blue,
showUnselectedLabels: true,
showSelectedLabels: true,
mouseCursor: SystemMouseCursors.move,
enableFeedback: false,
items: [
_singleBotNavItem(0),
_singleBotNavItem(1),
],
);
}
_onTabTapped(int index) {
setState(() {});
_currentIndex = index;
if (!tabInt.contains(index)) {
tabInt.add(index);
}
if (widget.stackValue != null) {
widget.stackValue!(_currentIndex, tabInt);
}
}
}
typedef ValueChanged = void Function(
int currentIndex,
List<int> tabInt,
);
自定義Icon

創建assets 檔案夾來存盤要讀取的自定義圖示

在 pubspec.yaml 檔案里面配置圖片的依賴

_singleTabImage(_labelPng) {
return [
Image.asset(
'assets/${_labelPng}_b_select.png',
width: 40.0,
height: 40.0,
),
Image.asset(
'assets/${_labelPng}_b_normal.png',
width: 40.0,
height: 40.0,
)
];
}
elevation / 導航欄陰影Z坐標




selectedLabelStyle / unselectedLabelStyle
導航欄選中文本的樣式 (字體顏色、背景顏色、字體權重、字體陰影 、…...)
導航欄選中文本的樣式 (字體顏色、背景顏色、字體權重、字體陰影 、……)


showSelectedLabels / showUnselectedLabels
是否顯示選中時的文本 / 是否顯示未選中時的文本

GlobalKey 實作導航區域重繪
StartPage 包含了 內容區域 (StackWidget) 和底部導航 (BotNavBar) . 當首次進入應用時 , 會渲染內容容區域和底部導航 . 當我們需要切換其它導航時 , 要做到切換導航重新渲染內容區域和底部導航而不執行內容區域和底部導航的父控制元件StartPage的build函式,需要用到GlobalKey來實作點擊導航重繪內容區域而不執行StartPage的build函式 .
class _StartPageState extends State<StartPage> {
GlobalKey<StackWState> _stackGk = GlobalKey<StackWState>();
@override
Widget build(BuildContext context) {
print('StartPage _build');
return Scaffold(
bottomNavigationBar: BotNavBar(
stackValue: (int currentIndex, List<int> tabInt) {
_stackGk.currentState!.changeStack(currentIndex, tabInt);
},
),
body: StackWidget(
key: _stackGk,
));
}
}


flutter_bottom_navigator 案例下載
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/401631.html
標籤:java
上一篇:JAVA實作客戶資訊管理系統以及給大一寒假學生的建議
下一篇:嘗試將地圖串列轉換為小部件時出錯

