Flutter Save & Load Image - Image Picker/Image crop - image

I'm trying to make a profile picture screen in flutter. I have used this 2 plugin (image crop and image picker) for select and edit the image.
class ProfilePage extends StatefulWidget {
#override
__ProfilePageState createState() => __ProfilePageState();
}
class __ProfilePageState extends State<ProfilePage> {
File _pickedImage;
String _imagepath;
#override
void initState() {
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Profile'),
// ),
body: ListView(
children: <Widget>[
Center(
child: CircleAvatar(
radius: 80,
child: _imagepath == null ? Text('Profile image') : null,
backgroundImage:
_imagepath != null ? FileImage(File(_imagepath)) : null,
),
),
SizedBox(height: 10),
RaisedButton(
child: Text('Select image'),
onPressed: () {
_showPickOptionDialog(context);
},
)
],
),
);
}
_loadPicker(ImageSource source) async {
File picked = await ImagePicker.pickImage(source: source);
if (picked != null) {
_cropImage(picked);
SaveImage(picked.path);
}
LoadImage();
Navigator.pop(context);
}
_cropImage(File picked) async {
File cropped = await ImageCropper.cropImage(
androidUiSettings: AndroidUiSettings(
toolbarTitle: "Modifica immagine",
statusBarColor: Colors.green,
toolbarColor: Colors.green,
toolbarWidgetColor: Colors.white,
),
sourcePath: picked.path,
// aspectRatioPresets: [
// CropAspectRatioPreset.original,
// CropAspectRatioPreset.ratio16x9,
// CropAspectRatioPreset.ratio4x3,
// ],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
}
void _showPickOptionDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('select image from gallery'),
onTap: () {
_loadPicker(ImageSource.gallery);
}),
ListTile(
title: Text('Scatta una foto'),
onTap: () {
_loadPicker(ImageSource.camera);
},
),
],
),
));
}
void SaveImage(path) async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
saveimage.setString("imagepath", path);
}
void LoadImage() async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
setState(() {
_imagepath = saveimage.getString("imagepath");
});
}
}
Code works but it only save the picked image instead of the cropped one.
I've tried many times but I can't see the error, sorry about that..
could you help me?
Thanks!

when you use Future you should return value and use this value with .then()
try this:
class ProfilePage extends StatefulWidget {
#override
__ProfilePageState createState() => __ProfilePageState();
}
class __ProfilePageState extends State<ProfilePage> {
File _pickedImage;
String _imagepath;
#override
void initState() {
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Profile'),
// ),
body: ListView(
children: <Widget>[
Center(
child: CircleAvatar(
radius: 80,
child: _imagepath == null ? Text('Profile image') : null,
backgroundImage:
_imagepath != null ? FileImage(File(_imagepath)) : null,
),
),
SizedBox(height: 10),
RaisedButton(
child: Text('Select image'),
onPressed: () {
_showPickOptionDialog(context);
},
)
],
),
);
}
_loadPicker(ImageSource source) async {
File picked = await ImagePicker.pickImage(source: source);
if (picked != null) {
_cropImage(picked).then(File cropped){
SaveImage(cropped.path);
}
}
LoadImage();
Navigator.pop(context);
}
Future<File> _cropImage(File picked) async {
File cropped = await ImageCropper.cropImage(
androidUiSettings: AndroidUiSettings(
toolbarTitle: "Modifica immagine",
statusBarColor: Colors.green,
toolbarColor: Colors.green,
toolbarWidgetColor: Colors.white,
),
sourcePath: picked.path,
// aspectRatioPresets: [
// CropAspectRatioPreset.original,
// CropAspectRatioPreset.ratio16x9,
// CropAspectRatioPreset.ratio4x3,
// ],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
return cropped;
}
void _showPickOptionDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('select image from gallery'),
onTap: () {
_loadPicker(ImageSource.gallery);
}),
ListTile(
title: Text('Scatta una foto'),
onTap: () {
_loadPicker(ImageSource.camera);
},
),
],
),
));
}
void SaveImage(path) async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
saveimage.setString("imagepath", path);
}
void LoadImage() async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
setState(() {
_imagepath = saveimage.getString("imagepath");
});
}
}

Found the solution by editing this part:
if (cropped != null) {
_pickedImage = cropped;
SaveImage(_pickedImage.path);
LoadImage();
setState(() {});
}
}

Related

How to Display Picked Image in Flutter

