I am making a puzzle with hexagonal tiles that the user can rotate and reorder to reach the solution. I would like the tile that is dragged and dropped and the tile that is originally in the dropping position to swap places. I guess that I should use the Draggable class wrapped in DragTarget, but I didn't manage even to have the DragTarget accept the Draggable, let alone that there is a widget swap. Here is the code (now with only two tiles in one row, but there will be more in three rows):
import 'package:flutter/material.dart';
import 'package:hexagon/hexagon.dart';
class Puzzle extends StatefulWidget {
const Puzzle({super.key});
@override
State<Puzzle> createState() => _PuzzleState();
}
class _PuzzleState extends State<Puzzle> {
bool isOnTarget = false;
String imageName = "";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Row(
children: [
DragTarget<String>(
builder: (context, candidateData, rejectedData) {
return PuzzleTile(image: isOnTarget ? imageName : "assets/images/1.png");
},
onAcceptWithDetails: (DragTargetDetails<String> image) {
setState(() {
isOnTarget = true;
imageName = image.data;
});
},
),
DragTarget<String>(
builder: (context, candidateData, rejectedData) {
return PuzzleTile(image: isOnTarget ? imageName : "assets/images/2.png");
},
onAcceptWithDetails: (image) {
setState(() {
isOnTarget = true;
imageName = image.data;
});
},
),
],
)
],
)
)
);
}
}
class PuzzleTile extends StatefulWidget {
final String image;
const PuzzleTile({super.key, required this.image});
@override
State<PuzzleTile> createState() => _PuzzleTileState();
}
class _PuzzleTileState extends State<PuzzleTile> {
double angle = 0.0;
late final String image;
void _changeRotation() {
setState(() => angle += 1.0 / 6.0);
}
@override
void initState(){
super.initState();
image = widget.image;
}
@override
Widget build(BuildContext context) {
return Draggable(
data: image,
feedback: HexagonWidget.pointy(
color: Colors.black,
width: 100,
elevation: 8,
child: GestureDetector(
child: AnimatedRotation(
turns: angle,
duration: const Duration(milliseconds: 200),
child: Image.asset(image)),
onTap: () {
setState(() {
_changeRotation();
});
},
),
),
child: HexagonWidget.pointy(
color: Colors.black,
width: 100,
elevation: 8,
child: GestureDetector(
child: AnimatedRotation(
turns: angle,
duration: const Duration(milliseconds: 200),
child: Image.asset(image)),
onTap: () {
setState(() {
_changeRotation();
});
},
),
),
);
}
}