Is it possible to create image from Text in a flutter? - flutter

I am working on a app where user can logged into a app and can enter a text in a textformfileld it and can also apply different fontstyle and font family and generate a image from it.
is it possible ?
Any help would be highly appreciated

Here is an example for you. You can test it in an app.
It draw the text to a canvas then save canvas as an image. So you can apply any font style to ParagraphBuilder.
I hope it helps
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController controller = TextEditingController();
Image? img;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormField(
controller: controller,
),
ElevatedButton(onPressed: _onPressedButton, child: const Text("Create Image")),
Container(width: 200, height: 200, color: Colors.blueGrey, child: img ?? Container())
],
),
),
);
}
void getCanvasImage(String str) async {
var builder = ParagraphBuilder(ParagraphStyle(fontStyle: FontStyle.normal));
builder.addText(str);
Paragraph paragraph = builder.build();
paragraph.layout(const ParagraphConstraints(width: 100));
final recorder = PictureRecorder();
var newCanvas = Canvas(recorder);
newCanvas.drawParagraph(paragraph, Offset.zero);
final picture = recorder.endRecording();
var res = await picture.toImage(100, 100);
ByteData? data = await res.toByteData(format: ImageByteFormat.png);
if (data != null) {
img = Image.memory(Uint8List.view(data.buffer));
}
setState(() {});
}
void _onPressedButton() {
getCanvasImage(controller.text);
}
}

You need to send your text through External API like this https://rapidapi.com/seikan/api/img4me-text-to-image-service/ after that you need to download the image and show it to the user

Related

How to show the full image from a drawer in flutter

I'm trying to show the full image that has been clicked on from my drawer.
I have a liste of images that I display in my drawer and What I want is that when I click on a specific image, it closes my drawer and show the image on my screen in a kind of an image slider where I can switch images directly from the opened image.
here is my code where I extract my list of images from my asset folder :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class GetImages extends StatefulWidget {
const GetImages({super.key});
#override
State<GetImages> createState() => _GetImagesState();
}
class _GetImagesState extends State<GetImages> {
List<String> imagePaths = [];
#override
void initState() {
_initImages();
super.initState();
}
Future _initImages() async {
final Map<String, dynamic> assets =
jsonDecode(await rootBundle.loadString('AssetManifest.json'));
setState(() {
imagePaths = assets.keys
.where((String key) => key.contains('photos/'))
.where((String key) => key.contains('.JPG'))
.toList();
});
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.count(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 2,
children: imagePaths
.map(
(path) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: Image.asset(path),
),
)
.toList(),
);
});
}
}
And here is my code for my drawer :
import 'package:flutter/material.dart';
import 'package:myapp/widgets/get_images.dart';
import 'package:image_viewer/image_viewer.dart';
class SideBar extends StatelessWidget {
const SideBar({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const Center(
child: Text('My Page!'),
),
drawer: Drawer(
child: InkWell(
child: GetImages(),
onTap: () {
//ImageViewer.showImageSlider(images: ["assets/photos/IMG_4100.JPG"]);
// montre la photo et ferme la sidebar
Navigator.pop(context);
},
),
),
);
}
}
Thanks in advance for your help :)
You could try this package that i've used before https://pub.dev/packages/lightbox seems like it does exactly what you are looking for.

How to convert text inserted into textformfield into image in a flutter?

I am having Textformfield where user can type text and on a button tap i want to convert inserted text into image and display it on a some other screen.
Any help would be highly appreciated.
I tried using third party screenshot package but i want it without third party package or API
You can get an image of some widget by finding widget's RenderObject and converting it to an image. Then you can save this image in the state and use in other places.
Below is an example:
class _HomeState extends State<Home> {
final GlobalKey _globalKey = GlobalKey();
Widget? _image;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
if (_image != null) _image!,
RepaintBoundary(
key: _globalKey,
child: TextField(),
),
TextButton(
onPressed: () async {
final boundary = _globalKey.currentContext?.findRenderObject();
if (boundary is RenderRepaintBoundary) {
final uiimage = await boundary.toImage();
final pngBytes = await uiimage.toByteData(format: ImageByteFormat.png);
setState(() {
_image = Image.memory(
Uint8List.view(pngBytes!.buffer)
);
});
}
},
child: Text('Cheese'),
)
],
),
);
}
}