I want to Pick a image and then display the picked Image. So I tried doing this->
class ImageUploadChoice extends StatefulWidget {
#override
_ImageUploadChoiceState createState() => _ImageUploadChoiceState();
}
class _ImageUploadChoiceState extends State<ImageUploadChoice> {
File imageFile;
Future getImage(int type) async {
PickedFile pickedImage = await ImagePicker().getImage(
source: type == 1 ? ImageSource.camera : ImageSource.gallery,
imageQuality: 50
);
return pickedImage;
}
For Displaying Image
Expanded(
child: Container(
child: imageFile != null
? Image.file(
imageFile,
height: MediaQuery.of(context).size.height / 5,
)
: Text("Pick up the image"),
),
),
For Calling Function->
new ListTile(
leading: new Icon(
Icons.photo_library,
color: Colors.black,),
title: new Text(
'Photo Library',
style: getTextStyle(MediaQuery.of(context).size.height, "heading2"),
),
onTap: () async {
final tmpFile = await getImage(2);
setState(() {
imageFile = tmpFile;
});
Navigator.pop(context);
Navigator.of(context).pop();
}),
But It's not Working. The Selected Image is not been displayed. What else I need to do?
Made a sample code and it's working fine. Remove following lines
Navigator.pop(context);
Navigator.of(context).pop();
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Test(),
);
}
}
class Test extends StatefulWidget {
#override
_Test createState() => _Test();
}
class _Test extends State<Test> {
File imageFile;
Future getImage() async {
final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
imageFile = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: InkWell(
onTap: (){
getImage();
},
child: Icon(
Icons.add
),
),
body: Center(
child: root(),
),
);
}
Widget root() {
return Container(
child: imageFile != null
? Image.file(
imageFile,
height: MediaQuery
.of(context)
.size
.height / 5,
)
: Text("Pick up the image"),
);
}
}

setState() or markNeedsBuild() error when trying to pick image from gallery and take image with camera flutter

