David Peters
David Peters

Reputation: 929

Flutter circular ripple effect: How to build beautiful material BottomNavigationBar

As the Google stadia app is made with flutter I was wondering how they achieved the much more beautiful ripple animation on their BottomNavigationBar.

Example:

enter image description here

How did they achieve the custom ripple animation?

Edit: Simple custom 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)),
    );
  }
}

Upvotes: 9

Views: 9107

Answers (4)

Amine LAHRIM
Amine LAHRIM

Reputation: 796

Google Stadia App Example: Image 1 Image 2

NB: Use Material Widget as parent of the Row so the effect can be expanded over all the row width and with a limit condition of "radius: 40"

Also this example it's just simple code no offense to SOLID pattern..etc

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)),
              ),
            ),
          ],
        ),
      ),
    )

Upvotes: 8

MrFlutterBoy
MrFlutterBoy

Reputation: 1

                                 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),

Upvotes: 0

Bilaal Abdel Hassan
Bilaal Abdel Hassan

Reputation: 1379

You might want to use the InkResponse Class in your BottomNavigationBar :)

Edited from InkWell to InkResponse.

Upvotes: 0

Mariano Zorrilla
Mariano Zorrilla

Reputation: 7686

The Ink you're looking for is InkResponse and not InkWell. InkWell fills the entire available space with a highlight and then do the splash but, InkResponse does the splash with that circular effect you're looking for, you need to tweak it a bit, but this is the code example:


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),
            ),
          ),
        ),
      ),
    )

| InkWell | InkResponse Default | InkResponse Custom |

Upvotes: 22

Related Questions