Flutter - select only single item in list view

In my app I am generating a ListView and items can be highlighted by tapping on them. That works fine and I also have a callback function that gives me the key for the just selected item. I can currently manually deselect the item by tapping on it again, but will ultimately take that functionality out.
My problem is that I want one and only one item to be selected at a time. In order to create the list I currently take some initial content in the form of a list, generate the tiles and add them to another list. I then use that list to create the ListView. My plan was on the callback from a new selection, run through the list of tiles and deselect them before highlighting the new chosen tile and carrying out the other functions. I have tried various methods to tell each tile to deselect itself but have not found any way to address each of the tiles. Currently I get the error:
Class 'OutlineTile' has no instance method 'deselect'.
Receiver: Instance of 'OutlineTile'
Tried calling: deselect()
I have tried to access a method within the tile class and to use a setter but neither worked so far. I am quite new to flutter so it could be something simple I am missing. My previous experience was with Actionscript where this system would have worked fine and I could access a method of an object (in this case the tile) easily as long s it is a public method.
I'd be happy to have another way to unselect the old item or to find a way to access a method within the tile. The challenge is to make the tiles show not highlighted without them being tapped themselves but when a different tile is tapped.
The code in my parent class is as follows:
class WorkingDraft extends StatefulWidget {
final String startType;
final String name;
final String currentContent;
final String currentID;
final List startContent;
WorkingDraft(
{this.startType,
this.name,
this.currentContent,
this.currentID,
this.startContent});
#override
_WorkingDraftState createState() => _WorkingDraftState();
}
class _WorkingDraftState extends State<WorkingDraft> {
final _formKey = GlobalKey<FormState>();
final myController = TextEditingController();
//String _startType;
String _currentContent = "";
String _name = "Draft";
List _startContent = [];
List _outLineTiles = [];
int _counter = 0;
#override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
void initState() {
super.initState();
_currentContent = widget.currentContent;
_name = widget.name;
_startContent = widget.startContent;
_counter = 0;
_startContent.forEach((element) {
_outLineTiles.add(OutlineTile(
key: Key("myKey$_counter"),
outlineName: element[0],
myContent: element[1],
onTileSelected: clearHilights,
));
_counter++;
});
}
dynamic clearHilights(Key myKey) {
_outLineTiles.forEach((element) {
element.deselect(); // this throws an error Class 'OutlineTile' has no instance method 'deselect'.
Key _foundKey = element.key;
print("Element Key $_foundKey");
});
}
.......
and further down within the widget build scaffold:
child: ListView.builder(
itemCount: _startContent.length,
itemBuilder: (context, index) {
return _outLineTiles[index];
},
),
Then the tile class is as follows:
class OutlineTile extends StatefulWidget {
final Key key;
final String outlineName;
final Icon myIcon;
final String myContent;
final Function(Key) onTileSelected;
OutlineTile(
{this.key,
this.outlineName,
this.myIcon,
this.myContent,
this.onTileSelected});
#override
_OutlineTileState createState() => _OutlineTileState();
}
class _OutlineTileState extends State<OutlineTile> {
Color color;
Key _myKey;
#override
void initState() {
super.initState();
color = Colors.transparent;
}
bool _isSelected = false;
set isSelected(bool value) {
_isSelected = value;
print("set is selected to $_isSelected");
}
void changeSelection() {
setState(() {
_myKey = widget.key;
_isSelected = !_isSelected;
if (_isSelected) {
color = Colors.lightBlueAccent;
} else {
color = Colors.transparent;
}
});
}
void deselect() {
setState(() {
isSelected = false;
color = Colors.transparent;
});
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Row(
children: [
Card(
elevation: 10,
margin: EdgeInsets.fromLTRB(10.0, 6.0, 5.0, 0.0),
child: SizedBox(
width: 180,
child: Container(
color: color,
child: ListTile(
title: Text(widget.outlineName),
onTap: () {
if (widget.outlineName == "Heading") {
Text("Called Heading");
} else (widget.outlineName == "Paragraph") {
Text("Called Paragraph");
widget.onTileSelected(_myKey);
changeSelection();
},
),
........
Thanks for any help.
Amended Code sample and explanation, that builds to a complete project, from here:
Following the advice from phimath I have created a full buildable sample of the relevant part of my project.
The problem is that the tiles in my listview are more complex with several elements, many of which are buttons in their own right so whilst phimath's solution works for simple text tiles I have not been able to get it working inside my own project. My approach is trying to fundamentally do the same thing as phimath's but when I include these more complex tiles it fails to work.
This sample project is made up of three files. main.dart which simply calls the project and passes in some dummy data in the way my main project does. working_draft.dart which is the core of this issue. And outline_tile.dart which is the object that forms the tiles.
Within working draft I have a function that returns an updated list of the tiles which should show which tile is selected (and later any other changes from the other buttons). This gets called when first going to the screen. When the tile is tapped it uses a callback function to redraw the working_draft class but this seems to not redraw the list as I would expect it to. Any further guidance would be much appreciated.
The classes are:
first class is main.dart:
import 'package:flutter/material.dart';
import 'package:listexp/working_draft.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: WorkingDraft(
startType: "Basic",
name: "Draft",
currentID: "anID",
startContent: [
["Heading", "New Heading"],
["Paragraph", "New Text"],
["Image", "placeholder"],
["Signature", "placeholder"]
],
));
}
}
Next file is working_draft.dart:
import 'package:flutter/material.dart';
import 'package:listexp/outline_tile.dart';
class WorkingDraft extends StatefulWidget {
final String startType;
final String name;
final String currentContent;
final String currentID;
final List startContent;
final int selectedIndex;
WorkingDraft(
{this.startType,
this.name,
this.currentContent,
this.currentID,
this.startContent,
this.selectedIndex});
#override
_WorkingDraftState createState() => _WorkingDraftState();
}
class _WorkingDraftState extends State<WorkingDraft> {
int selectedIndex;
String _currentContent = "";
String _name = "Draft";
List _startContent = [];
var _outLineTiles = [];
int _counter = 0;
int _selectedIndex;
bool _isSelected;
dynamic clearHilights(int currentIndex) {
setState(() {
_selectedIndex = currentIndex;
});
}
updatedTiles() {
if (_selectedIndex == null) {
_selectedIndex = 0;
}
_currentContent = widget.currentContent;
_name = widget.name;
_startContent = widget.startContent;
_counter = 0;
_outLineTiles = [];
_startContent.forEach((element) {
_isSelected = _selectedIndex == _counter ? true : false;
_outLineTiles.add(OutlineTile(
key: Key("myKey$_counter"),
outlineName: element[0],
myContent: element[1],
myIndex: _counter,
onTileSelected: clearHilights,
isSelected: _isSelected,
));
_counter++;
});
}
#override
Widget build(BuildContext context) {
updatedTiles();
return Scaffold(
body: Center(
child: Column(children: [
SizedBox(height: 100),
Text("Outline", style: new TextStyle(fontSize: 15)),
Container(
height: 215,
width: 300,
decoration: BoxDecoration(
border: Border.all(
color: Colors.lightGreenAccent,
width: 2,
),
borderRadius: BorderRadius.circular(2),
),
child: ListView.builder(
itemCount: _startContent.length,
itemBuilder: (context, index) {
return _outLineTiles[index];
},
),
),
]),
));
}
}
and finally is outline_tile.dart
import 'package:flutter/material.dart';
class OutlineTile extends StatefulWidget {
final Key key;
final String outlineName;
final Icon myIcon;
final String myContent;
final int myIndex;
final Function(int) onTileSelected;
final bool isSelected;
OutlineTile(
{this.key,
this.outlineName,
this.myIcon,
this.myContent,
this.myIndex,
this.onTileSelected,
this.isSelected});
#override
_OutlineTileState createState() => _OutlineTileState();
}
class _OutlineTileState extends State<OutlineTile> {
Color color;
// Key _myKey;
bool _isSelected;
#override
void initState() {
super.initState();
_isSelected = widget.isSelected;
if (_isSelected == true) {
color = Colors.lightBlueAccent;
} else {
color = Colors.transparent;
}
}
void deselect() {
setState(() {
_isSelected = widget.isSelected;
if (_isSelected == true) {
color = Colors.lightBlueAccent;
} else {
color = Colors.transparent;
}
});
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Row(
children: [
Card(
elevation: 10,
margin: EdgeInsets.fromLTRB(10.0, 6.0, 5.0, 0.0),
child: SizedBox(
width: 180,
child: Container(
color: color,
child: ListTile(
title: Text(widget.outlineName),
onTap: () {
if (widget.outlineName == "Heading") {
Text("Called Heading");
} else if (widget.outlineName == "Paragraph") {
Text("Called Paragraph");
} else if (widget.outlineName == "Signature") {
Text("Called Signature");
} else {
Text("Called Image");
}
var _myIndex = widget.myIndex;
widget.onTileSelected(_myIndex);
deselect();
},
),
),
),
),
SizedBox(
height: 60,
child: Column(
children: [
SizedBox(
height: 20,
child: IconButton(
iconSize: 30,
icon: Icon(Icons.arrow_drop_up),
onPressed: () {
print("Move Up");
}),
),
SizedBox(height: 5),
SizedBox(
height: 20,
child: IconButton(
iconSize: 30,
icon: Icon(Icons.arrow_drop_down),
onPressed: () {
print("Move Down");
}),
),
],
),
),
SizedBox(
height: 60,
child: Column(
children: [
SizedBox(
height: 20,
child: IconButton(
iconSize: 20,
icon: Icon(Icons.add_box),
onPressed: () {
print("Add another");
}),
),
SizedBox(
height: 10,
),
SizedBox(
height: 20,
child: IconButton(
iconSize: 20,
icon: Icon(Icons.delete),
onPressed: () {
print("Delete");
}),
),
],
),
),
],
),
);
}
}
Thanks again
Instead of manually deselecting tiles, just keep track of which tile is currently selected.
I've made a simple example for you. When we click a tile, we just set the selected index to the index we clicked, and each tile looks at that to see if its the currently selected tile.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(body: Home()),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int selectedIndex;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item: $index'),
tileColor: selectedIndex == index ? Colors.blue : null,
onTap: () {
setState(() {
selectedIndex = index;
});
},
);
},
);
}
}