I'm trying to take an image from my gallery or capture with camera immediately the upload page is built. I created a dialog to show the two options but I'm getting the error
setState() or markNeedsBuild() called during build.
when I run on my emulator.
Any help will be appreciated. Thank you
This is my code
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker=ImagePicker();
takeImage(mContext){
return showDialog(
context: mContext,
builder: (context){
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Cancel",style: TextStyle(color: Colors.red),),
onPressed: (){
Navigator.pop(context);
},
),
],
);
}
);
}
#override
Widget build(BuildContext context) {
return takeImage(context);
}
}
showDialog displays a dialog above the current contents of the app and it returns the future.
You can call showDialog after build
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker = ImagePicker();
takeImage(mContext) {
return showDialog(
context: mContext,
builder: (context) {
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text(
"Cancel",
style: TextStyle(color: Colors.red),
),
onPressed: () {
Navigator.pop(context);
},
),
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Take Picture',
),
),
body: Center(
child: FlatButton(
color: Colors.blue,
onPressed: () {
takeImage(context);
},
child: Text(
'Select Image',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}

How can I select and upload Multiple images in Flutter

I tried to find how to select and upload multiple images in flutter but most of the plugins are not working or I did not understand them well. I found little application but it selects and upload only one picture. How to change this code that user can select and upload multiple pictures or is there any other alternatives. Please write in details, i am freshman in coding. Thanks in advance.
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
import 'package:toast/toast.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Upload Demo',
theme: ThemeData(primarySwatch: Colors.pink),
home: ImageInput());
}
}
class ImageInput extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _ImageInput();
}
}
class _ImageInput extends State<ImageInput> {
// To store the file provided by the image_picker
File _imageFile;
// To track the file uploading state
bool _isUploading = false;
String baseUrl = 'http://YOUR_IPV4_ADDRESS/flutterdemoapi/api.php';
void _getImage(BuildContext context, ImageSource source) async {
File image = await ImagePicker.pickImage(source: source);
setState(() {
_imageFile = image;
});
// Closes the bottom sheet
Navigator.pop(context);
}
Future<Map<String, dynamic>> _uploadImage(File image) async {
setState(() {
_isUploading = true;
});
// Find the mime type of the selected file by looking at the header bytes of the file
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest =
http.MultipartRequest('POST', Uri.parse(baseUrl));
// Attach the file in the request
final file = await http.MultipartFile.fromPath('image', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
// Explicitly pass the extension of the image with request body
// Since image_picker has some bugs due which it mixes up
// image extension with file name like this filenamejpge
// Which creates some problem at the server side to manage
// or verify the file extension
imageUploadRequest.fields['ext'] = mimeTypeData[1];
imageUploadRequest.files.add(file);
try {
final streamedResponse = await imageUploadRequest.send();
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode != 200) {
return null;
}
final Map<String, dynamic> responseData = json.decode(response.body);
_resetState();
return responseData;
} catch (e) {
print(e);
return null;
}
}
void _startUploading() async {
final Map<String, dynamic> response = await _uploadImage(_imageFile);
print(response);
// Check if any error occured
if (response == null || response.containsKey("error")) {
Toast.show("Image Upload Failed!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
} else {
Toast.show("Image Uploaded Successfully!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
}
void _resetState() {
setState(() {
_isUploading = false;
_imageFile = null;
});
}
void _openImagePickerModal(BuildContext context) {
final flatButtonColor = Theme.of(context).primaryColor;
print('Image Picker Modal Called');
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 150.0,
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Text(
'Pick an image',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(
height: 10.0,
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Camera'),
onPressed: () {
_getImage(context, ImageSource.camera);
},
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Gallery'),
onPressed: () {
_getImage(context, ImageSource.gallery);
},
),
],
),
);
});
}
Widget _buildUploadBtn() {
Widget btnWidget = Container();
if (_isUploading) {
// File is being uploaded then show a progress indicator
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: CircularProgressIndicator());
} else if (!_isUploading && _imageFile != null) {
// If image is picked by the user then show a upload btn
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: RaisedButton(
child: Text('Upload'),
onPressed: () {
_startUploading();
},
color: Colors.pinkAccent,
textColor: Colors.white,
),
);
}
return btnWidget;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Upload Demo'),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 10.0, right: 10.0),
child: OutlineButton(
onPressed: () => _openImagePickerModal(context),
borderSide:
BorderSide(color: Theme.of(context).accentColor, width: 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.camera_alt),
SizedBox(
width: 5.0,
),
Text('Add Image'),
],
),
),
),
_imageFile == null
? Text('Please pick an image')
: Image.file(
_imageFile,
fit: BoxFit.cover,
height: 300.0,
alignment: Alignment.topCenter,
width: MediaQuery.of(context).size.width,
),
_buildUploadBtn(),
],
),
);
}
}
I used that package:
dependencies:
multi_image_picker: ^4.6.7
Ex:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:multi_image_picker/multi_image_picker.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Asset> images = List<Asset>();
String _error;
#override
void initState() {
super.initState();
}
Widget buildGridView() {
if (images != null)
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
Asset asset = images[index];
return AssetThumb(
asset: asset,
width: 300,
height: 300,
);
}),
);
else
return Container(color: Colors.white);
}
Future<void> loadAssets() async {
setState(() {
images = List<Asset>();
});
List<Asset> resultList;
String error;
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
);
} on Exception catch (e) {
error = e.toString();
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
images = resultList;
if (error == null) _error = 'No Error Dectected';
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
),
);
}
}
Add dependecy of image_picker:
image_picker: ^0.8.4+3
Then make a method for selectImages():
final ImagePicker imagePicker = ImagePicker();
List<XFile>? imageFileList = [];
void selectImages() async {
final List<XFile>? selectedImages = await
imagePicker.pickMultiImage();
if (selectedImages!.isNotEmpty) {
imageFileList!.addAll(selectedImages);
}
print("Image List Length:" + imageFileList!.length.toString());
setState((){});
}
Create a builder for showing selected Images:
return Scaffold(
appBar: AppBar(
title: Text('Multiple Images'),
),
body: SafeArea(
child: Column(
children: [
ElevatedButton(
onPressed: () {
selectImages();
},
child: Text('Select Images'),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
itemCount: imageFileList!.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Image.file(File(imageFileList![index].path),
fit: BoxFit.cover,);
}),
),
),
],
),
));
Complete Source code available in github link...
https://github.com/NishaJain24/multi_image_picker

Flutter: Overput image over image save it on image and then share it

