How to refresh a listview from another widget in flutter? - flutter

I am new to flutter, and I am trying to refresh my list of files after adding a file in my PDF app. Listview and add button I am using are in different widgets. Refresh function I have used is working for the delete button which is in the same widget as listview and gives error for the add button which is in a different widget from the List view. In both instances ,I am trying to update the List view.
`
class ListFiles extends StatefulWidget {
const ListFiles({Key? key}) : super(key: key);
#override
State<ListFiles> createState() => _ListFilesState();
}
class _ListFilesState extends State<ListFiles> {
final storage = FirebaseStorage.instance;
late Future<ListResult> futureFiles;
String pathPDF = "";
final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
#override
void initState() {
super.initState();
futureFiles = FirebaseStorage.instance.ref('files').listAll();
}
#override
Widget build(BuildContext context) => SizedBox(
height: 450,
child: RefreshIndicator(
onRefresh: onRefresh,
child: FutureBuilder<ListResult>(
future: futureFiles,
builder: (context, snapshot) {
if (snapshot.hasData) {
final files = snapshot.data!.items;
return ListView.builder(
itemCount: files.length,
itemBuilder: (context, index) {
final file = files[index];
return ListTile(
title: Text(file.name),
onTap: () async {
String url = await getFirebaseDownUrl(file);
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) =>
Scaffold(
appBar: AppBar(
title: Text(file.name),
backgroundColor: Colors.red,
),
body: SfPdfViewer.network(
url,
key: _pdfViewerKey,
)
),
),
);
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
onPressed: () {
_dialogBuilder(context, file);
},
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
],
),
);
}
);
} else if (snapshot.hasError) {
return Column(
children: [
ListTile(
leading: const Icon(
Icons.error,
color: Colors.redAccent,
),
title: const Text('Error occurred'),
trailing: IconButton(
onPressed: () {
setState(() {
onRefresh();
});
},
icon: const Icon(
Icons.refresh,
color: Colors.blue,
),
),
),
],
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
),
);
Future<String> getFirebaseDownUrl(Reference ref) async {
print(await ref.getDownloadURL());
return ref.getDownloadURL();
}
Future downloadFile(Reference ref) async {
List<int> textBytes = utf8.encode('{$ref}');
Uint8List data = Uint8List.fromList(textBytes);
String mimeType = "application/pdf";
DocumentFileSavePlus.saveFile(data, ref.name, mimeType);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Downloaded ${ref.name} successfully')),
);
}
Future deleteFile(Reference ref) async {
// Create a reference to the file to delete
final storageRef = FirebaseStorage.instance.ref();
final deleteRef = storageRef.child(ref.fullPath);
// Delete the file
await deleteRef.delete();
// setState(() {
// futureFiles = FirebaseStorage.instance.ref('files').listAll();
// });
// build(context);
onRefresh();
// WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text('Deleted file ${ref.name}')),
SnackBar(
content: Row(
children: [
Text('${ref.name} deleted successfully'),
const Spacer(
flex: 2,
),
TextButton(
onPressed: () {
onRefresh();
},
child: const Text(
'Refresh',
style: TextStyle(color: Colors.blue),
),
),
],
),
),
);
}
Future<void> _dialogBuilder(BuildContext context, Reference file) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Warning'),
content: const Text('Are you sure you want to delete the file?'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('NO', style: TextStyle(color: Colors.green)),
),
TextButton(
onPressed: () {
Navigator.of(context).pop();
deleteFile(file);
},
child:
const Text('YES', style: TextStyle(color: Colors.redAccent)),
),
],
);
},
);
}
Future onRefresh() async {
print('Page refreshing...');
setState(() {
futureFiles = FirebaseStorage.instance.ref('files').listAll();
print('Status updated...');
});
build(context);
// ListFiles();
print('Page refreshed...');
}
}
class AddButton extends StatefulWidget {
const AddButton({Key? key}) : super(key: key);
#override
State<AddButton> createState() => _AddButtonState();
}
class _AddButtonState extends State<AddButton> {
PlatformFile? pickedFile;
UploadTask? uploadTask;
late Future<ListResult> futureFiles;
#override
Widget build(BuildContext context) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
backgroundColor: const Color(0xFFFF1D1D),
foregroundColor: Colors.white,
onPressed: () async {
addFile();
},
child: const Icon(Icons.add),
),
),
],
);
}
Future addFile() async {
final result = await FilePicker.platform.pickFiles();
if (result == null) return;
setState(() {
pickedFile = result.files.first;
});
uploadFile();
}
Future uploadFile() async {
final path = 'files/${pickedFile!.name}';
final file = File(pickedFile!.path!);
final ref = FirebaseStorage.instance.ref().child(path);
final _ListFilesState Listfile = new _ListFilesState();
setState(() {
uploadTask = ref.putFile(file);
});
setState(() {
uploadTask = null;
});
if (pickedFile != null) {
addtoFirestore();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const Text('File uploaded successfully!'),
const Spacer(
flex: 2,
),
TextButton(
onPressed: () => Listfile.onRefresh(),
child: const Text(
'Refresh',
style: TextStyle(color: Colors.blue),
),
),
],
),
),
);
}
}
`
This is the response msg I get when refresh button of the snackbar is clicked.
enter image description here
Is this implementation correct?
Thank you for your time.

