Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Flutter is it possible to increase the transparency of a Dismissible widget the further it is dismissed?

I have a Dismissible widget in my application that I drag down to dismiss. There is a requirement that the transparency of the Dismissible should increase the further it is dragged down. So it should look as if it is fading out as it is dismissed. If it were to be dragged back up, its transparency should decrease.

As a simple test I tried wrapping the Dismissible in a Listener and Opacity widget. The opacity value is set to a variable tracked in state. The Listener widget listens to the total "y" axis movement of the Dismissible and when it reaches a certain threshold, decreases the the opacity value tracked in state. See code below for example:

import 'package:flutter/material.dart';

class FadingDismissible extends StatefulWidget {
  @override
  _FadingDismissible createState() => _FadingDismissible();
}

class _FadingDismissible extends State<FadingDismissible> {
  double _totalMovement = 0;
  double _opacity;

  @override
  void initState() {
    super.initState();
    _opacity = 1.0;
  }

  _setOpacity(double opacityValue) {
    setState(() {
      _opacity = opacityValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerMove: (PointerMoveEvent event) {
        _totalMovement += event.delta.dy;
        if (_totalMovement > 200) {
          _setOpacity(0.5);
        }
      },
      onPointerUp: (PointerUpEvent event) {
        _setOpacity(1.0);
        _totalMovement = 0;
      },
      child: Opacity(
        opacity: _opacity,
        child: Dismissible(
          direction: DismissDirection.down,
          key: UniqueKey(),
          onDismissed: (direction) {
            Navigator.pop(context);
          },
          child: Scaffold(
            floatingActionButton: FloatingActionButton(
              onPressed: () {},
            ),
            body: Container(color: Colors.blue),
          ),
        ),
      ),
    );
  }
}

The issue is, whenever the state is set, the widget is re-built and the Dismissible jumps back to the top.

Right now I'm not sure of another way around this. Is there a way to change the transparency of a Dismissible widget as it is dragged? Or will I have to use a different widget altogether?

Thanks!

like image 752
magee05 Avatar asked Dec 03 '19 15:12

magee05


People also ask

How do you increase opacity in flutter?

Flutter uses a 32 bit color value in ARGB format, where A = Alpha, R = RED, G = GREEN and B = BLUE. So to control the opacity you can change the values of first two digits of the hex value in const Color(0xFF0E3311) , you can use values ranging from 0x000E3311 , 0x010E3311 .... 0xFF0E3311 . Hope that helps!

What is opacity widget in flutter?

The Opacity widget that makes its child partially transparent. This class colors its child into an intermediate buffer and then merges the child back into the scene partially transparent.

How do you dismiss a widget in flutter?

A widget that can be dismissed by dragging in the indicated direction. Dragging or flinging this widget in the DismissDirection causes the child to slide out of view.

What is key in dismissible flutter?

Customizing Dismissible WidgetThe key (Key) and the child (Widget) are the required fields for the constructor. The key becomes an important role because the widget can be removed from the widget list. The child is a major role because it shows where we need to pass the widget that can be dismissed.


1 Answers

I think might be the closest if you do not want to create your own Dismissible widget:

class FadingDismissible extends StatefulWidget {
  final String text;
  FadingDismissible({@required this.text});

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

class _FadingDismissibleState extends State<FadingDismissible> {
  double opacity = 1.0;
  StreamController<double> controller = StreamController<double>();
  Stream stream;

  double startPosition;

  @override
  void initState() {
    super.initState();
    stream = controller.stream;
  }

  @override
  void dispose() {
    super.dispose();
    controller.close();
  }

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: GlobalKey(),
      child: StreamBuilder(
        stream: stream,
        initialData: 1.0,
        builder: (context, snapshot) {
          return Listener(
            child: Opacity(
              opacity: snapshot.data,
              child: Text(widget.text),
            ),
            onPointerDown: (event) {
              startPosition = event.position.dx;
            },
            onPointerUp: (event) {
              opacity = 1.0;
              controller.add(opacity);
            },
            onPointerMove: (details) {
              if (details.position.dx > startPosition) {
                var move = details.position.dx - startPosition;
                move = move / MediaQuery.of(context).size.width;

                opacity = 1 - move;

                controller.add(opacity);
              }
            },
          );
        },
      ),
    );
  }
}
like image 78
Snieder Avatar answered Oct 07 '22 17:10

Snieder