I want to add a simple image over an image from the gallery/camera. The behavior should be like it.
Open the application, choose a photo or make one with the floating buttons, then show the image and over put our logo on the bottom left. All it is working now.
Then I would like to save it both images in a single one, but I don't know how this process is called or how to achieve it.
import 'package:share/share.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Picker Demo',
home: MyHomePage(title: 'Image Picker Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File _imageFile;
dynamic _pickImageError;
String _retrieveDataError;
void _onImageButtonPressed(ImageSource source) async {
try {
_imageFile = await ImagePicker.pickImage(source: source);
} catch (e) {
_pickImageError = e;
}
setState(() {});
}
Widget _previewImage() {
final Text retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFile != null) {
print('La imagen ha sido puesta en la pantalla?');
return Image.file(_imageFile);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
Future<void> retrieveLostData() async {
final LostDataResponse response = await ImagePicker.retrieveLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
setState(() {
_imageFile = response.file;
});
} else {
_retrieveDataError = response.exception.code;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Stack(children: <Widget>[
Container(
color: Colors.amber,
child: Platform.isAndroid
? FutureBuilder<void>(
future: retrieveLostData(),
builder:
(BuildContext context, AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return _previewImage();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: (_previewImage())), //
Positioned(
bottom: 16,
left: 16,
width: 100,
height: 100,
child: Image.network(
'http://father-home.ru/wp-content/uploads/2018/05/cropped-logo8.png'))
]))),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
onPressed: () {
_onImageButtonPressed(ImageSource.gallery);
},
heroTag: 'image0',
tooltip: 'Pick Image from gallery',
child: const Icon(Icons.photo_library),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
_onImageButtonPressed(ImageSource.camera);
},
heroTag: 'image1',
tooltip: 'Take a Photo',
child: const Icon(Icons.camera_alt),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
_onShare();
},
tooltip: 'Share',
child: const Icon(Icons.share),
),
),
],
),
);
}
void _onShare(){
//TODO: save the two images into one and share
}
Text _getRetrieveErrorWidget() {
if (_retrieveDataError != null) {
final Text result = Text(_retrieveDataError);
_retrieveDataError = null;
return result;
}
return null;
}
}
the widget with this code looks like it:
You can use RepaintBoundary widget to export a specific widget to image.
I believe that you will need to work with Bitmap.
Load 2 bitmaps, one is the background, one is your logo.
Apply transformation as you like.
Save output bitmap to file.
Take a look at: https://pub.dev/packages/bitmap

setState does not update wiget UI

I spent few hours trying to understand why clicking on the IconButton does not toggle change its icon.
import 'package:flutter/material.dart';
import 'dart:core';
class TestIconChange extends StatefulWidget {
#override
_TestIconChangeState createState() => _TestIconChangeState();
}
class _TestIconChangeState extends State<TestIconChange>
with TickerProviderStateMixin {
IconData _iconData = Icons.add;
AnimationController _animationController1;
Widget _child;
#override
void initState() {
super.initState();
_animationController1 = AnimationController(
vsync: this,
value: 1,
duration: Duration(seconds: 1),
);
}
#override
Widget build(BuildContext context) {
if (_child == null) _child = _buildButton();
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
AnimatedSwitcher(
duration: Duration(milliseconds: 100),
child: _child,
),
RaisedButton(
child: Text('Text Child'),
onPressed: (() {
setState(() {
_child = Text('Dummy text');
});
}),
),
RaisedButton(
child: Text('Button Child'),
onPressed: (() {
setState(() {
_child =_buildButton();
},);
}),
)
],
),
),
),
);
}
Widget _buildButton() {
return IconButton(
onPressed: () {
setState(() {
(_iconData == Icons.add)
? _iconData = Icons.remove
: _iconData = Icons.add;
});
},
icon: Icon(_iconData),
);
}
}
When you call setState it rebuild only Widgets that build in build method.
The main problem was that you didn't do it. You didn't rebuild _child in build method.
This line in your code wrong: if (_child == null) _child = _buildButton();
If you make it like this _child = _buildButton(); then work only button +/-, but not works change to text. Need refactoring of your code!
So, I made refactoring of your code and add ChildType that indicate what type of Widget you want to show: text or button. And then use it in setState method. Now it works, as you expected :)
import 'package:flutter/material.dart';
import 'dart:core';
class TestIconChange extends StatefulWidget {
#override
_TestIconChangeState createState() => _TestIconChangeState();
}
enum ChildType {text, button}
class _TestIconChangeState extends State<TestIconChange>
with TickerProviderStateMixin {
ChildType curChildType = ChildType.button;
IconData _iconData = Icons.add;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
AnimatedSwitcher(
duration: Duration(milliseconds: 100),
child: _buildButton(),
),
RaisedButton(
child: Text('Text Child'),
onPressed: (() {
setState(() {
curChildType = ChildType.text;
});
}),
),
RaisedButton(
child: Text('Button Child'),
onPressed: (() {
setState(() {
curChildType = ChildType.button;
},);
}),
)
],
),
),
);
}
Widget _buildButton() {
if (curChildType == ChildType.text) {
return Text('Dummy text');
}
else {
return IconButton(
icon: Icon(_iconData),
onPressed: () {
setState(() {
_iconData = (_iconData == Icons.add) ? Icons.remove : _iconData = Icons.add;
});
},
);
}
}
}
Good Luck!

Resources