add a callback function to your ListFiles class:
setStateAddedNewClient( item ) {
setState(() {
futureFiles.add(item);
});
}
then add function parameter to your AddButton class:
final Function(dynamic) callback;
const AddButton({Key? key ,required this.callback }) : super(key: key);
and send file to callback function in your addFile function.
Future addFile() async {
final result = await FilePicker.platform.pickFiles();
if (result == null) return;
setState(() {
pickedFile = result.files.first;
callback(result.files.first);
});
uploadFile();
}

you can use a HookWidget
useEffect((() {
//request that you fetch data to listview
context.read<Cubit>().getListRequest();
return null;
}), [dependenciesFromAnotherWidgetToRefreshList]);

Related

I can not save the date after editing in the pop-up box

The code is as follows.
All the packages are imported with no error. It adds and saves the text but it does not save the date after editing it in the pop-up box. In the Save part I got this error "Unhandled Exception: type 'bool' is not a subtype of type 'String'". I also tried
Navigator.of(context).pop(textField?.controller?.text ?? "");
but this time it deletes the text after editing and saving it.
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Notepad',
home: NoteList(),
);
}
}
class NoteList extends StatefulWidget {
#override
_NoteListState createState() => _NoteListState();
}
class _NoteListState extends State<NoteList> {
final List<String> _notes = [];
final TextEditingController _textController = TextEditingController();
void _loadNotes() async {
var directory = await getApplicationDocumentsDirectory();
var file = File("${directory.path}/notes.txt");
if (!await file.exists()) {
file.createSync();
file.writeAsStringSync("Hello, World!\nThis is your first note.\n");
}
var contents = await file.readAsString();
setState(() {
_notes.addAll(contents.split("\n"));
});
}
void _saveNotes() async {
var directory = await getApplicationDocumentsDirectory();
var file = File("${directory.path}/notes.txt");
var contents = _notes.join("\n");
await file.writeAsString(contents);
}
void _deleteNote(int index) {
setState(() {
_notes.removeAt(index);
});
_saveNotes();
}
#override
void initState() {
super.initState();
_loadNotes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Notepad'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _notes.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_notes[index]),
onTap: () async {
var result = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Edit Note"),
content: TextField(
controller: TextEditingController(text: _notes[index]),
autofocus: true,
),
actions: [
ElevatedButton(
child: Text("Cancel"),
onPressed: () => Navigator.of(context).pop(),
),
ElevatedButton(
child: Text("Save"),
onPressed: () {
final TextField? textField = context.findAncestorWidgetOfExactType<TextField>();
Navigator.of(context).pop(textField != null?.controller?.text);
},
),
],
);
},
);
// update the note with the new text if the user saved their changes
if (result != null) {
setState(() {
_notes[index] = result;
});
_saveNotes();
}
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteNote(index),
),
],
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: "Enter a new note",
),
),
),
ElevatedButton(
child: Text("Add Note"),
onPressed: () {
setState(() {
_notes.add(_textController.text);
});
_textController.clear();
_saveNotes();
},
),
],
),
);
}
}
I never used findAncestorWidgetOfExactType before in my code but its for finding the ancestor. But when you are using the AlertDialog, its inner widgets like title, content and actions are suppose to be siblings. Thats why you can't find the TextField using this method.
Try creating a temporary TextEditingController inside the showDialog's builder method & use that in the TextField & Save button.
Like this
var result = await showDialog(
context: context,
builder: (context) {
TextEditingController temp = TextEditingController(text: _notes[index]);
return AlertDialog(
title: Text("Edit Note"),
content: TextField(
controller: temp,
autofocus: true,
),
actions: [
ElevatedButton(
child: Text("Cancel"),
onPressed: () => Navigator.of(context).pop(),
),
ElevatedButton(
child: Text("Save"),
onPressed: () {
Navigator.of(context).pop(temp.text);
},
),
],
);
},
);
You can test the code here https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1

