10

I am using flutter and i have a container with the shape of a circle using this code

new Container(
 width: 50.0,
  height: 50.0,
   decoration: new BoxDecoration(
   shape: BoxShape.circle)

I want to make this circle move on the screen like this

enter image description here

how can I do this?

4 Answers4

11

Here it is:

import 'package:flutter/material.dart';

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Drag app"),
        ),
        body: HomePage(),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomePageState();
  }
}

class _HomePageState extends State<HomePage> {
  double width = 100.0, height = 100.0;
  Offset position ;

  @override
  void initState() {
    super.initState();
    position = Offset(0.0, height - 20);
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          left: position.dx,
          //top: position.dy - height + 20,
          child: Draggable(
            child: Container(
              width: width,
              height: height,
              color: Colors.blue,
              child: Center(child: Text("Drag", style: Theme.of(context).textTheme.headline,),),
            ),
            feedback: Container(
              child: Center(
                child: Text("Drag", style: Theme.of(context).textTheme.headline,),),
              color: Colors.red[800],
              width: width,
              height: height,
            ),
            onDraggableCanceled: (Velocity velocity, Offset offset){
              setState(() => position = offset);
            },
          ),
        ),
      ],
    );
  }
}
Ali Tavana
  • 358
  • 2
  • 5
4

What you are looking for is Draggable widget. You can then handle the translation using onDraggableCanceled which is passed and offset that you can be used to update the placement

onDraggableCanceled :(velocity,offset){ 
//update the position here
} 

Update

After checking the image you will need "Drop me here" part to be a DragTarget that has a method onAccept which will handles the logic when you drag and drop your Draggable

asherbret
  • 5,439
  • 4
  • 38
  • 58
Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
3

First, wrap your Container inside the Stack with Positioned.

Then, use Pan Gesture to implement a Pan in your Container and use onPan... methods to handle Pan Gesture

Here is code:

Offset position;

@override
  void initState() {
    super.initState();
    position = Offset(10, 10);
  }    

@override
    Widget build(BuildContext context) {

        double _width = MediaQuery.of(context).size.width;
        double _height = _width * 9 / 16;


        return GestureDetector(
          onPanStart: (details) => _onPanStart(context, details),
          onPanUpdate: (details) => _onPanUpdate(context, details, position),
          onPanEnd: (details) => _onPanEnd(context, details),
          onPanCancel: () => _onPanCancel(context),

          child: SafeArea(
            child: Stack(
              children: <Widget>[
                Positioned(
                  top: position.dy,
                  child: Container(
                    color: Colors.red,
                    width: _width,
                    height: _height,
                  ),
                ),
              ],
            ),
          ),
        );
      }

      void _onPanStart(BuildContext context, DragStartDetails details) {
        print(details.globalPosition.dy);

      }

      void _onPanUpdate(BuildContext context, DragUpdateDetails details, Offset offset) {
        setState(() {
          position = details.globalPosition;
        });
      }

      void _onPanEnd(BuildContext context, DragEndDetails details) {
        print(details.velocity);
      }

      void _onPanCancel(BuildContext context) {
        print("Pan canceled !!");
      }

Hope this helps!

ANDYNVT
  • 531
  • 4
  • 19
2

You can use Draggable class for dragging the item which you want to drag and for placing it or sticking it to somewhere on the screen you have to wrap that item with DragTarget class. In DragTarget class onAccept method is there where you can write the logic. You can also take a reference to my code here it is

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.indigo,
      ),
      home: new MyHomePage(title: 'Flutter Demo Drag Box'),
    );
  }
}

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

  final String title;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(title),
      ),
      body:
          new DragGame(), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class DragGame extends StatefulWidget {
  @override
  _DragGameState createState() => new _DragGameState();
}

class _DragGameState extends State<DragGame> {
  int boxNumberIsDragged;

  @override
  void initState() {
    boxNumberIsDragged = null;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
        constraints: BoxConstraints.expand(),
        color: Colors.grey,
        child: new Stack(
          children: <Widget>[
            buildDraggableBox(1, Colors.red, new Offset(30.0, 100.0)),
            buildDraggableBox(2, Colors.yellow, new Offset(30.0, 200.0)),
            buildDraggableBox(3, Colors.green, new Offset(30.0, 300.0)),
          ],
        ));
  }

  Widget buildDraggableBox(int boxNumber, Color color, Offset offset) {
    return new Draggable(
      maxSimultaneousDrags: boxNumberIsDragged == null || boxNumber == boxNumberIsDragged ? 1 : 0,
      child: _buildBox(color, offset),
      feedback: _buildBox(color, offset),
      childWhenDragging: _buildBox(color, offset, onlyBorder: true),
      onDragStarted: () {
        setState((){
          boxNumberIsDragged = boxNumber;
        });
      },
      onDragCompleted: () {
        setState((){
          boxNumberIsDragged = null;
        });
      },
      onDraggableCanceled: (_,__) {
        setState((){
          boxNumberIsDragged = null;
        });
      },
    );
  }

  Widget _buildBox(Color color, Offset offset, {bool onlyBorder: false}) {
    return new Container(
      height: 50.0,
      width: 50.0,
      margin: EdgeInsets.only(left: offset.dx, top: offset.dy),
      decoration: BoxDecoration(
          color: !onlyBorder ? color : Colors.grey,
          border: Border.all(color: color)),
    );
  }
}
Rishabh
  • 2,410
  • 4
  • 17
  • 36