Hi I have a screen for adding images. I use the multi_image_picker for picking the images. Upon selection of the images, all images picked will be shown in a grid view with a FloatingActionButton on top of each image for removal of each image. The problem is, when I click the button for removing an image, the last image is removed not the one I clicked on. Has anyone experienced this?
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:krakatoa/api/FileApi.dart';
import 'package:krakatoa/components/AssetView.dart';
import 'package:krakatoa/config/Themes.dart' as themes;
import 'package:krakatoa/mixins/SnackBarMixin.dart';
import 'package:krakatoa/podos/User.dart';
import 'package:krakatoa/utils/Common.dart' as common;
import 'package:multi_image_picker/multi_image_picker.dart';
class AddImageScreen extends StatefulWidget {
final List<String> currentImageUrls;
final String postUrl;
AddImageScreen({this.currentImageUrls, #required this.postUrl});
#override
State<StatefulWidget> createState() => _AddImageState();
}
class _AddImageState extends State<AddImageScreen> with SnackBarMixin {
List<Asset> _images = [];
User _user;
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text('Add images'),
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.only(bottom: 10),
child: Text(
"Upload Images:",
style: Theme.of(context).textTheme.headline,
),
),
Container(
padding: EdgeInsets.only(bottom: 10),
child: GridView.count(
shrinkWrap: true,
crossAxisSpacing: 3,
mainAxisSpacing: 3,
crossAxisCount: 3,
children: _renderPickedImages(),
),
),
Container(
child: FlatButton(
child: Text('UPLOAD'),
padding: EdgeInsets.symmetric(vertical: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
color: themes.primaryColor,
onPressed: _onUploadBtnPress,
),
),
],
),
),
);
}
#override
void dispose() {
super.dispose();
for (var image in _images) {
image.release();
}
}
#override
void initState() {
super.initState();
common.getCurrentUser().then((user) {
if (user != null) {
_user = user;
} else {
_user = User();
}
});
}
void showProgressAlert() {
showDialog(
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
content: ListTile(
leading: CircularProgressIndicator(
value: null,
),
title: Text('Processing...'),
),
),
);
},
barrierDismissible: false,
);
}
void _onAddImageBtnPress() async {
List<Asset> resultList;
try {
resultList = await MultiImagePicker.pickImages(maxImages: 5, enableCamera: true);
} on PlatformException catch (e) {
debugPrint("AddImageScreen._onAddImageBtnPress: ${e.toString()}");
}
if (!mounted) return;
if (resultList.isNotEmpty) {
setState(() {
_images.addAll(resultList);
});
}
}
void _onUploadBtnPress() {
if (_images.isNotEmpty) {
showProgressAlert();
_uploadImages();
} else {
showSnackBarMessage("No images to upload", seconds: 5);
}
}
void _removeImage(int index, Asset image) {
debugPrint("INDEX: $index");
debugPrint("Orig Image: ${_images[index].hashCode}");
setState(() {
_images.removeAt(index);
});
}
List<Widget> _renderPickedImages() {
List<Widget> imageWidgets = [];
imageWidgets.add(InkWell(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.grey,
),
),
child: Center(
child: Icon(
Icons.add,
size: 60,
color: Colors.grey,
),
),
),
onTap: _onAddImageBtnPress,
));
var ctr = 0;
for (var image in _images) {
imageWidgets.add(Container(
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
AssetView(image),
Positioned(
bottom: 0,
right: 0,
child: _ImageRemoveButton(
index: ctr,
removeItem: _removeImage,
image: image,
),
),
],
),
));
ctr++;
}
return imageWidgets;
}
Future<void> _uploadImages() async {
if (_user.id <= 0) {
showSnackBarMessage("User is not logged in");
Navigator.of(context).pop("User is not logged in");
return;
}
try {
await FileApi.uploadImages(widget.postUrl, _images);
Navigator.of(context).pop();
Navigator.of(context).pop("Success");
} on Exception catch (e) {
debugPrint(e.toString());
showSnackBarMessage(e.toString());
Navigator.of(context).pop(e.toString());
}
}
}
class _ImageRemoveButton extends StatelessWidget {
final Function removeItem;
final Asset image;
final int index;
_ImageRemoveButton({this.removeItem, this.index, this.image});
#override
Widget build(BuildContext context) {
return FloatingActionButton(
backgroundColor: Colors.white,
mini: true,
heroTag: "ImageAction_$index",
isExtended: false,
child: Icon(
Icons.close,
size: 15,
color: Colors.black,
),
onPressed: _onPress,
);
}
void _onPress() {
debugPrint("${this.hashCode}");
debugPrint("Passed Image: ${image.hashCode}");
removeItem(index, image);
}
}
add key: Key(YOUR_LIST.length.toString()),
having KEY helps with the update of the ListView
that worked for me on ListView.builder
Related
I am using flutter river pods for this project. I want to change the API call when pressing on the second and third tab. I.e make the JSON API link dynamic. How can I do that?
Each widget is in its different file
Here is my code
main.dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: true,
home: HomeView(),
);
}
}
Home_views.dart
class HomeView extends ConsumerWidget {
const HomeView({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
TabController controller;
final ModelView = ref.watch(getFutureData);
return Consumer(
builder: (context, WidgetRef ref, _) {
return TabBarWidget;
}
);
}
}
Data_model.dart
class DataModel {
const DataModel({
required this.id,
required this.joke,
required this.categories,
});
final int id;
final String joke;
final String categories;
}
data_controllers.dart
final getFutureData = ChangeNotifierProvider<GetApiDATA>((ref) => GetApiDATA());
class GetApiDATA extends ChangeNotifier{
List<DataModel> ListOfDataModels = [];
GetApiDATA(){
getDataApi();
}
Future getDataApi() async {
ListOfDataModels = [];
try{
http.Response ApiResponse = await http.get(Uri.parse("https://v2.jokeapi.dev/joke/Programming?type=single&contains=joke&amount=10"));
if (ApiResponse.statusCode == 200) {
final body = jsonDecode(ApiResponse.body) as Map<String, dynamic>;
if (body['error'] == false) {
final jokes = body['jokes'];
for (final joke in jokes) {
final jokeMap = joke as Map<String, dynamic>;
print("jokeText is ${jokeMap['joke']}");
final id = jokeMap['id'] as int;
final jokeText = jokeMap['joke'] as String;
final categories = jokeMap['category'] as String;
ListOfDataModels.add(DataModel(id: id, joke: jokeText, categories: categories));
}
print("Length is ${ListOfDataModels.length}");
notifyListeners();
}
}
}
catch(e)
{
print(e.toString());
}
}
}
TabBarWidget.dart
import 'package:assignment_moe/Controllers/data_controllers.dart';
import 'package:assignment_moe/Widgets/TabViewWidget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
Widget TabBarWidget = Consumer(
builder: (context, WidgetRef ref, _) {
final ModelView = ref.watch(getFutureData);
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
backgroundColor: Color(0XffF7F7F7),
appBar: AppBar(
backgroundColor: Color(0xff1B9C8F),
title: Text('Jokes API'),
),
body: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 30, left: 10,right: 10),
height: 35,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white,
),
child: TabBar(
indicator: BoxDecoration(
color: Color(0xff1B9C8F),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
labelColor: Colors.white,
unselectedLabelColor: Color(0xff1B9C8F),
tabs: [
Tab(
text: 'Programming',
),
Tab(
text: 'Dark',
),
Tab(
text: 'Spooky',
),
],
),
),
Expanded(
child: TabBarView(
children: [
TabViewWidget,
TabViewWidget,
TabViewWidget,
],
),
),
],
),
),
),
);
}
);
TabViewWidget.dart
import 'package:assignment_moe/Controllers/data_controllers.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
Widget TabViewWidget = Consumer (
builder: (context, WidgetRef ref, _) {
final ModelView = ref.watch(getFutureData);
return ModelView.ListOfDataModels.isEmpty ?
Center(child: CircularProgressIndicator(),) :
ListView.builder(
itemCount: ModelView.ListOfDataModels.length,
itemBuilder: (context, index) =>
Container(
margin: EdgeInsets.only(top: 20,left: 20,right: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white,
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListTile(
title: Text(ModelView.ListOfDataModels[index].categories
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(ModelView.ListOfDataModels[index].joke),
),
leading: Container(
alignment: Alignment.center,
width: 35,
height: 35,
decoration: BoxDecoration(
color: Color(0xff1B9C8F),
borderRadius: BorderRadius.circular(20)),
child: Text(
ModelView.ListOfDataModels[index].id.toString(),
style: TextStyle(color: Colors.white),
),
),
),
),
),
);
}
);
Below is the screen shot
ANy help would be appreciated
I resolved my current issue regarding locking and unlocking buttons. I am basing my levels on the marks the user got. If they got a score of 25 and above, they will proceed to the next level.
Now the problem here is since my quiz is sharing one code with a different JSON file, when the user perfects the score on the first stage, the whole level will unlock which is a no-no. The idea is even they scored perfect, the next stage will be unlocked not the whole level. I tried thinking of ways on how to do it but nothing comes to my mind.
Here is my Quiz Page:
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:baybay_app/Quiz/NextLevel class.dart';
import 'package:baybay_app/Quiz/QuizHome.dart';
import 'package:baybay_app/Quiz/ResultPage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Quizjson extends StatelessWidget {
String roundName;
bool isComplete = false;
Quizjson(this.roundName, mark);
String assettoload;
int question;
// a function
// sets the asset to a particular JSON file
// and opens the JSON
setasset() {
if (roundName == 'Easy Round') {
assettoload ='assets/Sample.json';
} else if (roundName == 'Average Round') {
assettoload = 'assets/Medium.json';
} else if (roundName == 'Hard Round') {
assettoload = 'assets/Hard.json';
}else {
assettoload = 'assets/Intermediate.json';
}
}
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future: DefaultAssetBundle.of(context).loadString(assettoload, cache: false),
builder: (context, snapshot){
List mydata = json.decode(snapshot.data.toString());
if(mydata == null){
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
}else{
return quizpage(mydata: mydata);
}
}
);
}
}
class quizpage extends StatefulWidget {
String langname;
var mydata;
quizpage({Key key, #required this.mydata}): super(key: key);
#override
_quizpageState createState() => _quizpageState(mydata);
}
class _quizpageState extends State<quizpage> {
var mydata;
_quizpageState(this.mydata);
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(20.0),
alignment: Alignment.bottomLeft,
child: Text(mydata[0][question.toString()])
),
),
Expanded(
flex: 6,
child: Container(
child: Column(
children: [
Row(
children:[
ChoiceButton("a"),
ChoiceButton("b")
]
),
Row(
children: [
ChoiceButton("c"),
ChoiceButton("d"),
]
)
]
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 20.0
),
),
),
),
),
],
)
);
}
Widget ChoiceButton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 10.0),
child: MaterialButton(
onPressed: ()=>CheckAnswer(k),
child: Text(
mydata[1][question.toString()][k],
style: TextStyle(
color: Colors.white
)),
color: btncolor[k],
),
);
}
Color colorsToShow = Colors.brown[700];
Color right = Colors.greenAccent[700];
Color wrong = Colors.redAccent[700];
int mark = 0;
int question = 1;
int timer = 30;
String showtimer = "30";
bool canceltimer = false;
bool isComplete = false;
Map<String,Color> btncolor = {
"a" : Colors.brown[700],
"b" : Colors.brown[700],
"c" : Colors.brown[700],
"d" : Colors.brown[700],
};
#override
void initState(){
starttimer();
super.initState();
}
#override
void setState(fn){
if(mounted){
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t){
setState(() {
if(timer < 1){
t.cancel();
NextQuestion();
}
else if(canceltimer==true){
t.cancel();
}
else{
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void NextQuestion(){
canceltimer = false;
timer = 30;
setState(() {
if(question< 10){
question++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => ResultPage(mark: mark),
));}
btncolor["a"] = Colors.brown[700];
btncolor["b"] = Colors.brown[700];
btncolor["c"] = Colors.brown[700];
btncolor["d"] = Colors.brown[700];
isComplete = true;
});
starttimer();
}
void CheckAnswer(String k) {
if(mydata[2][question.toString()] == mydata[1][question.toString()][k]){
mark = mark+5;
colorsToShow = right;
}
else{
colorsToShow = wrong;
}
setState(() {
btncolor[k] = colorsToShow;
});
Timer(Duration(seconds: 2), NextQuestion);
}
}
Here is my Quiz Home:
import 'package:baybay_app/Quiz/QuizTracingSound.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:baybay_app/Quiz/QuizTracingSound.dart';
class QuizHome extends StatefulWidget {
int mark = 0;
QuizHome({ #required this.mark });
#override
_QuizHomeState createState() => _QuizHomeState(mark);
}
class _QuizHomeState extends State<QuizHome> {
createAlertDialouge(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 25 above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
createAlertDialougeOne(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 35 and above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
createAlertDialougeTwo(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 35 and above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
int mark = 0 ;
_QuizHomeState(this.mark);
String langname;
bool isComplete = false;
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
List <String> images = [
'assets/Ba.gif',
'assets/GA.PNG',
'assets/HA.PNG',
'assets/SA.PNG'
];
return Scaffold(
appBar: AppBar(
title: Text('Quiz Home '),
),
body:ListView(
children: <Widget>[
FlatButton(
child: CustomCard('Easy Round', images[0], des[1], isComplete, Colors.green, mark),
onPressed: () {
{ Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Easy Round", mark = 5),
));}
}
),
SizedBox(
height: 20.0,
),
FlatButton(
child: CustomCard('Average Round', images[1], des[1], isComplete, lockOrNot, mark),
onPressed: _onPressedOne,
),
SizedBox(
height: 20.0,
),
FlatButton(
onPressed: _onPressedTwo,
child: CustomCard('Hard Round', images[2],des[2], isComplete, btncolor, mark)
),
SizedBox(
height: 20.0,
),
FlatButton(
onPressed: _onPressedThree,
child: CustomCard('Intermediate Round', images[3],des[3], isComplete, btncolor, mark )
),
],
)
);
}
List <String> des = [
"The easy round lets you test your knowledge in determining letters. Are you up for the challenge? Click here!!!",
"Do you want to step up your baybayin game? Let's see if you can distinguish words! Click here!!!",
"Do you know how to construct sentences with the use of Baybayin? Click here!!!",
"Masters of baybayin can only enter this quiz! Are you one of them? Click Here!!!",
];
Color btncolor;
Widget CustomCard(String roundName,images,String des, bool isComplete, Color btncolor, int mark ) {
return Material(
color: btncolor,
elevation: 10.0,
borderRadius: BorderRadius.circular(20.0),
child: Container(
child: Column(
children: <Widget>[
Text(
'$mark'
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
),
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(100.0),
child: Container(
height: 200.0,
width: 200.0,
child:ClipOval(
child: Image(
image: AssetImage(images),
),
)
),
),
),
Center(
child: Text( roundName,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
letterSpacing: 10.0,
fontFamily: 'S'
),),
),
Container(
padding:EdgeInsets.all(8.0),
child: Text(
des,
style: TextStyle(
color: Colors.white,
letterSpacing: 1.0
),
),
),
],
),
),
);
}
Color unlockColor = Colors.green;
Color lockColor = Colors.grey;
Color lockOrNot = Colors.grey;
void _onPressedOne() {
int marks1 = 24;
if(marks1< mark){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson( "Average Round", 7 ),
));
}
else{
createAlertDialouge(context);
}
}
void _onPressedTwo() {
int marks2 = 34;
int marc = mark;
if( marks2 < marc ){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Hard Round", 7 ),
));
}
else{
createAlertDialougeOne(context);
}
}
void _onPressedThree() {
int marks3 = 49;
int marc = mark;
if( marks3 < marc ){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Average Round", 8),
));
}
else{
createAlertDialougeTwo(context);
}
}
}
If you need the Result page:
import 'package:baybay_app/Quiz/QuizHome.dart';
import 'package:flutter/material.dart';
class ResultPage extends StatefulWidget {
int mark;
ResultPage({Key key, #required this.mark}) : super(key: key);
#override
_ResultPageState createState() => _ResultPageState(mark);
}
class _ResultPageState extends State<ResultPage> {
List<String> images = [
'assets/excellent.jpg',
'assets/good.png',
'assets/Sorry.png'
];
String message;
String image;
#override
void initState(){
if(mark<5){
image = images[2];
message = 'Try Again..\n' + 'You scored $mark';
}
else if(mark==5){
image = images[1];
message = 'Good.. \n' + 'You scored $mark';
}
else{
image = images[0];
message = 'Excellent!!!...\n' + 'You scored $mark';
}
}
int mark;
_ResultPageState(this.mark);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Result"
)
),
body: Column(
children:[
Expanded(
flex: 6,
child: Material(
elevation: 5.0,
child: Container(
child:Column(
children: [
Material(
child: Container(
width: 300.0,
height: 300.0,
child: ClipRect(
child: Image(
image: AssetImage(
image,
)
)
),
),
),
Center(
child: Text(
message,
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Staatliches'
),
),
)
],
),
),
),
),
Expanded(
flex:4,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
OutlineButton(
onPressed: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> QuizHome(mark:mark)));
},
child: Text(
'Continue',
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Staatliches'
)
),
padding: EdgeInsets.symmetric(vertical: 10.0,horizontal: 15.0),
borderSide: BorderSide(width: 3.0,color: Colors.brown[700])
)
],
)
)
]
)
);
}
}
What can I try next?
Everyone I am new in flutter. How can create loading screen on login page. when i click on login button then it should be redirect on Dashboard with loading screen. I am trying to create loading screen in flutter. When I click on login button then loading screen show be show and after loading screen it should be redirect on Dashboard.....
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutternew/dashboard.dart';
import 'package:flutternew/forget_password.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'bezierContainer.dart';
class Home extends StatefulWidget {
Home({Key key, this.title}) : super(key: key);
final String title;
#override
_HomeState createState() => _HomeState();
}
class ShowLoading extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Loading View'),
),
body: Center(
child: _circularProgressIndicator(),
));
}
Widget _circularProgressIndicator() {
return CircularProgressIndicator();
}
}
class _HomeState extends State<Home> {
bool _isLoading = false;
GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: '_homekey');
final _scaffoldKey = GlobalKey<ScaffoldState>();
String _email;
String _password;
final TextEditingController emailController = new TextEditingController();
final TextEditingController passwordController = new TextEditingController();
var modal = Container();
showAlertDialog(BuildContext context, String message) {
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
AlertDialog alert = AlertDialog(
title: Text("Error"),
content: Text(message),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Widget _formSetupWidget(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
controller: emailController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Username",
hintStyle: TextStyle(color: Colors.grey, fontSize: 25),
fillColor: Color(0xFFFAFAfA),
filled: true),
keyboardType: TextInputType.emailAddress,
validator: (val) {
if (val.length == 0)
return "Please enter email";
else if (!val.contains("#"))
return "Please enter valid email";
else
return null;
},
onSaved: (val) => _email = val,
),
SizedBox(
height: 15,
),
TextFormField(
controller: passwordController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Password",
hintStyle: TextStyle(color: Colors.grey, fontSize: 25),
fillColor: Color(0xFFFAFAfA),
filled: true),
obscureText: true,
validator: (val) {
if (val.length == 0)
return "Please enter password";
else if (val.length <= 5)
return "Your password should be more then 6 char long";
else
return null;
},
onSaved: (val) => _password = val,
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
),
ButtonTheme(
minWidth: 500.0,
height: 60.0,
child: RaisedButton(
child: new Text("Login",
style: TextStyle(color: Colors.white, fontSize: 23.0)),
color: Colors.blueAccent,
highlightColor: Colors.blueAccent,
onPressed: () {
if (emailController.text != " " ||
passwordController.text != " ") {
signIn(emailController.text, passwordController.text);
}
},
),
),
],
),
);
}
signIn(String email, pass) async {
int visible = 0;
final sharedPreferences = await SharedPreferences.getInstance();
Map data = {'email': email, 'password': pass};
var jsonResponse = null;
var response = await http
.post("https://abcdef.com/iot/api/login", body: data);
if (response.statusCode == 200) {
jsonResponse = json.decode(response.body);
if (jsonResponse != null) {
if (jsonResponse['success'] == 1) {
sharedPreferences.setString("token", jsonResponse['data']['token']);
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) => Dashboard()),
(Route<dynamic> route) => false);
} else {
String message = jsonResponse['message'];
showAlertDialog(context, message);
}
}
} else {
setState(() {
_isLoading = false;
});
print(response.body);
}
}
#override
Widget build(BuildContext context) {
Center(
child: SpinKitWave(color: Colors.white, type: SpinKitWaveType.start),
);
var assetsImage = new AssetImage('assets/logo.png');
var image = new Image(image: assetsImage, width: 150.0, height: 150.0);
final height = MediaQuery.of(context).size.height;
return Scaffold(
body: Container(
height: height,
color: Colors.white,
child: Stack(
children: <Widget>[
Positioned(
top: -height * .15,
right: -MediaQuery.of(context).size.width * .4,
child: BezierContainer()),
Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 70),
new Center(
child: image,
),
SizedBox(height: 20),
_formSetupWidget(context),
Container(
padding: EdgeInsets.symmetric(vertical: 10),
alignment: Alignment.centerRight,
child: FlatButton(
child: Text("Forgot Password?"),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) =>
Forget_password()),
(Route<dynamic> route) => false);
},
),
),
SizedBox(height: height * .055),
],
),
),
),
],
),
));
}
}
Create class
class LoaderDialog {
static Future<void> showLoadingDialog(BuildContext context, GlobalKey key) async {
var wid = MediaQuery.of(context).size.width / 2;
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 130 , right: 130),
child: Dialog(
key: key,
backgroundColor: Colors.white,
child: Container(
width: 60.0,
height: 60.0,
child: Image.asset(
'images/loaderOld.gif',
height: 60,
width: 60,
),
)
),
);
},
);
}
}
How to Call:
In your Class(Where you want to show the loader).
final GlobalKey<State> _LoaderDialog = new GlobalKey<State>();
// Show
LoaderDialog.showLoadingDialog(context, _LoaderDialog);
// Hide
Navigator.of(_LoaderDialog.currentContext,rootNavigator: true).pop();
In the code below, I seek to make users vote only once in my Voting App.
At the moment users can vote more than once. I have created hasVoted field(a map with the UID of users and true as a value to indicate the user has voted) in the item being voted for as shown in my Firestore backend, however this does not seem to work as i want it to. What could be wrong. Does anyone here know a way around this?
Please i am new to flutter and dart so kindly forgive petty mistake that i make in posting this question
Below is my code
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:compuvote/models/finance_model.dart';
import 'package:compuvote/routes/home_page.dart';
import 'package:compuvote/routes/transitionroute.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class FinanceResult extends StatefulWidget {
#override
_FinanceResultState createState() {
return _FinanceResultState();
}
}
class _FinanceResultState extends State<FinanceResult> {
List<charts.Series<Record, String>> _seriesBarData;
List<Record> mydata;
_generateData(mydata) {
_seriesBarData = List<charts.Series<Record, String>>();
_seriesBarData.add(
charts.Series(
domainFn: (Record record, _) => record.name.toString(),
measureFn: (Record record, _) => record.totalVotes,
//colorFn: (Record record, _) => record.color,
id: 'Record',
data: mydata,
// Set a label accessor to control the text of the arc label.
labelAccessorFn: (Record row, _) => '${row.name}: ${row.totalVotes}',
colorFn: (_, __) => charts.MaterialPalette.cyan.shadeDefault,
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Finance Result'),
leading: IconButton(
icon: Icon(Icons.home),
onPressed: () {
Navigator.push(context, TransitionPageRoute(widget: HomePage()));
},
),
),
body: Container(
color: Colors.grey.shade100,
child: _buildBody(context),
));
}
/// ****** This code is suppose to build the body ***********/
Widget _buildBody(BuildContext context) {
return Column(
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('finance').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: LinearProgressIndicator(
valueColor: AlwaysStoppedAnimation(
Theme.of(context).primaryColor,
),
),
);
} else {
List<Record> finance = snapshot.data.documents
.map((documentSnapshot) =>
Record.fromMap(documentSnapshot.data))
.toList();
return _buildChart(context, finance);
}
},
),
],
);
}
Widget _buildChart(BuildContext context, List<Record> recorddata) {
mydata = recorddata;
_generateData(mydata);
return Padding(
padding: EdgeInsets.all(8.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 1.2,
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Expanded(
child: charts.PieChart(
_seriesBarData,
animate: true,
animationDuration: Duration(seconds: 3),
//For adding labels to the chart
defaultRenderer: new charts.ArcRendererConfig(
strokeWidthPx: 2.0,
arcWidth: 100,
arcRendererDecorators: [
// <-- add this to the code
charts.ArcLabelDecorator(
labelPosition: charts.ArcLabelPosition.auto,
labelPadding: 3,
showLeaderLines: true,
insideLabelStyleSpec: charts.TextStyleSpec(
color: charts.Color.white,
fontSize: 12,
),
outsideLabelStyleSpec: charts.TextStyleSpec(
color: charts.Color.black,
fontSize: 12,
),
),
]),
),
),
Container(
width: MediaQuery.of(context).size.width / 3.5,
height: 1,
color: Colors.black38,
),
Expanded(
child: Scaffold(
backgroundColor: Colors.grey.shade100,
body: _castVote(context),
),
),
],
),
),
),
);
}
/// ****** This code is suppose to link to the Firestore collection ***********/
Widget _castVote(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('finance').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(
child: LinearProgressIndicator(
valueColor: AlwaysStoppedAnimation(
Theme.of(context).primaryColor,
),
),
);
return _buildList(context, snapshot.data.documents);
},
);
}
/// ****** This code is suppose to build the List ***********/
Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
return ListView(
padding: const EdgeInsets.only(top: 20.0),
// ignore: missing_return
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
);
}
/// ****** This code is suppose to build the List Items ***********/
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record = Record.fromSnapshot(data);
return Padding(
key: ValueKey(record.name),
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Card(
elevation: 2,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade100),
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text(record.name),
trailing: Text(record.totalVotes.toString()),
onTap: () => {
_checkHasVoted(context, data),
}
//onTap: () => {record.reference.updateData({'votes': record.votes + 1}),
),
),
),
);
}
/// ****** This code is suppose to force users to vote only once ***********/
Widget _checkHasVoted(BuildContext context, DocumentSnapshot data) {
final record = Record.fromSnapshot(data);
StreamSubscription<DocumentSnapshot> subscription;
final DocumentReference documentReference =
Firestore.instance.collection("finance").document() as DocumentReference;
#override
void initState() {
super.initState();
subscription = documentReference.snapshots().listen((datasnapshot) {
if ((datasnapshot.data
.containsKey(FirebaseAuth.instance.currentUser()))) {
setState(() {
return Text("Sorry you have voted in this category already");
});
}
else if (!datasnapshot.data.containsKey(FirebaseAuth.instance.currentUser())){
setState(() {
record.reference.updateData({'votes':record.totalVotes + 1});
});
}
});
}
}
}
How i get focus of virtual keyboard rather than normal keyboard on textfiled .
heres the code
import 'dart:async';
import 'package:android/GlobalVariables.dart' as globals;
import 'package:flutter/material.dart';
import 'package:localstorage/localstorage.dart';
import 'Confirm.dart';
import 'package:virtual_keyboard/virtual_keyboard.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/services.dart';
import 'HomeScreen.dart';
void bh(context) async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
print("Connected to Mobile Network");
} else if (connectivityResult == ConnectivityResult.wifi) {
print("Connected to WiFi");
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Center(
child: Text(
"Connectivity ",
style: TextStyle(fontSize: 15),
),
),
actions: <Widget>[
Center(
child: Text(
"Please Check your Internet Connection",
style: TextStyle(fontSize: 15),
)),
FlatButton(
child: Text(
'ok',
style: TextStyle(fontSize: 15),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
}
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => new _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
LocalStorage userKey = new LocalStorage('userKey');
TextEditingController pinNumber = new TextEditingController();
bool hasKey;
var userKeyValue;
void showInSnackBar(String message) {
scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
}
#override
void initState() {
super.initState();
bh(context);
}
void checkKey() async {
userKeyValue = await userKey.getItem('userKey');
print(userKeyValue);
if (userKeyValue == null) {
hasKey = false;
} else {
hasKey = true;
}
}
void sendDataNav(BuildContext context) {
String textToSend = pinNumber.text;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Confirm(text: textToSend),
));
}
var study_no;
var select_mon;
LocalStorage mon = LocalStorage('mon');
LocalStorage studyNumber = LocalStorage('UserstudyNumber');
void start(context) async {
select_mon = DateTime.now().toString().substring(5, 7);
print("study number $study_no");
if (study_no == null) {
print("in $study_no");
Future.delayed(Duration.zero, () {
Navigator.pushNamed(context, '/setting');
});
} else {
print(select_mon);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(stu: study_no, mon: select_mon),
));
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
key: scaffoldKey,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width,
color: globals.primaryColor,
child: Image.asset('image/asset/Logob.png'),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
width: MediaQuery.of(context).size.width,
child: TextField(
controller: pinNumber,
style: new TextStyle(
fontSize: 20.0,
),
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 20),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.green, style: BorderStyle.solid),
borderRadius: new BorderRadius.horizontal(),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: globals.primaryColor,
style: BorderStyle.solid),
borderRadius: new BorderRadius.horizontal(),
),
//icon: Icon(Icons.calendar_today,),
hintText: 'PIN', suffixStyle: TextStyle(fontSize: 10),
labelText: 'Enter Your Pin',
),
// Navigator.pushNamed(context, '/afterCalender')
// keyboardType: TextInputType.number,
// autofocus: true,
onSubmitted: (ss) async {
if (pinNumber.text.length < 1) {
showInSnackBar("Enter Pin");
print('invalid');
return;
}
userKeyValue = await userKey.getItem('userKey');
if (userKeyValue == null) {
hasKey = false;
} else {
hasKey = true;
}
if (hasKey) {
if (userKeyValue != pinNumber.text) {
// show error message
showInSnackBar("Wrong Pin");
print('not valid');
} else {
print('valid');
study_no =
studyNumber.getItem('UserstudyNumber').toString();
start(context);
showInSnackBar("Sucessful");
}
} else {
if (pinNumber.text.length != 4) {
showInSnackBar("Enter Pin of 4 Numbers");
// show error message of length
print('hello');
} else {
setState(() {
sendDataNav(context);
});
// userKey.setItem('userKey', pinNumber.text);
}
}
},
),
),
),
VirtualKeyboard(
height: 300,
fontSize: 15,
textColor: Colors.black,
type: VirtualKeyboardType.Numeric,
onKeyPress: (key) => print(key.text)),
],
),
),
);
}
}
How i get focus of virtual keyboard rather than normal keyboard on textfiled .
onclick on textfiled i want system keyboard disabled and virtual keyboard to get focus and allow to add data..........................................................................................................................................................................................................................
When the onKeyPress callback get fired, you can set the text using the pinNumber text controller.