how can I use showChoiceDialog() in my main.dart file

here is code of imagepicker in flutter .
how can I use showChoiceDialog(), opengallery() ,openCamera() in my other files . what class objects and variable should i have to make in order to use this functions in other file .how can I use showChoiceDialog(), opengallery() ,openCamera() in my other files . what class objects and variable should i have to make in order to use this functions in other file .
how can i set new image to Image Widgets .how can update the state.
imagepicker.dart
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class CameraWidget extends StatefulWidget {
#override
State createState() {
// TODO: implement createState
return CameraWidgetState();
}
}
class CameraWidgetState extends State {
PickedFile? imageFile = null;
Future<void> showChoiceDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Choose option",
style: TextStyle(color: Colors.blue),
),
content: SingleChildScrollView(
child: ListBody(
children: [
Divider(
height: 1,
color: Colors.blue,
),
ListTile(
onTap: () {
_openGallery(context);
},
title: Text("Gallery"),
leading: Icon(
Icons.account_box,
color: Colors.blue,
),
),
Divider(
height: 1,
color: Colors.blue,
),
ListTile(
onTap: () {
_openCamera(context);
},
title: Text("Camera"),
leading: Icon(
Icons.camera,
color: Colors.blue,
),
),
],
),
),
);
},
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Pick Image Camera"),
backgroundColor: Colors.green,
),
body: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Card(
child: (imageFile == null)
? Text("Choose Image")
: Image.file(File(imageFile!.path)),
),
Image.asset('images/img1.jpg'),
MaterialButton(
textColor: Colors.white,
color: Colors.pink,
onPressed: () {
showChoiceDialog(context);
},
child: Text("Select Image"),
)
],
),
),
),
);
}
void _openGallery(BuildContext context) async {
final pickedFile = await ImagePicker().getImage(
source: ImageSource.gallery,
);
setState(() {
imageFile = pickedFile!;
});
Navigator.pop(context);
}
void _openCamera(BuildContext context) async {
final pickedFile = await ImagePicker().getImage(
source: ImageSource.camera,
);
setState(() {
imageFile = pickedFile!;
});
Navigator.pop(context);
}
}
You cannot access their properties as they are marked as private. To mark a function/method as private, you put an underscore before its name. For example, checkUpdates() is a public method, and _checkUpdates() is a public method.
I would recommend putting these in another file if you plan on reusing them.
A very basic method of doing this is to create a new file, image_service.dart
Make a new class
class ImageService {
static void openGallery(BuildContext context) async {
final pickedFile = await ImagePicker().getImage(
source: ImageSource.gallery,
);
setState(() {
imageFile = pickedFile!;
});
Navigator.pop(context);
}
static void openCamera(BuildContext context) async {
final pickedFile = await ImagePicker().getImage(
source: ImageSource.camera,
);
setState(() {
imageFile = pickedFile!;
});
Navigator.pop(context);
}
}
And then you can use it as follows. ImageService.openGallery(context);

How to show a text after onPressed function

I want to show a text after onPressed function happened, this function is a recording function and wants to show a text 'recording' when the function happening
voiceCreate.dart
import 'package:flutter/material.dart';
class VoiceCreate extends StatelessWidget {
final VoidCallback onPressed;
VoiceCreate({this.onPressed});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: onPressed),
),
),
);
}
}
**main.dart**
import 'dart:io';
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:permission_handler/permission_handler.dart';
import 'regitration.dart';
import 'voiceCreate.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String statusText = "";
bool isComplete = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(
builder: (context) => Scaffold(
drawer: Drawer(
elevation: 2.0,
child: ListView(
children: <Widget>[
ListTile(
title: Text('Home'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return MyApp();
},
),
);
},
),
ListTile(
title: Text('Sign up'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
},
),
ListTile(
title: Text('Sign in'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
// add sign in page
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return VoiceCreate(onPressed: startRecord);
}),
);
},
// Add your onPressed code here!
child: Icon(Icons.add),
backgroundColor: Colors.tealAccent.shade700,
),
backgroundColor: Colors.grey.shade900,
appBar: AppBar(
title: Text('Myvo'),
centerTitle: true,
backgroundColor: Colors.tealAccent.shade700,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 40,
onPressed: () async {
startRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.pause),
color: Colors.white,
iconSize: 40,
onPressed: () async {
pauseRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.stop),
color: Colors.white,
iconSize: 40,
onPressed: () async {
stopRecord();
}),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
statusText,
style: TextStyle(color: Colors.red, fontSize: 20),
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
play();
},
child: Container(
margin: EdgeInsets.only(top: 30),
alignment: AlignmentDirectional.center,
width: 100,
height: 50,
child: isComplete && recordFilePath != null
? Text(
"play",
style: TextStyle(color: Colors.red, fontSize: 20),
)
: Container(),
),
),
]),
),
),
);
}
Future<bool> checkPermission() async {
if (!await Permission.microphone.isGranted) {
PermissionStatus status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
return false;
}
}
return true;
}
void startRecord() async {
bool hasPermission = await checkPermission();
if (hasPermission) {
statusText = "Recording...";
recordFilePath = await getFilePath();
isComplete = false;
RecordMp3.instance.start(recordFilePath, (type) {
statusText = "Record error--->$type";
setState(() {});
});
} else {
statusText = "No microphone permission";
}
setState(() {});
}
void pauseRecord() {
if (RecordMp3.instance.status == RecordStatus.PAUSE) {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
} else {
bool s = RecordMp3.instance.pause();
if (s) {
statusText = "Recording pause...";
setState(() {});
}
}
}
void stopRecord() {
bool s = RecordMp3.instance.stop();
if (s) {
statusText = "Record complete";
isComplete = true;
setState(() {});
}
}
void resumeRecord() {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
}
String recordFilePath;
void play() {
if (recordFilePath != null && File(recordFilePath).existsSync()) {
AudioPlayer audioPlayer = AudioPlayer();
audioPlayer.play(recordFilePath, isLocal: true);
}
}
int i = 0;
Future<String> getFilePath() async {
Directory storageDirectory = await getApplicationDocumentsDirectory();
String sdPath = storageDirectory.path + "/record";
var d = Directory(sdPath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
return sdPath + "/test_${i++}.mp3";
}
}
VoiceCreate function will happen on a new page when clicking on the Floating button in main.dart and recording will happen when click on mic Icon, want show the text 'recording' whine the fuction happening.
First of all, you need to have StatefulWidget to manage changes in state, then you can use two functions startRecording and stopRecording to toggle the isRecording variable. Then based on the value of isRecording you can make changes in the view, e.g., displaying a text. For displaying the text you can use a Visibility widget and set its visible parameter to isRecording.
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isRecording = false;
_startRecording() {
this.setState(() {
_isRecording = true;
});
}
_stopRecording() {
this.setState(() {
_isRecording = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: () => _startRecording(),
),
IconButton(
icon: Icon(Icons.stop),
color: Colors.white,
iconSize: 70,
onPressed: () => _stopRecording(),
),
Visibility(
visible: _isRecording,
child: Text(
'recording',
style: TextStyle(
color: Colors.red
),
),
)
],
),
),
),
);
}
}
Maybe a snackbar could be useful here, something like:
class VoiceCreate extends StatefulWidget {
VoiceCreate({Key key, this.title}) : super(key: key);
final String title;
#override
_VoiceCreateState createState() => _VoiceCreateState();
}
class _VoiceCreateState extends State<VoiceCreate> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
var isRecording = false;
void showRecordingMessage(String message, [Color color = Colors.red]) {
_scaffoldKey.currentState.showSnackBar(
new SnackBar(backgroundColor: color, content: new Text(message)));
}
void setRecordingState() {
this.setState(() {
isRecording = true;
});
print("isRecording is set to $isRecording");
showRecordingMessage('Recording now!');
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.blueGrey,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: () {
setRecordingState();
},
),
],
),
),
);
}
}

How to call child method from parent for another widget

main.dart
import 'dart:io';
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:permission_handler/permission_handler.dart';
import 'regitration.dart';
//import 'voiceCreate.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String statusText = "";
bool isComplete = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(
builder: (context) => Scaffold(
drawer: Drawer(
elevation: 2.0,
child: ListView(
children: <Widget>[
ListTile(
title: Text('Home'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return MyApp();
},
),
);
},
),
ListTile(
title: Text('Sign up'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
},
),
ListTile(
title: Text('Sign in'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
// add sign in page
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.add),
backgroundColor: Colors.tealAccent.shade700,
),
backgroundColor: Colors.grey.shade900,
appBar: AppBar(
title: Text('Myvo'),
centerTitle: true,
backgroundColor: Colors.tealAccent.shade700,
),
body: Column(children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 40,
onPressed: () async {
startRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.pause),
color: Colors.white,
iconSize: 40,
onPressed: () async {
pauseRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.stop),
color: Colors.white,
iconSize: 40,
onPressed: () async {
stopRecord();
}),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
statusText,
style: TextStyle(color: Colors.red, fontSize: 20),
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
play();
},
child: Container(
margin: EdgeInsets.only(top: 30),
alignment: AlignmentDirectional.center,
width: 100,
height: 50,
child: isComplete && recordFilePath != null
? Text(
"play",
style: TextStyle(color: Colors.red, fontSize: 20),
)
: Container(),
),
),
]),
),
),
);
}
Future<bool> checkPermission() async {
if (!await Permission.microphone.isGranted) {
PermissionStatus status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
return false;
}
}
return true;
}
void startRecord() async {
bool hasPermission = await checkPermission();
if (hasPermission) {
statusText = "Recording...";
recordFilePath = await getFilePath();
isComplete = false;
RecordMp3.instance.start(recordFilePath, (type) {
statusText = "Record error--->$type";
setState(() {});
});
} else {
statusText = "No microphone permission";
}
setState(() {});
}
void pauseRecord() {
if (RecordMp3.instance.status == RecordStatus.PAUSE) {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
} else {
bool s = RecordMp3.instance.pause();
if (s) {
statusText = "Recording pause...";
setState(() {});
}
}
}
void stopRecord() {
bool s = RecordMp3.instance.stop();
if (s) {
statusText = "Record complete";
isComplete = true;
setState(() {});
}
}
void resumeRecord() {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
}
String recordFilePath;
void play() {
if (recordFilePath != null && File(recordFilePath).existsSync()) {
AudioPlayer audioPlayer = AudioPlayer();
audioPlayer.play(recordFilePath, isLocal: true);
}
}
int i = 0;
Future<String> getFilePath() async {
Directory storageDirectory = await getApplicationDocumentsDirectory();
String sdPath = storageDirectory.path + "/record";
var d = Directory(sdPath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
return sdPath + "/test_${i++}.mp3";
}
}
I want to call the VoiceCreate function when clicking on onPressed
voiceCreate.dart
import 'package:flutter/material.dart';
import 'main.dart';
class VoiceCreate extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: () {}),
),
),
);
}
}
I want to call startRecord method from main.dart when clicking on onPressed
If you check the code of IconButton you'll see that onPressed is a VoidCallback, you can try to imitate the logic to do the same
class VoiceCreate extends StatelessWidget {
final VoidCallback onPressed;
VoiceCreate({this.onPressed});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: onPressed),
),
),
);
}
}
And in main just call your widget VoiceCreate with an onPressed parameter
VoiceCreate(
onPressed: () => startRecord
)
edited code here. Still the startRecord() is not working. VoiceCreate() is working
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return VoiceCreate(onPressed: startRecord);
}),
);
},
// Add your onPressed code here!
child: Icon(Icons.add),
backgroundColor: Colors.tealAccent.shade700,
),
class VoiceCreate extends StatelessWidget {
final VoidCallback onPressed;
VoiceCreate({this.onPressed});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: onPressed),
),
),
);
}
}
You could do this by using shared view model across need widgets, like so:
I'd recommend to use this approach instead of callbacks and Stateful widgets
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Parent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetBuilder<CommonViewModel>(
init: CommonViewModel(),
builder: (model) {
return Scaffold(
body: Column(
children: [
RaisedButton(onPressed: () => model.parentMethod(0)),
RaisedButton(onPressed: () => model.childMethod('call from parent')),
],
),
);
},
);
}
}
class Child extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetBuilder<CommonViewModel>(
builder: (model) {
return Scaffold(
body: Column(
children: [
RaisedButton(onPressed: () => model.childMethod('call from child')),
RaisedButton(onPressed: () => model.parentMethod(100)),
],
),
);
},
);
}
}
class CommonViewModel extends GetxController {
void parentMethod(int argument) {
print('Parent method $argument');
}
void childMethod(String argument) {
print('Child method $argument');
}
}

