Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Flutter: Increase hitbox of GestureDetector

I am fairly new to flutter and currently trying to create a NavBar.
It looks like this:
enter image description here

If I click on the icon, the bar moves to the selected one and the content changes.
However, I have to hit the icon perfectly. I would like to have a "box" around it, so I can tap just near it. Basically divide the space into 3.

I tried the following:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  Widget build(BuildContext context) {
    return Container(
      height: 60,
      color: Color(0xff282424),
      child: Stack(
        children: [
          Container(
            child: Row(
              children: items.map((x) => createNavBarItem(x)).toList(),
            ),
          ),
          AnimatedContainer(
            duration: Duration(milliseconds: 200),
            alignment: Alignment(active.offset, 0.7),
            child: AnimatedContainer(
              duration: Duration(milliseconds: 400),
              height: 5,
              width: 50,
              decoration: BoxDecoration(
                  color: active.color,
                  borderRadius: BorderRadius.circular(2.5)),
            ),
          ),
        ],
      ),
    );
  }


  Widget createNavBarItem(MenuItem item) {
    double width = MediaQuery.of(context).size.width;
    return SizedBox(
      width: width / items.length,
      height: 55,
      child: GestureDetector(
        child: Icon(
          Icons.access_time,
          color: item.color,
          size: 30,
        ),
        onTap: () {
          setState(() {
            active = item;
            navBarUpdate(item);
          });
        },
      ),
    );
  }

The items should take 1/3 of the width. It isn’t working that way tho. Any idea on how to increase the "tappable" space?

EDIT

Full code:

import 'package:flutter/material.dart';

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

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

  // This widget is the root of your application.\
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var screens = [Text("Button1"), Text("Button2"), Text("Button3")];
  int currentScreen = 0;

  void changeIndex(int index) => setState(() {
        currentScreen = index;
      });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.orange,
        child: Stack(
          children: [
            SafeArea(child: screens[currentScreen]),
            Container(
                alignment: Alignment.bottomCenter, child: NavBar(changeIndex))
          ],
        ),
      ),
    );
  }
}

class MenuItem {
  final String name;
  final Color color;
  final double offset;

  MenuItem(this.name, this.color, this.offset);
}

class NavBar extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => NavBarState(navBarUpdate);

  late Function(int) navBarUpdate;

  NavBar(this.navBarUpdate);
}

class NavBarState extends State<NavBar> {
  var items = [
    MenuItem("Test", Colors.red, -0.76),
    MenuItem("Test2", Colors.green, 0),
    MenuItem("Test3", Colors.yellow, 0.76)
  ];

  late MenuItem active;
  late Function(MenuItem) navBarUpdate;

  @override
  void initState() {
    super.initState();
    active = items[0];
  }

  NavBarState(Function(int) navBarUpdate) {
    this.navBarUpdate = (item) {
      navBarUpdate(items.indexOf(item));
    };
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      color: Color(0xff282424),
      child: Stack(
        children: [
          Container(
            child: Row(
              children: items.map((x) => createNavBarItem(x)).toList(),
            ),
          ),
          AnimatedContainer(
            duration: Duration(milliseconds: 200),
            alignment: Alignment(active.offset, 0.7),
            child: AnimatedContainer(
              duration: Duration(milliseconds: 400),
              height: 5,
              width: 50,
              decoration: BoxDecoration(
                  color: active.color,
                  borderRadius: BorderRadius.circular(2.5)),
            ),
          ),
        ],
      ),
    );
  }

  Widget createNavBarItem(MenuItem item) {
    double width = MediaQuery.of(context).size.width;
    return SizedBox(
      width: width / items.length,
      height: 55,
      child: GestureDetector(
        child: Icon(
          Icons.access_time,
          color: item.color,
          size: 30,
        ),
        onTap: () {
          setState(() {
            active = item;
            navBarUpdate(item);
          });
        },
      ),
    );
  }
}

>Solution :

You can use behavior: HitTestBehavior.translucent, or opaque on createNavBarItem

child: GestureDetector(
  behavior: HitTestBehavior.translucent,

You can swap your GestureDetector on top level widget from Icon.

 Widget createNavBarItem(MenuItem item) {
    double width = MediaQuery.of(context).size.width;
    return GestureDetector(
      child: Container(
        color: Colors.transparent,
        width: width / items.length,
        height: 55,
        child: Icon(
          Icons.access_time,
          color: item.color,
          size: 30,
        ),
      ),
      onTap: () {
        setState(() {
          active = item;
          navBarUpdate(item);
        });
      },
    );
  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading