flutter 底部应用栏demo 笔记

Posted aikongmeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flutter 底部应用栏demo 笔记相关的知识,希望对你有一定的参考价值。

参考链接:
https://gallery.flutter.cn/#/

底部应用栏demo

重点看凹口设置:
floatingActionButtonLocation bottomNavigationBar
BottomAppBarshape: CircularNotchedRectangle,这个CircularNotchedRectangle 是必须配置的。
同时需设置 floatingActionButtonLocation 这个参数接受的是

FloatingActionButtonLocation 提供了

startTopstartFloatcenterFloatendFloat … 其他停靠的只有这三个属性startDockedcenterDockedendDocked


如果需要自己计算位置可以继承StandardFabLocation
重写 getOffsetX 、getOffsetY。
计算值可以参考系统提供的的 FabEndOffsetXFabDockedOffsetY几个位置的计算:

mixin FabEndOffsetX on StandardFabLocation 
  /// Calculates x-offset for end-aligned [FloatingActionButtonLocation]s.
  @override
  double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) 
    assert(scaffoldGeometry.textDirection != null);
    switch (scaffoldGeometry.textDirection) 
      case TextDirection.rtl:
        return StandardFabLocation._leftOffsetX(scaffoldGeometry, adjustment);
      case TextDirection.ltr:
        return StandardFabLocation._rightOffsetX(scaffoldGeometry, adjustment);
    
  

下面是官方源码修改的demo

// Copyright 2019 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class BottomAppBarDemo extends StatefulWidget 
  const BottomAppBarDemo(Key? key) : super(key: key);

  
  State createState() => _BottomAppBarDemoState();


class _BottomAppBarDemoState extends State<BottomAppBarDemo>
    with RestorationMixin 
  final RestorableBool _showFab = RestorableBool(true);
  final RestorableBool _showNotch = RestorableBool(true);
  final RestorableInt _currentFabLocation = RestorableInt(0);
  DateTime date = DateTime.now();

  
  String get restorationId => 'bottom_app_bar_demo';

  
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) 
    registerForRestoration(_showFab, 'show_fab');
    registerForRestoration(_showNotch, 'show_notch');
    registerForRestoration(_currentFabLocation, 'fab_location');
  

  
  void dispose() 
    _showFab.dispose();
    _showNotch.dispose();
    _currentFabLocation.dispose();
    super.dispose();
  

  // Since FloatingActionButtonLocation is not an enum, the index of the
  // selected FloatingActionButtonLocation is used for state restoration.
  static const List<FloatingActionButtonLocation> _fabLocations = [
    FloatingActionButtonLocation.endDocked,
    FloatingActionButtonLocation.centerDocked,
    FloatingActionButtonLocation.endFloat,
    FloatingActionButtonLocation.centerFloat,
  ];

  void _onShowNotchChanged(bool value) 
    setState(() 
      _showNotch.value = value;
    );
  

  void _onShowFabChanged(bool value) 
    setState(() 
      _showFab.value = value;
    );
  

  void _onFabLocationChanged(int? value) 
    setState(() 
      _currentFabLocation.value = value!;
    );
  

  
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text("底部應用欄"),
      ),
      body: ListView(
        padding: const EdgeInsets.only(bottom: 88),
        children: [
          SwitchListTile(
            title: Text(
              "悬浮操作按钮",
            ),
            value: _showFab.value,
            onChanged: _onShowFabChanged,
          ),
          SwitchListTile(
            title: Text("凹口"),
            value: _showNotch.value,
            onChanged: _onShowNotchChanged,
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text("悬浮操作按钮位置"),
          ),
          RadioListTile<int>(
            title: Text(
              "停靠-末端",
            ),
            value: 0,
            groupValue: _currentFabLocation.value,
            onChanged: _onFabLocationChanged,
          ),
          RadioListTile<int>(
            title: Text(
              "停靠-居中",
            ),
            value: 1,
            groupValue: _currentFabLocation.value,
            onChanged: _onFabLocationChanged,
          ),
          RadioListTile<int>(
            title: Text(
              "悬浮-末端",
            ),
            value: 2,
            groupValue: _currentFabLocation.value,
            onChanged: _onFabLocationChanged,
          ),
          RadioListTile<int>(
            title: Text(
              "悬浮-居中",
            ),
            value: 3,
            groupValue: _currentFabLocation.value,
            onChanged: _onFabLocationChanged,
          ),
        ],
      ),
      floatingActionButton: _showFab.value
          ? FloatingActionButton(
              onPressed: () 
                _buildCupertinoDatePicker(
                    context,
                    _BottomPicker(
                      child: CupertinoDatePicker(
                        mode: CupertinoDatePickerMode.date,
                        onDateTimeChanged: (newDateTime) 
                          setState(() => date = newDateTime);
                        ,
                      ),
                    ));
              ,
              tooltip: "创建按钮",
              child: const Icon(Icons.add),
            )
          : null,
      floatingActionButtonLocation: _fabLocations[_currentFabLocation.value],
      bottomNavigationBar: _DemoBottomAppBar(
        fabLocation: _fabLocations[_currentFabLocation.value],
        shape: _showNotch.value ? const CircularNotchedRectangle() : null,
      ),
    );
  

  void _buildCupertinoDatePicker(BuildContext context, Widget child) 
    final themeData = CupertinoTheme.of(context);
    final dialogBody = CupertinoTheme(
      data: themeData,
      child: child,
    );

    showCupertinoModalPopup<void>(
      context: context,
      builder: (context) => dialogBody,
    );
  