How to prevent calling http request everytime we click into the page on bottom navigation bar in flutter?

On the home page I have 4 different api calls fetching 4 different data from a wordpress site. The current way I have coded is that everytime we enter home page, in the initState(), the get _getHomePageData() function is called where the async api fetching is happening. while this is happening allDataLoaded boolean is set to false in the first place.
Once the data is loaded allDataLoaded is set to true, the loading stops and the widgets are shown.
Here is the homepage widget:
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final String homePageLatestArtworkApi =
'https://example.com/wp-json/wp/v2/artworks?
per_page=1&_embed';
final String homePageAllArtworkApi =
'https://example.com/wp-json/wp/v2/artworks?
per_page=6&_embed';
final String homePageAllEventsApi =
'https://example.com/wp-json/wp/v2/events?
per_page=6&_embed';
final String homePageAllVenuesApi =
'https:example.com/wp-json/wp/v2/venues?
per_page=6&_embed';
List homePageLatestArtwork;
List homePageAllArtworks;
List homePageAllEvents;
List homePageAllVenues;
var allDataLoaded = false;
#override
void initState(){
super.initState();
print('init state is called everytime the page is loaded');
_getHomePageData();
}
Future<String> _getHomePageData() async{
var responseLatestArtwork = await http.get(Uri.encodeFull(homePageLatestArtworkApi));
var responseAllArtworks = await http.get(Uri.encodeFull(homePageAllArtworkApi));
var responseAllEvents = await http.get(Uri.encodeFull(homePageAllEventsApi));
var responseAllVenues = await http.get(Uri.encodeFull(homePageAllVenuesApi));
setState(() {
//latest artwork
var convertDataToJsonLatestArtwork = json.decode(responseLatestArtwork.body);
homePageLatestArtwork = convertDataToJsonLatestArtwork;
//All Artworks
var convertDataToJsonAllArtworks = json.decode(responseAllArtworks.body);
homePageAllArtworks = convertDataToJsonAllArtworks;
// All Events
var convertDataToJsonAllEvents = json.decode(responseAllEvents.body);
homePageAllEvents = convertDataToJsonAllEvents;
//All venues
var convertDataToJson = json.decode(responseAllVenues.body);
homePageAllVenues = convertDataToJson;
if(homePageLatestArtwork != null && homePageAllArtworks != null && homePageAllEvents != null && homePageAllVenues != null){
allDataLoaded = true;
}
// print('converted data is here');
//print(homePageLatestArtwork);
//print('the title is here :');
//print(homePageLatestArtwork[0]['title']['rendered']);
//print(homePageLatestArtwork[0]['_embedded']['wp:featuredmedia'][0]['source_url']);
});
#override
Widget build(BuildContext context) {
if(allDataLoaded){ //wait for the data to load and show spinning loader untill data is completely loaded
return Scaffold(
// body: Text('title'),
// body: Text("title: ${homePageLatestArtwork[0]['title']['rendered']} "),
body: Container(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// Expanded(
Container(
height: 200.0,
child: Image.network(homePageLatestArtwork[0]['_embedded']['wp:featuredmedia'][0]['source_url'],
fit: BoxFit.fill,
width: double.maxFinite,),
),
Container(
padding: EdgeInsets.only(left:15.0,right:15.0,top:10.0),
child: Text(homePageLatestArtwork[0]['title']['rendered'],textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 20.0,
fontFamily: 'Montserrat-Regular',
color: Color(0XFF212C3A),
fontWeight: FontWeight.bold
),),
),
])
),
),
);
}else{
return new Center(
child: new CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color> .
(Theme.of(context).primaryColor),
),
);
}
} //end of _HOMEPAGESTATE
I would like to not load every single time the home page is viewed, or let's say I just want to fetch the api data once when the app starts and let users manually pull down to refresh the data.
Method 1:
If you are just talking about data then you should have a singleton object that you can init once in initState();
class _HomePageData {
var allDataLoaded = false;
String contents = "";
Future<String> _getHomePageData() async {
// Assuming contents is the data model and you load the data into contents
this.contents = "Loaded";
this.allDataLoaded = true;
return this.contents;
}
}
final _HomePageData data = _HomePageData();
class _HomePageState extends State<HomePage> {
String contents;
#override
void initState(){
super.initState();
if (!data.allDataLoaded) {
data._getHomePageData().then((contents) {
setState(() {
this.contents = contents;
})
});
} else {
this.contents = data.contents;
}
}
}
Method 2:
Previously I was dealing with tabs that constantly reload every time I move to another tab. Flutter actively remove state when they are not attached to any active widget tree. The idea is to have the widget in a Stack, placed into Offstage & TickerMode to control visibility and animation.
class MyTabState extends State<MyTabPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: MyBottomBar(
onTab: _onTab,
currentIndex: _currentIndex,
),
body: Stack(
children: List.generate(3, (index) {
return Offstage(
offstage: _currentIndex != index,
child: TickerMode(
enabled: _currentIndex == index,
child: getChild(index),
),
);
}, growable: false),
),
);
}
}
I hope I am not enough late. Anyhow if anyone else get the same situation not to refresh again and again you can add the following line at the end of your state. For example
with AutomaticKeepAliveClientMixin
It should be like this:
class _HomeScreenState extends State<HomeScreen>
with AutomaticKeepAliveClientMixin
then you can add an override
#override
bool get wantKeepAlive => true;
You are ready to rock.

