Flutter圆形波纹效果:如何打造漂亮的material BottomNavigationBar

Flutter circular ripple effect: How to build beautiful material BottomNavigationBar

作为 Google stadia app is made with flutter 我想知道他们是如何在 BottomNavigationBar 上实现更漂亮的波纹动画的。

示例:

他们是如何实现自定义波纹动画的?

编辑:简单自定义 BottomNavigationItem:

bottomNavigationBar: Container(
      height: 50,
      child: Row(
        children: <Widget>[
          Expanded(
            child: BottomItem(),
          ),
          Expanded(
            child: BottomItem(),
          ),
          Expanded(
            child: BottomItem(),
          ),
        ],
      )),
class BottomItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {},
      child: Center(child: Icon(Icons.shop)),
    );
  }
}

您可能想在 BottomNavigationBar 中使用 InkResponse Class:)

从 InkWell 编辑到 InkResponse。

您要找的 InkInkResponse 而不是 InkWell。 InkWell 用高亮填充整个可用的 space,然后做飞溅,但是,InkResponse 会用你正在寻找的圆形效果做飞溅,你需要稍微调整一下,但这是代码示例:


Material(
  child: Container(
    child: Center(
       child: InkResponse(
            focusColor: Colors.transparent,
            hoverColor: Colors.transparent,
            highlightColor: Colors.transparent,
            onTap: () {},
            child: Padding(
              padding: const EdgeInsets.all(30),
              child: Icon(Icons.home),
            ),
          ),
        ),
      ),
    )

| 墨池 | InkResponse 默认值 | InkResponse 自定义 |

Google Stadia 应用示例: Image 1 Image 2

注意:使用 Material Widget 作为 Row 的父级,因此效果可以扩展到所有行宽,并且限制条件为“radius: 40”

Container(
      width: double.infinity,
      height: 300,
      child: Material(
        color: Colors.transparent,
        child: Row(
          children: [
            Expanded(
              flex: 20,
              child: InkResponse(
                onTap: () {},
                //containedInkWell: false,
                splashFactory: InkRipple.splashFactory,
                radius: 40,
                splashColor: Colors.black12,
                highlightColor: Colors.transparent,
                child: Container(height: double.infinity, alignment: Alignment.center, child: Icon(Icons.search_rounded)),
              ),
            ),
            Expanded(
              flex: 20,
              child: InkResponse(
                onTap: () {},
                //containedInkWell: false,
                splashFactory: InkRipple.splashFactory,
                radius: 40,
                splashColor: Colors.black12,
                highlightColor: Colors.transparent,
                child: Container(height: double.infinity, alignment: Alignment.center, child: Icon(Icons.search_rounded)),
              ),
            ),
            Expanded(
              flex: 20,
              child: InkResponse(
                onTap: () {},
                //containedInkWell: false,
                splashFactory: InkRipple.splashFactory,
                radius: 40,
                splashColor: Colors.black12,
                highlightColor: Colors.transparent,
                child: Container(height: double.infinity, alignment: Alignment.center, child: Icon(Icons.search_rounded)),
              ),
            ),
            Expanded(
              flex: 20,
              child: InkResponse(
                onTap: () {},
                //containedInkWell: false,
                splashFactory: InkRipple.splashFactory,
                radius: 40,
                splashColor: Colors.black12,
                highlightColor: Colors.transparent,
                child: Container(height: double.infinity, alignment: Alignment.center, child: Icon(Icons.search_rounded)),
              ),
            ),
            Expanded(
              flex: 20,
              child: InkResponse(
                onTap: () {},
                //containedInkWell: false,
                splashFactory: InkRipple.splashFactory,
                radius: 40,
                splashColor: Colors.black12,
                highlightColor: Colors.transparent,
                child: Container(height: double.infinity, alignment: Alignment.center, child: Icon(Icons.search_rounded)),
              ),
            ),
          ],
        ),
      ),
    )
                                 FIRST WAY
    

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BottomNavigationBar in style Material Design 2',
      theme: ThemeData(primarySwatch: Colors.indigo),
      home: BottomNavigationMaterial2(),
    );
  }
}

class BottomNavigationMaterial2 extends StatefulWidget {
  const BottomNavigationMaterial2({Key? key}) : super(key: key);

  @override
  State<BottomNavigationMaterial2> createState() =>
      _BottomNavigationMaterial2State();
}

class _BottomNavigationMaterial2State extends State<BottomNavigationMaterial3> {
  Widget _bottomNavItem() {
    return InkWell(
      onTap: () {},
      radius: 93,
      splashColor: Color.fromARGB(124, 108, 130, 255),
      highlightColor: Colors.white,
      splashFactory: InkRipple.splashFactory,
      child: Center(child: Icon(Icons.search, size: 25)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      bottomNavigationBar: Container(
        height: 80,
        child: Row(
          children: <Widget>[
            Container(child: _bottomNavItem(), width: 196),
            Container(child: _bottomNavItem(), width: 196),
          ],
        ),
      ),
    );
  }
}
                                 SECOND WAY
    

theme: ThemeData(splashFactory: InkRipple.splashFactory),