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

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);

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 to refresh a listview from another widget in 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]);

Image is being passed in second attempt not in the first attempt in Flutter

I need some help regarding the image picker plugin in Flutter. When I press image or gallery in the alert dialog and selecting my image, then background image is being displayed but not passed/saved but when I again press image or gallery in the alert dialog and selecting my image, then background image is being both displayed and passed/saved. what should I do?
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UserImagePicker extends StatefulWidget {
UserImagePicker(this.imagePickfn);
final void Function(File pickedImage) imagePickfn;
#override
_UserImagePickerState createState() => _UserImagePickerState();
}
class _UserImagePickerState extends State<UserImagePicker> {
File _pickedImage;
void _pickImage() {
showDialog<ImageSource>(
context: context,
builder: (context) =>
AlertDialog(title: Text("Choose image source"), actions: [
FlatButton(
child: Text("Camera"),
onPressed: () => Navigator.pop(context, ImageSource.camera),
),
FlatButton(
child: Text("Gallery"),
onPressed: () => Navigator.pop(context, ImageSource.gallery),
),
]),
).then((ImageSource source) async {
if (source != null) {
final pickedFile = await ImagePicker().getImage(
source: source,
imageQuality: 50,
maxWidth: 150,
);
setState(() => _pickedImage = File(pickedFile.path));
}
});
widget.imagePickfn(_pickedImage);
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CircleAvatar(
radius: 40,
backgroundColor: Theme.of(context).primaryColor,
backgroundImage:
_pickedImage != null ? FileImage(_pickedImage) : null,
),
FlatButton.icon(
textColor: Theme.of(context).primaryColor,
onPressed: _pickImage,
icon: Icon(Icons.image),
label: Text('Add an Image'),
),
],
);
}
}
The problem is in the _pickImage() method. You need to move widget.imagePickfn(_pickedImage); inside then section. Like this.
void _pickImage() {
showDialog<ImageSource>(
context: context,
builder: (context) =>
AlertDialog(title: Text("Choose image source"), actions: [
FlatButton(
child: Text("Camera"),
onPressed: () => Navigator.pop(context, ImageSource.camera),
),
FlatButton(
child: Text("Gallery"),
onPressed: () => Navigator.pop(context, ImageSource.gallery),
),
]),
).then((ImageSource source) async {
if (source != null) {
final pickedFile = await ImagePicker().getImage(
source: source,
imageQuality: 50,
maxWidth: 150,
);
setState(() => _pickedImage = File(pickedFile.path));
widget.imagePickfn(_pickedImage);
}
});
}
This is happening because you called the widget.imagePickfn(_pickedImage); method outside the then method. The picked image result is returned in the then section after closing dialog. That is why, in first attempt your image is not returning, and in second attempt it is returning the previous selected image.
Hope this will solve your problem.
If the above one doesn't solve your problem, you can try this one
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UserImagePicker extends StatefulWidget {
UserImagePicker(this.imagePickfn);
final void Function(File pickedImage) imagePickfn;
#override
_UserImagePickerState createState() => _UserImagePickerState();
}
class _UserImagePickerState extends State<UserImagePicker> {
File _pickedImage;
void _pickImage() async {
ImageSource source = await showDialog<ImageSource>(
context: context,
builder: (context) =>
AlertDialog(title: Text("Choose image source"), actions: [
FlatButton(
child: Text("Camera"),
onPressed: () => Navigator.pop(context, ImageSource.camera),
),
FlatButton(
child: Text("Gallery"),
onPressed: () => Navigator.pop(context, ImageSource.gallery),
),
]),
);
if (source != null) {
final pickedFile = await ImagePicker().getImage(
source: source,
imageQuality: 50,
maxWidth: 150,
);
setState(() => _pickedImage = File(pickedFile.path));
widget.imagePickfn(_pickedImage);
}
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CircleAvatar(
radius: 40,
backgroundColor: Theme.of(context).primaryColor,
backgroundImage:
_pickedImage != null ? FileImage(_pickedImage) : null,
),
FlatButton.icon(
textColor: Theme.of(context).primaryColor,
onPressed: () => _pickImage(),
icon: Icon(Icons.image),
label: Text('Add an Image'),
),
],
);
}
}

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');
}
}