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

猜你喜欢

转载自blog.csdn.net/aikongmeng/article/details/127793321