Can I get the same effect in flutter as the <TouchableOpacity /> in React Native?

3,247

Solution 1

@Shan Liu you are correct that InkWell has its own "splash" effect which makes the rectangle or square you mentioned.

If you don't want that splash effect, use GestureDetector.

In below example, I put a Text inside a GestureDetector, but you can put your widget there instead:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'InkWell Demo';

    return MaterialApp(
      title: title,
      home: MyHomePage(title: title),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(child: MyButton()),
    );
  }
}

class MyButton extends StatefulWidget {
  @override
  MyButtonState createState() {
    return MyButtonState();
  }
}

class MyButtonState extends State<MyButton> {
  bool isTappedDown = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
      },
      onTapDown: (tapDownDetails) {
        setState(() {
          isTappedDown = true;
        });
      },
      onTapUp: (tapUpDetails) {
        setState(() {
          isTappedDown = false;
        });
      },
      child: Text(
        'Flat Button',
        style: TextStyle(
            fontSize: 30,
            fontWeight: FontWeight.bold,
            color: isTappedDown ? Colors.black.withOpacity(0.5) : Colors.black),
      ),
    );
  }
}

Solution 2

Use the code below:

import 'package:flutter/material.dart';

class TouchableOpacity extends StatefulWidget {
  final Widget child;
  final Function onTap;
  final Duration duration = const Duration(milliseconds: 50);
  final double opacity = 0.5;

  TouchableOpacity({@required this.child, this.onTap});

  @override
  _TouchableOpacityState createState() => _TouchableOpacityState();
}

class _TouchableOpacityState extends State<TouchableOpacity> {
  bool isDown;

  @override
  void initState() {
    super.initState();
    setState(() => isDown = false);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) => setState(() => isDown = true),
      onTapUp: (_) => setState(() => isDown = false),
      onTapCancel: () => setState(() => isDown = false),
      onTap: widget.onTap,
      child: AnimatedOpacity(
        child: widget.child,
        duration: widget.duration,
        opacity: isDown ? widget.opacity : 1,
      ),
    );
  }
}

Usage:

TouchableOpacity(
  child: ....
  onTap: () {....}
)

Solution 3

I think you'll need to combine a gesture detector and an opacity animation. I couldn't find a ready to use example. But here is the example for opacity animation. Flutter opacity animation

Share:
3,247
Shan Liu
Author by

Shan Liu

Updated on December 09, 2022

Comments

  • Shan Liu
    Shan Liu over 1 year

    I found that in React Native, when using component, pressing the corresponding area can have a opacity effect. In flutter, we sure can use InkWell widget, but i don't want a rectangle or square. Can we implement the same result using flutter. Cheers!

  • Shan Liu
    Shan Liu about 5 years
    That's one way to go. Cheers mate.
  • Shan Liu
    Shan Liu about 5 years
    updates - if you tap on the text but release somewhere else. it would cause some side effects