Flutter sharedpreferences get data after app restart

I have implemented the shared preferences which is used to store the current logged in user, i can get the username in each and every time after the user log in, however after the app is restart, the username is gone but the current user is still logged in. I attached the gif to have better explaination. Below is my code.
main.dart
Future<void> main() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var usernamee = prefs.getString('yourusername');
print(usernamee);
runApp(MaterialApp(
home: usernamee == null
? LoginPage()
: MainPage(
username: username,
)));
}
String username = '';
loginpage.dart
class LoginPage extends StatefulWidget {
#override
LoginPageState createState() => LoginPageState();
}
class LoginPageState extends State<LoginPage> {
TextEditingController user = new TextEditingController();
TextEditingController pass = new TextEditingController();
String txtmsg = '';
#override
void initState() {
super.initState();
}
Future<bool> _onWillPop() {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Are you sure?'),
content: new Text('Do you want to exit an App'),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('No'),
),
new FlatButton(
onPressed: () => Navigator.of(context).pop(true),
child: new Text('Yes'),
),
],
),
) ??
false;
}
Future<List> _login() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final response =
await http.post("http://192.168.1.2/login/login.php", body: {
"username": user.text,
"password": pass.text,
});
var datauser = json.decode(response.body);
if (datauser.length == 0) {
setState(() {
txtmsg = "Username or password is wrong, please try again.";
Fluttertoast.showToast(msg: txtmsg);
});
} else {
if (datauser[0]['level'] == 'admin') {
prefs.setString('yourusername', '$username');
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext ctx) => MainPage(
username: username,
)));
}
setState(() {
username = datauser[0]['username'];
});
}
print(username);
return datauser;
}
final logo = Hero(
tag: 'hero',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 48.0,
child: Image.asset('assets/images/ic_launcher.png'),
),
);
final forgotLabel = FlatButton(
child: Text(
'Forgot password?',
style: TextStyle(color: Colors.black54),
),
onPressed: () {},
);
#override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
ScreenUtil.instance =
ScreenUtil(width: 750, height: 1334, allowFontScaling: true);
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
logo,
SizedBox(height: 48.0),
Center(
child: FormUI(),
)
],
),
)));
}
Widget FormUI() {
return new Column(
children: <Widget>[
TextFormField(
controller: user,
decoration: InputDecoration(
hintText: 'Username',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 20.0),
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
),
validator: validateusername,
),
SizedBox(height: 18.0),
TextFormField(
controller: pass,
obscureText: true,
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 20.0),
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
),
validator: validatepassword,
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(40),
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: () => _login(),
padding: EdgeInsets.all(12),
color: Colors.lightBlueAccent,
child: Text('Log In', style: TextStyle(color: Colors.white)),
),
forgotLabel,
],
);
}
String validateusername(String value) {
if (value.length == 0) {
return "Name is Required";
}
return null;
}
String validatepassword(String value) {
if (value.length == 0) {
return "Password is Required";
}
return null;
}
}
mainpage.dart
class MainPage extends StatefulWidget {
MainPage({this.username});
final String username;
#override
MainPageState createState() => MainPageState();
}
class MainPageState extends State<MainPage> {
Future<bool> _onWillPop() {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Are you sure?'),
content: new Text('Do you want to exit an App'),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('No'),
),
new FlatButton(
onPressed: () => Navigator.of(context).pop(true),
child: new Text('Yes'),
),
],
),
) ??
false;
}
void showWifiAlert() async {
var wifiEnabled = await getWifiStatus();
if (wifiEnabled) {
//Do stuff
} else {
AlertDialog(
title: Center(
child: Text('Alert'),
),
content: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Text(
'Please connect to the internet',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.red,
),
),
)
],
),
actions: <Widget>[
FlatButton(
child: Text(
'Ok',
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
}
Future<bool> getWifiStatus() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
return true;
}
} on SocketException catch (_) {
print('not connected');
return false;
}
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
String username;
print(username);
showWifiAlert();
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: Center(
child: Text(
widget.username,
),
),
drawer: new DrawerOnly()),
);
}
}
class DrawerOnly extends StatefulWidget {
#override
DrawerOnlyState createState() => DrawerOnlyState();
}
class DrawerOnlyState extends State<DrawerOnly> {
#override
Widget build(BuildContext ctxt) {
return new Drawer(
child: new ListView(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: Text('$username'),
accountEmail: null,
currentAccountPicture: CircleAvatar(
child: FlutterLogo(size: 42.0),
backgroundColor: Colors.white,
),
),
new ListTile(
leading: Icon(Icons.library_music),
title: Text('Fragment 1'),
onTap: () {
Navigator.pop(ctxt);
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new FirstFragment()));
},
),
new ListTile(
leading: Icon(Icons.movie),
title: Text('Fragment 2'),
onTap: () {
Navigator.pop(ctxt);
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new SecondFragment()));
},
),
new ListTile(
leading: Icon(Icons.exit_to_app),
title: Text('Logout'),
onTap: () async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('yourusername');
Navigator.pushReplacement(ctxt,
MaterialPageRoute(builder: (BuildContext ctx) => LoginPage()));
/* Navigator.pop(ctxt);
Navigator.pushReplacementNamed(ctxt, '/landingpage'); */
},
),
],
));
}
}
How do i able to get the username even the app is restarted?
I've figure out, i had to add this code in the mainpage.dart. Below is the snippet.
loadUsername() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
username = prefs.getString('yourusername');
});
}
#override
void initState() {
super.initState();
loadUsername();
}
Fetch the value on initState not in the main method.
var username;
getUsername() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
username = prefs.getString('yourusername');
}
#override
void initState() {
getUsername()
super.initState();
}
i use it like that, on my splashscreen and it works perfectly
#override
void initState() {
super.initState();
token();
}
token() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String token = prefs.getString('userToken');
Timer(Duration(milliseconds: 1000), () {
if (token == null || token == '') {
Navigator.pushNamed(context, '/login');
} else {
Navigator.pushNamed(context, '/home');
}
});
}
Use setUser() [retrieve preferences values] just before super.initState();
#override
void initState() {
setUser();
super.initState();
}
setUser() async{
preferences=await SharedPreferences.getInstance();
setState(() {
userId = preferences.getString(USERID) ?? "ak id";
userName = preferences.getString(USERNAME) ?? "ak name";
userEmail = preferences.getString(USEREMAIL) ?? "ak email";
userPhoto = preferences.getString(USERPHOTO) ?? "";
});
}