Import Libraries
Import the necessary libraries. dart:math provides random functions, and flutter/material.dart is essential for building Flutter UI components.
import 'dart:math' as math;
import 'package:flutter/material.dart';
Create the Main SwipeAndWin Widget
Define the main SwipeAndWin widget as a StatefulWidget to handle dynamic state changes during user interactions.
class SwipeAndWin extends StatefulWidget {
const SwipeAndWin({Key? key}) : super(key: key);
@override
State<SwipeAndWin> createState() => _SwipeAndWinState();
}
Define the State and Animation Controller
Create private state variables to track drag position, game status, score, and messages. The AnimationController handles animations when the user interacts.
class _SwipeAndWinState extends State<SwipeAndWin> with SingleTickerProviderStateMixin {
late AnimationController _controller;
double _dragPosition = 0;
bool _isWon = false;
int _score = 0;
String _message = '';
}
Initialize the Animation Controller
In initState, initialize _controller with an 800ms animation duration and add a listener to rebuild the widget whenever animation values change.
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_controller.addListener(() => setState(() {}));
}
Dispose of the Animation Controller
Dispose of _controller in dispose() to release resources when the widget is removed from the widget tree.
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Handle User Dragging and Animation Triggering
_onDragUpdate updates _dragPosition while ensuring itβs within a range.
_onDragEnd checks if the drag was far enough to trigger the win condition, then randomly determines a win or loss. It also resets the drag position after animation.
void _onDragUpdate(DragUpdateDetails details) {
setState(() {
_dragPosition += details.delta.dx;
_dragPosition = _dragPosition.clamp(-180.0, 180.0); // Limit drag range
});
}
void _onDragEnd(DragEndDetails details) {
if (_dragPosition.abs() > 100) {
final bool won = math.Random().nextBool();
setState(() {
_isWon = won;
if (_isWon) {
_score += 10;
_message = 'π WIN! π';
} else {
_message = math.Random().nextInt(3) == 0 ? 'Better luck next time!' : 'π’ Try Again!';
}
});
_controller.forward(from: 0.0);
Future.delayed(const Duration(milliseconds: 800), () {
if (mounted) {
setState(() {
_dragPosition = 0;
});
}
});
} else {
setState(() {
_dragPosition = 0;
});
}
}
Build the UI Layout
Use Scaffold to set the background color and organize UI elements.
Add a GestureDetector to capture horizontal drag gestures and apply a 3D transformation based on _dragPosition.
An AnimatedBuilder widget dynamically animates the size and opacity changes based on the _controller values.
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[100],
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Score: $_score',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
const SizedBox(height: 10),
const Text(
'Swipe to Try Your Luck!',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
const SizedBox(height: 40),
GestureDetector(
onHorizontalDragUpdate: _onDragUpdate,
onHorizontalDragEnd: _onDragEnd,
child: Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(_dragPosition / 180 * math.pi),
alignment: Alignment.center,
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.scale(
scale: 1.0 + (_controller.value * 0.2),
child: Opacity(
opacity: 1.0 - (_controller.value * 0.5),
child: Container(
width: 200,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Center(
child: _controller.value > 0
? Text(
_message,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: _isWon ? Colors.green : Colors.red,
),
)
: const Icon(
Icons.card_giftcard,
size: 80,
color: Colors.blue,
),
),
),
),
);
},
),
),
),
],
),
),
);
}
Run the App
Set up main() to run the SwipeAndWin widget inside MaterialApp and display it. This launches the swipe-to-win app.
void main() {
runApp(const MaterialApp(
home: SwipeAndWin(),
));
}