Feedback property of Draggable widget is not animating

772 views Asked by At

I need to animate a Draggable widget while it is in motion. The animation depends on the global position coordinates of the widget being dragged. I've used a Listener to get the finger tap position but the problem is that the feedback widget of the Draggable widget is not updating with setState. I found this, this, this and this link but none of them helped. Here's the code to demonstrate my problem.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  double x = 0, y = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Listener(
        onPointerMove: (opm) {
          setState(() {
            x = opm.position.dx;
            y = opm.position.dy;
          });
          print('(${x.floor()}, ${y.floor()})');
        },
        child: Center(
          child: Draggable(
            childWhenDragging: Container(),
            child: Container(
              height: 150,
              width: 150,
              color: Colors.red,
            ),
            feedback: Material(
              child: Container(
                height: 150,
                width: 150,
                color: Colors.blue,
                child: Center(child: Text('(${x.floor()}, ${y.floor()})')),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

In this case, the coordinates displayed inside the blue screen should animate but even after doing a setState they don't update. I tried using AnimatedBuilder but there was no difference. It would be really helpful if someone could provide me with some help or an alternative method for achieving this with the Draggable widget.

1

There are 1 answers

2
Ashutosh Singh On

I don't understand this part fully but with pskink's help and with some documentations I was able to achieve this animation using the following code.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  double x = 0, y = 0;

  AnimationController _controller;

  Animation animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
    animation = Tween(begin: 0, end: 100).animate(_controller);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Listener(
        onPointerMove: (opm) {
          setState(() {
            x = opm.position.dx;
            y = opm.position.dy;
            _controller.value = 0;
          });
          print('(${x.floor()}, ${y.floor()})');
        },
        child: Center(
          child: Draggable(
            childWhenDragging: Container(),
            child: Container(
              height: 150,
              width: 150,
              color: Colors.red,
            ),
            feedback: AnimatedBuilder(
              animation: animation,
              builder: (_, __) {
                return Material(
                  child: Container(
                    height: 150,
                    width: 150,
                    color: Colors.blue,
                    child: Center(child: Text('(${x.floor()}, ${y.floor()})')),
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

Please comment if you have any better way of doing this or if you'd like to add some extra information or explanations.