I am currently using Flappy Search Bar for my Flutter app.
I got the search right, but I can't seem to find a example of customizing the SearchBarController for Flappy Search Bar.
I am trying to do a sort function, and the Flappy library says SearchBarController will do the job.
Any links or tutorials I can refer to?
It would be better if anyone has some code they did regarding this controller that I can learn from.
Any help would be much appreciated,
Thanks in advance ;)
You can copy paste run full code below
To do sort you can use sortList and pass a function
signature void sortList(int Function(T a, T b) sorting)
code snippet
_searchBarController.sortList((Post a, Post b) {
return a.body.compareTo(b.body);
});
working demo
full code
import 'dart:math';
import 'package:flappy_search_bar/flappy_search_bar.dart';
import 'package:flappy_search_bar/scaled_tile.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Post {
final String title;
final String body;
Post(this.title, this.body);
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final SearchBarController<Post> _searchBarController = SearchBarController();
bool isReplay = false;
Future<List<Post>> _getALlPosts(String text) async {
await Future.delayed(Duration(seconds: text.length == 4 ? 10 : 1));
if (isReplay) return [Post("Replaying !", "Replaying body")];
if (text.length == 5) throw Error();
if (text.length == 6) return [];
List<Post> posts = [];
var random = new Random();
for (int i = 0; i < 10; i++) {
posts.add(Post("$text $i", "body random number : ${random.nextInt(100)}"));
}
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SearchBar<Post>(
searchBarPadding: EdgeInsets.symmetric(horizontal: 10),
headerPadding: EdgeInsets.symmetric(horizontal: 10),
listPadding: EdgeInsets.symmetric(horizontal: 10),
onSearch: _getALlPosts,
searchBarController: _searchBarController,
placeHolder: Text("placeholder"),
cancellationWidget: Text("Cancel"),
emptyWidget: Text("empty"),
indexedScaledTileBuilder: (int index) => ScaledTile.count(1, index.isEven ? 2 : 1),
header: Row(
children: <Widget>[
RaisedButton(
child: Text("sort"),
onPressed: () {
_searchBarController.sortList((Post a, Post b) {
return a.body.compareTo(b.body);
});
},
),
RaisedButton(
child: Text("Desort"),
onPressed: () {
_searchBarController.removeSort();
},
),
RaisedButton(
child: Text("Replay"),
onPressed: () {
isReplay = !isReplay;
_searchBarController.replayLastSearch();
},
),
],
),
onCancelled: () {
print("Cancelled triggered");
},
mainAxisSpacing: 10,
crossAxisSpacing: 10,
crossAxisCount: 2,
onItemFound: (Post post, int index) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.body),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => Detail()));
},
),
);
},
),
),
);
}
}
class Detail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
Text("Detail"),
],
),
),
);
}
}
Related
I have a question about updating Android Emulator after pressing on an icon using setState()
this is my code:
import 'package:flutter/material.dart';
void main() {
return runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
title: Text('Dicee'),
backgroundColor: Colors.red,
),
body: DicePage(),
),
),
);
}
class DicePage extends StatefulWidget {
#override
_DicePageState createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
#override
Widget build(BuildContext context) {
int leftDiceNumber = 1;
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
leftDiceNumber = 5;
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
print('Right button got pressed.');
},
child: Image.asset('images/dice2.png'),
),
),
],
),
);
}
}
and I tried even multiple choices that I found in Stackoverflow , but nothing it's working...
this.setState(() {
leftDiceNumber = 5;
});
WidgetsBinding.instance.addPostFrameCallback((_) => setState(...));
insted of just setState() and didn't work
I want to change the value of leftDiceNumber = 5 when I click on the picture
the initialised value for leftDiceNumber is 1
Put the variable outside the build method.leftDiceNumber, else it will reset on every build.
class DicePage extends StatefulWidget {
#override
_DicePageState createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
int leftDiceNumber = 1; //here
#override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
leftDiceNumber = 5;
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
print('Right button got pressed.');
},
child: Image.asset('images/dice2.png'),
),
),
],
),
);
}
}
How am I supposed to pass a value in this big mess called Flutter?
30 years old php global $var wasn't good?
All these years were to come up with setState, passed in a controller which get redeclared as a key inside a stateful widget that receive the value from a Navigator?
By the way, I tried using Navigator.push but it seems to open a completely new window, the value is there but I'd need it to show in the tab body not in a new window, below is my code:
main.dart
import 'dart:core';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter App',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomeView(),
);
}
}
class HomeView extends StatefulWidget {
#override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
final tabs = [QRViewExample(), SecondView(res: '')];
int _currentIndex = 0;
#override
void initState() {
setState(() {});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 40.0,
elevation: 0,
centerTitle: true,
title: Text('Flutter App'),
),
body: tabs[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.red,
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white.withOpacity(0.5),
items: [
BottomNavigationBarItem(
icon: Icon(Icons.qr_code),
label: 'Scan',
),
BottomNavigationBarItem(
icon: Icon(Icons.list),
label: 'List',
),
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
// SECOND TAB WIDGET (custom)
class SecondView extends StatelessWidget {
const SecondView({Key? key, required this.res}) : super(key: key);
final String? res;
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(res!),
),
);
}
}
// FIRST TAB WIDGET (qrcode)
class QRViewExample extends StatefulWidget {
const QRViewExample({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _QRViewExampleState();
}
class _QRViewExampleState extends State<QRViewExample> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 500,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (result != null)
Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
else
const Text('Scan a code'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Text('Flash: ${snapshot.data}');
},
)),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.flipCamera();
setState(() {});
},
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data!)}');
} else {
return const Text('loading');
}
},
)),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.pauseCamera();
},
child: const Text('pause',
style: TextStyle(fontSize: 20)),
),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.resumeCamera();
},
child: const Text('resume',
style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
)
],
),
),
),
);
}
Widget _buildQrView(BuildContext context) {
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.cyanAccent,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
controller.pauseCamera();
setState(() {
result = scanData;
});
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondView(res: result!.code)))
.then((value) => controller.resumeCamera());
});
}
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
How am I supposed to pass a value in this big mess called Flutter?
With state management tools like InheritedWidget, InheritedModel, Provider, BloC and many more.
30 years old php global $var wasn't good? All these years were to come up with setState, passed in a controller which get redeclared as a key inside a stateful widget that receive the value from a Navigator?
Well, you shouldn't do that and it's not meant to be done like that. We can use several methods to propagate data down the widget tree. Let me explain this with InheritedWidget. But sometimes you want to go for Provider which is a wrapper class for InheritedWidget.
First we create a class named QRListModel which extends InheritedModel:
class QRListModel extends InheritedWidget {
final List<Barcode> qrList = []; // <- This holds our data
QRListModel({required super.child});
#override
bool updateShouldNotify(QRListModel oldWidget) {
return !listEquals(oldWidget.qrList, qrList);
}
static QRListModel of(BuildContext context) {
final QRListModel? result = context.dependOnInheritedWidgetOfExactType<QRListModel>();
assert(result != null, 'No QRListModel found in context');
return result!;
}
}
updateShouldNotify is a method we have to override to tell Flutter, when we want the widgets to rebuild. We want this to happen when the list changes. The of method is just a handy way to access the QRListModel.
Now wrap a parent widget of both the scan tab view and the list tab view inside QRListModel. We go for HomeView:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter App',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: QRListModel(child: HomeView()), // <- here!
);
}
}
We can take any parent widget but it should be a class where we don't call setState. Otherwise our QRListModel also gets rebuilt and our list is gone.
Now we can access QRListModel from anywhere inside the subtree. We need it here:
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
this.controller!.resumeCamera();
});
controller.scannedDataStream.listen((scanData) async {
controller.pauseCamera();
QRListModel.of(context).qrList.add(scanData); // <- Here we access the list
await showDialog(
context: context,
builder: (context) => SimpleDialog(
title: Text("Barcode was added!"),
children: [
Text(scanData.code!)
],
)
);
});
}
And here we read the list:
class SecondView extends StatelessWidget {
const SecondView({Key? key, required this.res}) : super(key: key);
final String? res;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: QRListModel.of(context).qrList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(QRListModel.of(context).qrList[index].code ?? "NO"),
),
);
}
);
}
}
Now both pages have access to the qr list. Please do mind that a InheritedWidget can only have final fields. So if you need mutable fields, you need an additional wrapper class. We don't need it as we don't change the list but only its elements.
By the way: You shouldn't call setState inside initState. You did this here:
class _HomeViewState extends State<HomeView> {
final tabs = [QRViewExample(), SecondView(res: '')];
int _currentIndex = 0;
#override
void initState() {
setState(() {}); // <- Don't call setState inside initState!
super.initState();
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auths/pages/searchservice.dart';
import 'package:flutter_auths/pages/tasks.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var queryResultSet = [];
var tempSearchStore = [];
initiateSearch(value) {
if (value.length == 0) {
setState(() {
queryResultSet = [];
tempSearchStore = [];
});
}
var capitalizedValue =
value.substring(0, 1).toUpperCase() + value.substring(1);
if (queryResultSet.length == 0 && value.length == 1) {
SearchService().searchByName(value).then((QuerySnapshot docs) {
for (int i = 0; i < docs.documents.length; ++i) {
queryResultSet.add(docs.documents[i].data);
}
});
} else {
tempSearchStore = [];
queryResultSet.forEach((element) {
if (element['Username'].startsWith(capitalizedValue)) {
setState(() {
tempSearchStore.add(element);
});
}
});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Firestore search'),
),
body: ListView(children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
onChanged: (val) {
initiateSearch(val);
},
decoration: InputDecoration(
prefixIcon: IconButton(
color: Colors.black,
icon: Icon(Icons.arrow_back),
iconSize: 20.0,
onPressed: () {
Navigator.of(context).pop();
},
),
contentPadding: EdgeInsets.only(left: 25.0),
hintText: 'Search by name',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0))),
),
),
SizedBox(height: 10.0),
GridView.count(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
crossAxisCount: 2,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0,
primary: false,
shrinkWrap: true,
children: tempSearchStore.map((element) {
return buildResultCard(element);
}).toList())
]));
}
}
Widget buildResultCard(data) {
return Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
elevation: 2.0,
child: Container(
child: Column(
children: <Widget> [ Text(data['Username'],
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 20.0,
),
),
RaisedButton(
onPressed: () {
Navigator.push(
data,
MaterialPageRoute(builder: (data) => ProfilePage()),
);
},
child: const Text('asd', style: TextStyle(fontSize: 12)),
),
]
)
)
);
}
Here I search for a user from database then it shows me the results in cards, I added a button and by clicking on it I want to navigate the page to another page but the following error occures.
this is the error and the app
So I want to click on specific user’s button and redirect the page to that user’s profile. How can I do that?
You are getting this error because instead of passing buildContext you are passing data.
So your error gets removed if you change you code from this
Navigator.push(
data,
MaterialPageRoute(builder: (data) => ProfilePage()),
);
to
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProfilePage(username: data['Username']))
);
This is how you should pass the data to the Profile Page.
Also
Widget buildResultCard(data)
be changed to
Widget buildResultCard(context, data)
and
buildResultCard(element);
to
buildResultCard(context, element);
First, you need to Navigate to that page with data like
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProfilePage(profileData: data))
);
then you need to receive that data
class ProfilePage extends StatefulWidget {
var profileData;
ProfilePage({this.profileData});
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(widget.profileData['username']),
),
);
}
}
You can pass and receive data in another way
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProfilePage(),settings: RouteSettings(arguments: data))
);
then
class ProfilePage extends StatefulWidget {
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
var profileData;
#override
Widget build(BuildContext context) {
profileData=ModalRoute.of(context).settings.arguments;
return Scaffold(
body: Center(
child: Text(profileData['username']),
),
);
}
}
whenever i enter a value in search bar i want to match it from the available list, for example if this is my list
List fooList = ['one', 'two', 'three', 'four', 'five']; and i enter e in search bar it should list those items which contains e in it. How can i do that, anybody please help.
class _HomeState extends State<HeaderWithSearchBox1> {
final SearchBarController<Post> _searchBarController = SearchBarController();
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = [];
var random = new Random();
for (int i = 0; i < 10; i++) {
posts
.add(Post("$text $i", "body random number : ${random.nextInt(100)}"));
}
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SearchBar<Post>(
minimumChars: 1,
searchBarPadding: EdgeInsets.symmetric(horizontal: 10),
headerPadding: EdgeInsets.symmetric(horizontal: 10),
listPadding: EdgeInsets.symmetric(horizontal: 10),
onSearch: _getALlPosts,
searchBarController: _searchBarController,
placeHolder: Center(
child: Text(
"PlaceHolder",
style: TextStyle(fontSize: 30),
)),
cancellationWidget: Text("Cancel"),
emptyWidget: Text("empty"),
onCancelled: () {
print("Cancelled triggered");
},
mainAxisSpacing: 10,
onItemFound: (Post post, int index) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.body),
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Detail()));
},
),
);
},
),
),
);
}
}
class Detail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: Center(child: Text("Detail", style: TextStyle(fontSize: 30),)),
),
);
}
}
You can copy paste run full code below
You filter fooList with where and use contains
code snippet
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = fooList
.where((element) =>
element.title.contains(text) || element.body.contains(text))
.toList();
return posts;
}
working demo
full code
import 'dart:math';
import 'package:flappy_search_bar/flappy_search_bar.dart';
import 'package:flappy_search_bar/scaled_tile.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Post {
final String title;
final String body;
Post(this.title, this.body);
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final SearchBarController<Post> _searchBarController = SearchBarController();
bool isReplay = false;
List<Post> fooList = [
Post('one', '1'),
Post('two', '2'),
Post('three', '3'),
Post('four', '4'),
Post('five', '5')
];
Future<List<Post>> _getALlPosts(String text) async {
List<Post> posts = fooList
.where((element) =>
element.title.contains(text) || element.body.contains(text))
.toList();
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SearchBar<Post>(
minimumChars: 1,
searchBarPadding: EdgeInsets.symmetric(horizontal: 10),
headerPadding: EdgeInsets.symmetric(horizontal: 10),
listPadding: EdgeInsets.symmetric(horizontal: 10),
onSearch: _getALlPosts,
searchBarController: _searchBarController,
placeHolder: Center(
child: Text(
"PlaceHolder",
style: TextStyle(fontSize: 30),
)),
cancellationWidget: Text("Cancel"),
emptyWidget: Text("empty"),
onCancelled: () {
print("Cancelled triggered");
},
mainAxisSpacing: 10,
onItemFound: (Post post, int index) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.body),
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Detail()));
},
),
);
},
),
),
);
}
}
class Detail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
Text("Detail"),
],
),
),
);
}
}
I have started to create a random math-app where the user first will be able to chose arithmetic. After that a random count for that arithmetic will show and the user will fill in the answer with a keyboard.
Now I'm not sure if putting each arithmetic in a class of its own (and get the random numbers there) is the best way, or if there is a better way?
I have tried to add all arithmetic choices to one class but I can't get it to work. I would somehow have to pass each choice to the right calculation in the same class.
I was thinking like with a calculator but you put in the arithmetic first - on a separate page. Would this even work?
Is it possible to get the outputs from each class gathered to one class, so that I only have to create one keyboard (even if I use keyboard.numbers)?
As I see it (but I can be dead wrong), the cons with different classes and different keybords is the size of the app.
The pros on the other hand is the possibilities to style every arithmetic class different from the other.
The code below is not finished, but it works and hopefulle gives you an idea of what I am trying to do.(I have used images for the arithmetics - added to pubspec.yaml)
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math';
void main() {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]) //to make the app in portait mode
.then((_) {
//to let it load in portrait mode before launch
runApp(new MyApp());
});
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "SOME MATH",
theme: ThemeData(primarySwatch: Colors.red),
home: MyHomeScreen(),
);
}
}
class MyHomeScreen extends StatefulWidget {
#override
_MyHomeScreenState createState() => _MyHomeScreenState();
}
class _MyHomeScreenState extends State<MyHomeScreen> {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.red,
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
//To make the appBar invisible
elevation: 0.0,
leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
//tapable without action
title: Text(
"MATH",
style: TextStyle(fontSize: 25.0),
),
),
body: ListView(
//would listView.builder be better?
children: <Widget>[
GestureDetector(
//could be changed to inkWell
child: _ArithmeticCard(
headImageAssetPath: 'assets/plus.png',
),
onTap: () {
//make it pass to stateful
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => new MyPlus()));
},
),
GestureDetector(
child: _ArithmeticCard(
headImageAssetPath: 'assets/minus.png',
),
onTap: () {
//new taps to different classes
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => new MyMinus()));
},
),
GestureDetector(
child: _ArithmeticCard(
headImageAssetPath: 'assets/times.png',
),
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => new MyTimes()));
},
),
GestureDetector(
child: _ArithmeticCard(
headImageAssetPath: 'assets/division.png',
),
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => new MyDivision()));
},
),
],
),
),
);
}
}
class _ArithmeticCard extends StatelessWidget {
final String headImageAssetPath;
_ArithmeticCard({this.headImageAssetPath});
//creating Card
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom:
10.0),
child: Card(
elevation: 10.0,
child: Column(
children: <Widget>[
Image.asset(
headImageAssetPath,
width: double.infinity,
height: 150.0,
fit: BoxFit.cover,
),
],
),
),
);
}
}
class MyPlus extends StatefulWidget {
//class for adding
#override
_MyPlusState createState() => _MyPlusState();
}
class _MyPlusState extends State<MyPlus> {
final random = Random();
int a, b, sum;
String output;
void changeData() {
setState(() {
a = random.nextInt(10);
b = random.nextInt(10);
sum = a + b;
output = "$a + $b = ";
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
"$output",
style: TextStyle(fontSize: 48.0),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.amber, //just playing with colors
child: Icon(Icons.refresh, color: Colors.white),
onPressed: changeData,
),
);
}
}
class MyMinus extends StatefulWidget {
//class for subtraktion
#override
_MyMinusState createState() => _MyMinusState();
}
class _MyMinusState extends State<MyMinus> {
final random = Random();
int a, b, sum;
String output;
void changeData() {
setState(() {
a = random.nextInt(10);
b = random.nextInt(10);
if (a >= b) {
sum = a - b;
output = "$a - $b =";
} else {
//Don't want the sum to be negative
sum = b - a;
output = "$b - $a =";
}
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
"$output",
style: TextStyle(fontSize: 48.0),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.lime,
child: Icon(Icons.refresh, color: Colors.black),
onPressed: changeData,
),
);
}
}
class MyTimes extends StatefulWidget {
#override
_MyTimesState createState() => _MyTimesState();
}
class _MyTimesState extends State<MyTimes> {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.purpleAccent),
child: Text("This is my times"),
);
}
}
class MyDivision extends StatefulWidget {
#override
_MyDivisionState createState() => _MyDivisionState();
}
class _MyDivisionState extends State<MyDivision> {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.limeAccent,
),
child: Text("This is my division"),
);
}
}
Any help or advice here is very appreciated. Thank you.