I'm trying to make an animation of sorting algorithms in flutter. So far I've coded the algorithm and managed to get some sort of animation by iterating once at a time instead of the whole sorting process but you have to keep tapping the button to sort, one item at a time. I've been trying to look for a way to animate this process. Here's my code:
import 'package:flutter/material.dart';
import 'dart:math';
List<double> rectHeights = new List<double>();
int n = 2;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sorting',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
int _selectedIndex = 0;
final _widgetOptions = [
Text('Index 0: Sort'),
Text('Index 1: Shuffle'),
];
@override
void initState() {
super.initState();
Random random = new Random();
for (int i = 0; i < 35; i++) {
double ranNum = random.nextDouble() * 600;
rectHeights.add(ranNum);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.all(8.0),
child: Center(
child: Row(
children: rectangles(),
),
),
),
bottomNavigationBar: BottomNavigationBar(
iconSize: 50.0,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.sort), title: Text('Sort', style: TextStyle(fontSize: 20.0),)),
BottomNavigationBarItem(icon: Icon(Icons.shuffle), title: Text('Shuffle', style: TextStyle(fontSize: 20.0),)),
],
currentIndex: _selectedIndex,
fixedColor: Colors.blue,
onTap: _onItemTapped,
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
switch(_selectedIndex) {
case 0:
setState(() {
insertSortOnce(rectHeights, 1);
});
break;
case 1:
setState(() {
shuffle(rectHeights);
n = 2;
});
}
}
}
List<Widget> rectangles() {
List<Widget> rects = new List<Widget>();
for (double height in rectHeights) {
var rect = Padding(
padding: EdgeInsets.symmetric(horizontal: 1.0),
child: Container(
width: 8.0,
height: height,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.blue
),
),
);
rects.add(rect);
}
return rects;
}
void insertSort(values, choice) {
int i, j;
double key, temp;
for (i = 1; i < values.length; i++) {
key = values[i];
j = i - 1;
switch (choice) {
case 1:
while (j >= 0 && key < values[j]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
case 2:
while (j >= 0 && key > values[j]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
}
}
}
void insertSortOnce(values, choice) {
int i, j;
double key, temp;
for (i = 1; i < n; i++) {
key = values[i];
j = i - 1;
switch (choice) {
case 1:
while (j >= 0 && key < values[j]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
case 2:
while (j >= 0 && key > values[j]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
}
}
n++;
}
List shuffle(List items) {
var random = new Random();
// Go through all elements.
for (var i = items.length - 1; i > 0; i--) {
// Pick a pseudorandom number according to the list length
var n = random.nextInt(i + 1);
var temp = items[i];
items[i] = items[n];
items[n] = temp;
}
return items;
}
Solution 1: Mazin Ibrahim
You can use a Future
function with a short delay, for example (one second) to call the insertSort()
after each second till the rectHeights
are sorted:
var _notSorted = true ;
var _shiftNotPressed = true ;
Future sortRectangles() async {
while(_notSorted & _shiftPressed) { // You have to provide a condition to know when to stop
await new Future.delayed(const Duration(seconds: 1), () {
insertSortOnce(rectHeights, 1);
}
);
}
}
Then checking for shuffling:
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
switch(_selectedIndex) {
case 0:
setState(() {
insertSortOnce(rectHeights, 1);
});
break;
case 1:
_shiftNotPressed = false ; // This is what you should add
setState(() {
shuffle(rectHeights);
n = 2;
});
}
}
Then Sorting completion:
void insertSortOnce(values, choice) {
_notSorted = false ; // if it didn't execute the loop it means sorted
int i, j;
double key, temp;
for (i = 1; i < n; i++) {
key = values[i];
j = i - 1;
switch (choice) {
case 1:
while (j >= 0 && key < values[j]) {
_notSorted = true ; //You should figure a more efficient way to do this
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
case 2:
while (j >= 0 && key > values[j]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
j--;
}
break;
}
}
n++;
}
Also, You should include in your condition whether the shift button is pressed and to terminate accordingly.