Flutter default image not loading

New to flutter. Working on a personal project. Stuck with a small issue related to show images. Here is my widget code which I'm using for showing images.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cached_network_image/cached_network_image.dart';
class UserProfile extends StatefulWidget {
#override
UserProfileState createState() => new UserProfileState();
}
class UserProfileState extends State<UserProfile> {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Map userDetails = {};
String profileImgPath;
#override
void initState() {
super.initState();
getUserDetails();
}
Future<Null> getUserDetails() async {
try {
final SharedPreferences prefs = await _prefs;
this.userDetails = json.decode(prefs.getString('user'));
if (prefs.getString('user') != null) {
if (this.userDetails['isLoggedIn']) {
setState(() {
this.profileImgPath = this.userDetails['profileImg'];
print('Shared preference userDetailsss : ${this.userDetails}');
});
}
} else {
print('Shared preference has no data');
}
} catch (e) {
print('Exception caught at getUserDetails method');
print(e.toString());
}
}
#override
Widget build(BuildContext context) {
Widget profileImage = new Container(
margin: const EdgeInsets.only(top: 20.0),
child: new Row(
children: <Widget>[
new Expanded(
child: new Column(
children: <Widget>[
new CircleAvatar(
backgroundImage: (this.profileImgPath == null) ? new AssetImage('images/user-avatar.png') : new CachedNetworkImageProvider(this.profileImgPath),
radius:50.0,
)
],
)
)
],
)
);
return new Scaffold(
appBar: new AppBar(title: new Text("Profile"), backgroundColor: const Color(0xFF009688)),
body: new ListView(
children: <Widget>[
profileImage,
],
),
);
}
}
What I'm trying to do is, show the default user-avatar.png image as long as CachedNetworkImageProvider don't get original image. But, it's bit behaving differently.
Whenever I'm opening the page - I'm getting a blank blue box then suddenly the original image from CachedNetworkImageProvider comes up.
Can't able to understand what's happening.
#Jonah Williams for your reference -
CachedNetworkImage can't be used for backgroundImage property because it does not extends ImageProvider. You can create a custom CircleAvatar like described below to use the CachedNetworkImage package:
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
class CustomCircleAvatar extends StatelessWidget {
final int animationDuration;
final double radius;
final String imagePath;
const CustomCircleAvatar({
Key key,
this.animationDuration,
this.radius,
this.imagePath
}) : super(key: key);
#override
Widget build(BuildContext context) {
return new AnimatedContainer(
duration: new Duration(
milliseconds: animationDuration,
),
constraints: new BoxConstraints(
minHeight: radius,
maxHeight: radius,
minWidth: radius,
maxWidth: radius,
),
child: new ClipOval(
child: new CachedNetworkImage(
errorWidget: (context, url, error) => Icon(Icons.error),
fit: BoxFit.cover,
imageUrl: imagePath,
placeholder: (context, url) => CircularProgressIndicator(),
),
),
);
}
}
And how to use:
body: new Center(
child: new CustomCircleAvatar(
animationDuration: 300,
radius: 100.0,
imagePath: 'https://avatars-01.gitter.im/g/u/mi6friend4all_twitter?s=128',
),
),
Maybe it is not the better way. But, it works!
(I'm assuming that CachedNetworkImageProvider is actually CachedNetworkImage from this package).
This line of code will always display the second image.
(this.profileImgPath == null)
? new AssetImage('images/user-avatar.png')
: new CachedNetworkImageProvider(this.profileImgPath)
Since profileImagePath is not null, the AssetImage is never created. Even if it was, as soon as it's not the cached network image will replace it before it has loaded. Instead, use the placeholder parameter of the network image. This will display your asset image until the network image loads.
new CachedNetworkImage(
placeholder: new AssetImage('images/user-avatar.png'),
imageUrl: profileImgPath,
)