• Flutter NestedScrollView 、SliverAppBar全解析,悬浮菜单的应用


    在我们开发过程中经常会使用到悬浮菜单的使用,当我们滑动到指定位置后,菜单会自动悬浮。

    实现效果如下(左为滑动前、右为滑动后):

    上述便是通过NestedScrollView 、SliverAppBar实现的效果,通过两个控件我们便可以实现上述的效果。

    废话不多说直接上代码,代码的实现原理会以注释的形式实现:

    1. import 'package:aboxmini/view/home/room/room_device_page.dart';
    2. import 'package:flutter/material.dart';
    3. import '../../model/app_model.dart';
    4. class HomeTabBar extends StatefulWidget {
    5. const HomeTabBar({super.key});
    6. @override
    7. State createState() => _HomeTabBarState();
    8. }
    9. class _HomeTabBarState extends State<HomeTabBar> with TickerProviderStateMixin {
    10. /// 自定义的一个类,此类可获取屏幕宽度等
    11. final AppModel _appModel = AppModel.share();
    12. /// 设置 中间展示区域的高度
    13. final double _topHeight = 180 + AppModel.share().safeTop + kToolbarHeight;
    14. /// 分栏控制器
    15. late TabController tabController = TabController(length: 3, vsync: this);
    16. /// 分栏控制器每一个标题
    17. final _tabs = <String>["Tab 1", "Tab 2", "Tab 3"];
    18. @override
    19. void dispose() {
    20. tabController.dispose();
    21. super.dispose();
    22. }
    23. @override
    24. Widget build(BuildContext context) {
    25. return DefaultTabController(
    26. length: _tabs.length,
    27. child: NestedScrollView(
    28. headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
    29. return [
    30. SliverOverlapAbsorber(
    31. handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
    32. sliver: SliverAppBar(
    33. /// 取消系统导航左边按钮
    34. leading: Container(),
    35. /// 设置背景色
    36. backgroundColor: Colors.white,
    37. /// 设置左边按钮宽度
    38. leadingWidth: _appModel.width,
    39. centerTitle: false,
    40. pinned: true,
    41. floating: false,
    42. snap: false,
    43. primary: true,
    44. /// 设置分栏区域上面的高度
    45. expandedHeight: 230.0,
    46. elevation: 10,
    47. //是否显示阴影,直接取值innerBoxIsScrolled,展开不显示阴影,合并后会显示
    48. forceElevated: innerBoxIsScrolled,
    49. ///自定义导航和中间内容的展示
    50. flexibleSpace: _displayNavAndEnvInfo(),
    51. /// TabBar 分栏标题
    52. bottom: _addTabBar(),
    53. ),
    54. ),
    55. ];
    56. },
    57. /// 分栏展示的页面信息
    58. body: _addTabBarView(),
    59. ),
    60. );
    61. }
    62. /// 自定义导航和中间内容展示
    63. Widget _displayNavAndEnvInfo() {
    64. return Container(
    65. color: Colors.white,
    66. width: _appModel.width,
    67. height: _topHeight,
    68. child: Column(
    69. children: [
    70. _addNav(),
    71. _displayEnvDevice(),
    72. ],
    73. ),
    74. );
    75. }
    76. /// 自定义导航 可随意定制
    77. Widget _addNav() {
    78. return SizedBox(
    79. width: _appModel.width,
    80. height: _appModel.safeTop + kToolbarHeight,
    81. child: Container(
    82. margin: EdgeInsets.only(top: _appModel.safeTop),
    83. height: kToolbarHeight,
    84. width: _appModel.width,
    85. alignment: Alignment.centerLeft,
    86. child: Row(
    87. children: [
    88. GestureDetector(
    89. onTap: () {
    90. widget.z.toggle!();
    91. },
    92. child: Row(
    93. children: [
    94. Container(
    95. margin: const EdgeInsets.only(left: 12, right: 6),
    96. child: const Icon(
    97. Icons.menu,
    98. size: 20,
    99. color: Colors.red,
    100. ),
    101. ),
    102. Text("${_appModel.currentDatum?.hostname ?? ""}"),
    103. ],
    104. ),
    105. ),
    106. Expanded(child: Container())
    107. ],
    108. ),
    109. ),
    110. );
    111. }
    112. /// 导航和TabBar中间展示的内容,可随意自定义
    113. Widget _displayEnvDevice() {
    114. return Container(
    115. color: Colors.white,
    116. );
    117. }
    118. /// TabBar 展示样式自定义,可以滚动并且居左展示
    119. PreferredSize _addTabBar() {
    120. return PreferredSize(
    121. /// 设置高度
    122. preferredSize: const Size.fromHeight(35),
    123. child: Align(
    124. /// 设置展示方式
    125. alignment: Alignment.centerLeft,
    126. /// TabBar选中、未选中样式
    127. child: TabBar(
    128. /// 是否允许滚动
    129. isScrollable: true,
    130. unselectedLabelColor: Colors.black54,
    131. unselectedLabelStyle: const TextStyle(fontSize: 15),
    132. labelColor: Colors.blue,
    133. labelStyle:
    134. const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
    135. indicatorSize: TabBarIndicatorSize.label,
    136. tabs: _tabs.map((String name) => Tab(text: name)).toList(),
    137. ),
    138. ),
    139. );
    140. }
    141. /// TabBar 分栏下的各个页面
    142. Widget _addTabBarView() {
    143. return TabBarView(
    144. children: _tabs.map((String name) {
    145. // 分栏下的页面(可随意定义、也可以设置成Text等控件),实现方式还有其他方式
    146. return RoomDevicePage();
    147. }).toList(),
    148. );
    149. }
    150. }

    以上便是菜单悬浮的效果实现,注释写的很详细,直接粘贴复制即可实现。

  • 相关阅读:
    汽车电子相关术语
    HTML文本内容 转化为纯文本
    WebRTC安全架构
    多极神经元手绘图作业,多极运动神经元手绘图
    Java版本spring cloud + spring boot企业电子招投标系统源代码
    信号量实现生产消费模型
    代码随想录训练营第29天|LeetCode 491.递增子序列、46.全排列、47.全排列 II
    MyBatis-Plus中的CURD(含部分注解)
    使用环形缓冲区ringbuffer实现串口数据接收
    秋染田野稻菽飘香 国稻种芯·中国水稻节:河北各地农业丰收
  • 原文地址:https://blog.csdn.net/WangQingLei0307/article/details/134463377