0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flutter で BottomNavigationBar に FloatingActionButton を埋め込んでみた

Posted at

こんな感じで、BottomNavigationBar に FloatingActionButton を埋め込んでみた。
スクリーンショット 2024-08-31 18.13.27.png
FloatingActionButton は丸くして、ぼわっと縁取ったカスタム仕様。

コード

カスタマイズした FloatingActionButton

まずは少しカッコよく見える、以下の特徴を持つ FloatingActionButton を作った。

  • 円形である。
  • ぼわっとした縁取り。

import 'package:flutter/material.dart';

/// ぼわぁっとした縁取りを持つ円形の FAB.
class BlurCircleFloatingActionButton extends StatelessWidget {
  final VoidCallback onPressed;
  final Widget child;
  final Color backgroundColor;
  final Color borderColor;
  final Color shadowColor;
  final double borderWidth;
  final double blurRadius;
  final double spreadRadius;
  final double width;
  final double height;

  const BlurCircleFloatingActionButton({super.key,
    required this.onPressed,
    required this.child,
    required this.backgroundColor,
    required this.borderColor,
    required this.shadowColor,
    this.borderWidth = 2.0,
    this.blurRadius = 10,
    this.spreadRadius = 5,
    this.width = 36.0,
    this.height = 36.0,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      width: width,
      height: height,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        boxShadow: [
          BoxShadow(
            color: shadowColor,
            blurRadius: blurRadius,
            spreadRadius: spreadRadius,
          ),
        ],
      ),
      child: FloatingActionButton(
        onPressed: onPressed,
        backgroundColor: backgroundColor,
        shape: CircleBorder(
          side: BorderSide(
            color: borderColor,
            width: borderWidth,
          ),
        ),
        child: child,
      ),
    );
  }
}

FloatingActionButton を任意の位置に配置する

FloatingActionButton を任意の位置に配置するために、FloatingActionButtonLocation をカスタマイズしたクラスを用意。
BottomNavigationBar への Dock位置と、そこからのオフセットを指定できるようになる。

class CustomizeFloatingLocation extends FloatingActionButtonLocation {
  FloatingActionButtonLocation location;
  double offsetX;
  double offsetY;
  CustomizeFloatingLocation(this.location, this.offsetX, this.offsetY);
  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    Offset offset = location.getOffset(scaffoldGeometry);
    return Offset(offset.dx + offsetX, offset.dy + offsetY);
  }
}

BottomNavigationBar

そして、 BottomNavigationBar !
build の部分以外は省略します。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text('タイトル'),
      ),
      body: const SafeArea(
        child: Center(
          Text('サンプル',),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items:  const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.photo_outlined),
            label: '写真',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.videocam_outlined),
            label: ' ',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.movie_outlined),
            label: '動画',
          ),
        ],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
        type: BottomNavigationBarType.fixed,
        backgroundColor: Theme.of(context).colorScheme.primary,
        selectedIconTheme: IconThemeData(size: 30, color: Theme.of(context).colorScheme.secondary),
        selectedLabelStyle: TextStyle(color: Theme.of(context).colorScheme.secondary),
        selectedItemColor: Theme.of(context).colorScheme.secondary,
        unselectedIconTheme: IconThemeData(size: 25, color: Theme.of(context).colorScheme.onPrimary),
        unselectedLabelStyle: TextStyle(color: Theme.of(context).colorScheme.onPrimary),
        unselectedItemColor: Theme.of(context).colorScheme.onPrimary,
      ),

      floatingActionButtonLocation: CustomizeFloatingLocation(FloatingActionButtonLocation.centerDocked, 0, 28),
      floatingActionButton: BlurCircleFloatingActionButton(
        onPressed: () async {
        },
        width: 60,
        height: 60,
        backgroundColor: Theme.of(context).colorScheme.surface,
        borderColor: Theme.of(context).colorScheme.secondary,
        borderWidth: 2,
        shadowColor: Theme.of(context).colorScheme.secondary.withOpacity(0.5),
        blurRadius: 10,
        spreadRadius: 5,
        child: Icon(Icons.videocam_outlined, color: Theme.of(context).colorScheme.onSurface, size: 36,),
      ),
    );
  }

ポイントとしては以下。

  • BottomNavigationBarItem は均等に配置するために FAB の裏にも用意してます。
  • floatingActionButtonLocation で、バーの中央にドック。
    オフセットを指定して下方向にずらしています。

最後に

ちょっとはカッコいい感じにできました!
色々調べると、BottomNavigationBar より BottomAppBar を使った方が、FABの周りに隙間を簡単に作ったり、色々とカスタマイズしやすいらしいです(コードは多めに書く必要があるけど)。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?