class _BottomPicker extends StatelessWidget 
  const _BottomPicker(
    Key? key,
    required this.child,
  ) : super(key: key);

  final Widget child;

  
  Widget build(BuildContext context) 
    return Container(
      height: 216,
      padding: const EdgeInsets.only(top: 6),
      margin: EdgeInsets.only(
        bottom: MediaQuery.of(context).viewInsets.bottom,
      ),
      color: CupertinoColors.systemBackground.resolveFrom(context),
      child: DefaultTextStyle(
        style: TextStyle(
          color: CupertinoColors.label.resolveFrom(context),
          fontSize: 22,
        ),
        child: GestureDetector(
          // Blocks taps from propagating to the modal sheet and popping.
          onTap: () ,
          child: SafeArea(
            top: false,
            child: child,
          ),
        ),
      ),
    );
  


class _DemoBottomAppBar extends StatelessWidget 
  const _DemoBottomAppBar(
    required this.fabLocation,
    this.shape,
  );

  final FloatingActionButtonLocation fabLocation;
  final NotchedShape? shape;

  static final centerLocations = <FloatingActionButtonLocation>[
    FloatingActionButtonLocation.centerDocked,
    FloatingActionButtonLocation.centerFloat,
  ];

  
  Widget build(BuildContext context) 
    return BottomAppBar(
      shape: shape,
      color: Colors.green,
      child: IconTheme(
        data: IconThemeData(color: Theme.of(context).colorScheme.onPrimary),
        child: Row(
          children: [
            IconButton(
              tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
              icon: const Icon(Icons.menu),
              onPressed: () ,
            ),
            if (centerLocations.contains(fabLocation)) const Spacer(),
            IconButton(
              tooltip: "starterAppTooltipSearch",
              icon: const Icon(Icons.search),
              onPressed: () ,
            ),
            IconButton(
              tooltip: "starterAppTooltipFavorite",
              icon: const Icon(Icons.favorite),
              onPressed: () ,
            ),
          ],
        ),
      ),
    );
  


以上是关于flutter 底部应用栏demo 笔记的主要内容,如果未能解决你的问题,请参考以下文章

flutter 底部应用栏demo 笔记

flutter 底部应用栏demo 笔记

flutter 底部应用栏demo 笔记

Flutter学习笔记--仿闲鱼底部导航栏带有中间凸起图标

Flutter:使用底部导航栏为应用栏颜色设置动画

Flutter底部导航栏BottomNavigationBar页面状态保持解决方案