flutter bottom application bar demo notes

Reference link:
https://gallery.flutter.cn/#/

Bottom app bar demo
insert image description here

Focus on the notch settings:
floatingActionButtonLocation bottomNavigationBar
BottomAppBaryes shape: CircularNotchedRectangle, this CircularNotchedRectanglemust be configured.
Also need to set floatingActionButtonLocationthis parameter to accept the

FloatingActionButtonLocationprovided

startTop, startFloat, centerFloat, endFloat... Other docks only have these three attributes startDocked, centerDocked, endDocked.


If you need to calculate the position yourself, you can inherit StandardFabLocation
and rewrite getOffsetX and getOffsetY. The calculated value can refer to the calculation of several positions of FabEndOffsetX and FabDockedOffsetY
provided by the system :

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);
    }
  }
}

The following is the demo of the official source code modification

// 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: () {
    
    },
            ),
          ],
        ),
      ),
    );
  }
}

おすすめ

転載: blog.csdn.net/aikongmeng/article/details/127793321