Flutter 如何从另一个小部件的父对象调用子方法
main.dartFlutter 如何从另一个小部件的父对象调用子方法,flutter,Flutter,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:pe
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";
}
}
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: () {}),
),
),
);
}
}
我想在点击按下图标按钮时从main.dart调用
startRecord
方法,如果你检查图标按钮的代码,你会发现按下图标按钮是一个无效回调,你可以尝试模仿逻辑来做同样的事情
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),
),
),
);
}
}
基本上,只需使用onPressed参数调用小部件VoiceCreate
VoiceCreate(
onPressed: () => startRecord
)
在这里编辑代码。开始记录()仍然不起作用VoiceCreate()正在工作
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),
),
),
);
}
}
如果您检查IconButton的代码,您将看到onPressed是一个VoidCallback,您可以尝试模仿逻辑来执行相同的操作
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),
),
),
);
}
}
基本上,只需使用onPressed参数调用小部件VoiceCreate
VoiceCreate(
onPressed: () => startRecord
)
在这里编辑代码。开始记录()仍然不起作用VoiceCreate()正在工作
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),
),
),
);
}
}
您可以通过跨需要的小部件使用共享视图模型来实现这一点,如下所示: 我建议使用这种方法,而不是回调和有状态小部件
导入“包装:颤振/材料.省道”;
导入“package:get/get.dart”;
类父级扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回GetBuilder(
init:CommonViewModel(),
建筑商:(模型){
返回脚手架(
正文:专栏(
儿童:[
RaisedButton(按下时:()=>model.parentMethod(0)),
RaisedButton(按下时:()=>model.childMethod('callfromParent'),
],
),
);
},
);
}
}
类子部件扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回GetBuilder(
建筑商:(模型){
返回脚手架(
正文:专栏(
儿童:[
RaisedButton(按下时:()=>model.childMethod('callfromchild'),
RaisedButton(按下时:()=>model.parentMethod(100)),
],
),
);
},
);
}
}
类CommonViewModel扩展了GetxController{
void parentMethod(int参数){
打印(“父方法$argument”);
}
void childMethod(字符串参数){
打印(“子方法$argument”);
}
}
您可以通过跨需求小部件使用共享视图模型来实现这一点,如下所示:
我建议使用这种方法,而不是回调和有状态小部件
导入“包装:颤振/材料.省道”;
导入“package:get/get.dart”;
类父级扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回GetBuilder(
init:CommonViewModel(),
建筑商:(模型){
返回脚手架(
正文:专栏(
儿童:[
RaisedButton(按下时:()=>model.parentMethod(0)),
RaisedButton(按下时:()=>model.childMethod('callfromParent'),
],
),
);
},
);
}
}
类子部件扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回GetBuilder(
建筑商:(模型){
返回脚手架(
正文:专栏(
儿童:[
RaisedButton(按下时:()=>model.childMethod('callfromchild'),
RaisedButton(按下时:()=>model.parentMethod(100)),
],
),
);
},
);
}
}
类CommonViewModel扩展了GetxController{
void parentMethod(int参数){
打印(“父方法$argument”);
}
void childMethod(字符串参数){
打印(“子方法$argument”);
}
}
您可以将startRecord函数作为VoicCreate的参数构造函数传递,并在按下时调用该函数。您可以将startRecord函数作为VoicCreate的参数构造函数传递,并在按下时调用该函数。单击浮动按钮时,startRecord()仍然不起作用,VoiceCreate正在使用floatingActionButton:floatingActionButton(按下时:(){Navigator.push(上下文,MaterialPage路由(生成器:(上下文){返回VoiceCreate(按下时:()=>startRecord);}),;},//在这里添加您的onPressed代码!child:Icon(Icons.Add),backgroundColor:Colors.tealacent.shade700,),我运行了一个示例,没有问题,只是将其更改为VoiceCreate(onPressed:()=>startRecord())
(忘记括号)或语音创建(按下:开始录制)
(这是一个无效函数,因此您可以忽略()=>
)但是,当单击浮动按钮时,startRecord()不工作,VoiceCreate正在工作浮动操作按钮:浮动操作按钮(context){return VoiceCreate(onPressed:()=>startRecord);}),;},//在此处添加onPressed代码!child:Icon(Icons.Add),backgroundColor:Colors.tealacent.shade700,),我毫无问题地运行了一个示例,只是将其更改为VoiceCreate(onPressed:()=>startRecord());
(忘记了括号)或VoiceCreate(onPressed:startRecord);
(这是一个无效函数,因此可以忽略()=>
)