カスタムダイアログウィジェットで指定されたものに応じて、画像またはテキストのいずれかを含む必要があるコンテナーがページにあります。このウィジェットを別のステートレス クラスで作成しました。コンテナが作成されたページからこれを呼び出しています。
カスタム ダイアログ
class CustomDialog extends StatelessWidget {
TextEditingController textController;
BuildContext context;
Function saveAction;
CustomDialog({
this.context,
this.textController,
this.saveAction,
});
_getText(String text) {
return Text(
text,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black, fontSize: 16),
);
}
_buildIconHolder(IconData icon) {
return Container(
width: 60,
height: 60,
decoration:
BoxDecoration(shape: BoxShape.circle, color: Colors.yellowAccent),
child: Icon(icon, size: 40, color: Colors.blue),
);
}
_buildImagePickerElements() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_getText("Add Image"),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildIconHolder(Icons.folder_open),
_getText("or"),
_buildIconHolder(Icons.camera_alt),
],
),
],
);
}
_buildTextInput() {
return Card(
color: Colors.orange[600],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Padding(
padding: EdgeInsets.all(10),
child: TextField(
controller: textController,
decoration: InputDecoration(
border: InputBorder.none, hintText: "hint text here"),
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
textInputAction: TextInputAction.next,
maxLines: 4,
),
),
);
}
_buildPrimaryButton(Function fn) {
return InkWell(
child: GestureDetector(
child: Container(
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
decoration: BoxDecoration(
color: Colors.purple,
borderRadius: BorderRadius.all(Radius.circular(10))),
child: Text("Save",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white)),
),
onTap: () => {
fn,
Navigator.of(ctx).pop();
),
);
}
_getDialogElements() {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_buildImagePickerElements(),
SizedBox(height: 10),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.only(right: 10),
child: Divider(color: Colors.purple, thickness: 2),
),
),
_getText("or"),
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 10),
child: Divider(color: Colors.purple, thickness: 2),
),
),
],
),
SizedBox(height: 10),
_getText("Describe Below"),
SizedBox(height: 10),
_buildTextInput(),
SizedBox(height: 10),
_buildPrimaryButton(saveAction),
],
);
}
Widget build(BuildContext context) {
return AlertDialog(
backgroundColor: Colors.blueGrey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
content: SingleChildScrollView(
child: Container(width: 400.0, child: _getDialogElements()),
),
);
}
}
ホームページ
import 'package:custom_dialog/custom_dialog.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _controller = new TextEditingController();
String _field = "";
clicked(BuildContext ctx) {
// setState(() {
if (_controller.text.isNotEmpty && _controller.text != null) {
_field = _controller.text;
}
// Navigator.of(ctx).pop();
// });
}
_makeContainerAText() {
return Container(
width: 40,
height: 60,
child: Text(_field),
);
}
_makeContainerAActionBtn() {
return Container(
width: 40,
height: 60,
child: FloatingActionButton(
backgroundColor: Colors.yellow,
onPressed: () {
setState(() {
print("Action button pressed");
showDialog(
context: context,
builder: (BuildContext context) => CustomDialog(
context: context,
textController: _controller,
saveAction: clicked(context),
),
);
});
},
child: Icon(
Icons.add,
color: Colors.purple,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Container Home Page"),
),
body: Center(
child: Stack(
children: <Widget>[
InkWell(
splashColor: Colors.orange[400],
highlightColor: Colors.purple,
child: Material(
elevation: 10,
borderRadius: BorderRadius.all(Radius.circular(10)),
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.orange[600],
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Padding(
padding: EdgeInsets.all(25),
child: validate
? _makeContainerAText()
: _makeContainerAActionBtn(),
),
),
),
)
],
),
),
);
}
}
要するに、テキストまたは画像を追加した後、コンテナを以下のリンクのように見せたいのです。
ステートレスであるため、カスタム ダイアログ クラスで setState を使用できません。ステートフルにすると、ダイアログを表示するコンテナをクリックしても、画面に表示されません。メソッドで setState を使用しようとしましたclicked()
が、以下のエラーが発生しました。
════════ Exception caught by animation library ═════════════════════════════════
The following assertion was thrown while notifying status listeners for AnimationController:
setState() or markNeedsBuild() called during build.
This _ModalScope<dynamic> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _ModalScope<dynamic>-[LabeledGlobalKey<_ModalScopeState<dynamic>>#f69dd]
state: _ModalScopeState<dynamic>#32d94
The widget which was currently being built when the offending call was made was: Builder
dirty
When the exception was thrown, this was the stack
#0 Element.markNeedsBuild.<anonymous closure>
package:flutter/…/widgets/framework.dart:3896
#1 Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:3911
#2 State.setState
package:flutter/…/widgets/framework.dart:1168
#3 _ModalScopeState._routeSetState
package:flutter/…/widgets/routes.dart:664
#4 ModalRoute.setState
package:flutter/…/widgets/routes.dart:784
...
The AnimationController notifying status listeners was: AnimationController#073ac(⏮ 0.000; paused; for _DialogRoute<dynamic>)
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
setState() or markNeedsBuild() called during build.
The relevant error-causing widget was
MaterialApp
lib/main.dart:9
════════════════════════════════════════════════════════════════════════════════