How to use png files as icons in a Flutter app? - flutter

To be able to use my icons, I upload them to fluttericon.com but it only accepts svg files. Since my icons are in .png format, I'm using a converter to convert them into svg. After the conversion, I upload them but it seems like they are not identified correctly by fluttericon.com, yet I'm unable to see icons on the app.
There is a custom bottom navigation bar in my app and it only accepts iconData as argument. So I have to use an actual icon. I tried using the custom icon on AppBar to be able know if it's bottom navigation bar causing the problem but it's same.
I read some comments saying the content of svg matters. Cause when I download a random icon in svg format directly and upload it, it's identified properly on fluttericon.com. What do I need to do?

Use icon: Image.asset("assets/home.png")
full code example:
class MyTabBar extends StatefulWidget {
#override
_MyTabBarState createState() => _MyTabBarState();
}
class _MyTabBarState extends State<MyTabBar> with TickerProviderStateMixin {
int tabIndex=0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: tabIndex ==0 ?BottomTabBarHome()
:tabIndex == 1? BottomTabBarMail(): BottomTabBarProfile()
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Image.asset("assets/home.png", color: Colors.grey,),
activeIcon: Image.asset("assets/home.png", color: Colors.blue,),
title: Text('')
),
BottomNavigationBarItem(
icon: Image.asset("assets/mail.png", color: Colors.grey,),
activeIcon: Image.asset("assets/mail.png", color: Colors.blue,),
title: Text('')
),
BottomNavigationBarItem(
icon: Image.asset("assets/account.png", color: Colors.grey,),
activeIcon: Image.asset("assets/account.png", color: Colors.blue,),
title: Text('')
)
],
currentIndex: tabIndex,
selectedItemColor: Colors.blueAccent,
onTap: (int index){
setState(() {
tabIndex = index;
});
},
),
);
}
}
class BottomTabBarHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(" Home Screen"),
),
);
}
}
class BottomTabBarMail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Mail Screen"),
),
);
}
}
class BottomTabBarProfile extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(" Profile Screen"),
),
);
}
}

pulled some code from my old project:
basic idea is that the icon or activeIcon named parameter asks for a Widget, includes but not limited to an Icon widget.
BottomNavigationBarItem(
title: Text('REALTIME SCHEDULE'),
activeIcon: TrackIcon(colorValue: Colors.white70),
icon: TrackIcon(colorValue: Color(0xff424150)),
),
class TrackIcon extends StatelessWidget {
final Color colorValue;
TrackIcon({#required this.colorValue});
#override
Widget build(BuildContext context) {
return SizedBox(
height: 33,
width: 99,
child: Image.asset(
'images/track_icon.png',
height: 25,
color: colorValue,
),
);
}
}

Here's how I used my png images as icons:
icon: const ImageIcon(
AssetImage('assets/image.png'),
),
It worked perfectly for me :).

As the above answers are useful (with just a few lines of edit), let me simplify
Use this line of code for using you PNG icons
icon: Image.asset("assets/home.png", color: Colors.grey,)
Now go to the folder containing the files of your flutter package for bottomNavigationBar and either edit the package itself OR copy the files into a folder flutterApp/packages/your_package/[those dart files] (second option is better to test with hot reload).
Note: flutterApp is the root folder of your flutter app.
Note: If you decided to edit the package itself in flutter/.pub-cache/hosted/... then you have to stop and re-run the debugging session after each edit for it to take effect.
Note: If you decided to copy the package files in your flutterApp then add them in your pubspecs.yaml as
dependencies:
your_package:
path: packages/your_package
Now, what to edit?
Find the constructor parameter icon or whatever it is. Now change its type from IconData (mostly) to Widget and now find the usage with simple searching/looking for the keyword and adjust/fit in the changed icon parameter as a Widget.
for example, if the usage looks something like this:
Icon(
widget.icon,
...
),
change it to:
widget.icon
because Icon() is also a widget which used the earlier IconData widget.icon and as we have converted that to Widget itself we can simply use widget.icon instead of Icon().

To add png to our code
add the below lines on pubspec.yaml
assets:
- lib/images/swap.png
in main.dart use the same directory
child: Image.asset('lib/images/swap.png')

Related

Flutter GNav disappears when using Navigator.pushNamed()

I implemented an app that uses GNav from google_nav_bar.dart. Most things work fine and I really like it, i can manually switch pages by clicking on the tab icons of the navbar. But when I am trying to change the page in the code (e.g. Buttonpress or after the User did a certain action) with Navigator.pushNamed the navbar disappears. I know that this is normal bcs why should the navbar stay, but I have no idea how to manage this. There are not that many examples on the internet. Would be pretty nice if someone could help me!
Explanation of the app: the User scans a barcode of a book, and after the scan he gets redirected to the app page, where the user can find reviews to that book. And i want the navbar on that reviews page as well.
Here the simplified code where the navigation happens, the different screens just return a Scaffold, they are not implemented yet:
class MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
int _selectedIndex = 0;
static final List<Widget> _pages = <Widget>[
const ScannerScreen(),
const AllReviewsScreen(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('ReviewApp'),
),
body: _pages.elementAt(_selectedIndex),
bottomNavigationBar: Container(
color: Colors.black,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 0),
child: GNav(
gap: 8,
backgroundColor: Colors.black,
color: Colors.white,
activeColor: Colors.white,
tabBackgroundColor: Colors.grey.shade800,
padding: const EdgeInsets.all(12),
tabs: const [
GButton(
icon: Icons.qr_code_scanner,
text: 'Scanner',
),
GButton(
icon: Icons.reviews,
text: 'Alle Reviews',
),
],
selectedIndex: _selectedIndex,
onTabChange: (index) {
setState(() {
_selectedIndex = index;
});
},
),
),
),
),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/scanner':
return FadeRoute(const ScannerScreen());
case '/all_reviews':
return FadeRoute(const AllReviewsScreen());
default:
return null;
}
});
}
}
I tried to use a tabController, but GoogleNavBar has no controller, so I think it handles this another way, but I hardly found stuff on the internet, in every example they only switch screen using the navbar. Of course i could just implement the navbar on every screen, but there must be an easier way
It is obvious behavior because when you call Navigator. push it immediately pushes the UI to a new screen where your bottomAppBar is not available.
Here is an article about what you want:
Multiple Navigators with BottomNavigationBar

Flutter Feature Discovery Not SHowing Overlay

I had built an application and I'm trying to show feature discovery but, It is not showing discovery. Also not showing any error.
Question I Referred To Solve Issue
Main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) async {
runApp(
FeatureDiscovery(
child: MaterialApp(
home: SplashScreen(),
),
),
);
});
}
ServicesOffersReviewsPhotos.dart
class ServicesOffersReviewsPhotos extends StatefulWidget {
#override
_ServicesOffersReviewsPhotosState createState() =>
_ServicesOffersReviewsPhotosState();
}
class _ServicesOffersReviewsPhotosState
extends State<ServicesOffersReviewsPhotos>
with SingleTickerProviderStateMixin {
late TabController _controller;
#override
void initState() {
_controller = TabController(length: 4, vsync: this, initialIndex: 0);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kOffWhiteBackGroundColor,
appBar: AppBar(
backgroundColor: kOffWhiteBackGroundColor,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: kDarkGrey,
size: MediaQuery.of(context).size.width*0.05,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
IconButton(
icon: Icon(
Icons.favorite_border,
color: kDarkGrey,
size: MediaQuery.of(context).size.width*0.05,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.share,
color: kDarkGrey,
size: MediaQuery.of(context).size.width*0.05,
),
onPressed: () {},
),
],
),
body: SafeArea(
child: DescribedFeatureOverlay(
featureId: 'add_item_feature_id', // Unique id that identifies this overlay.
tapTarget: const Icon(Icons.add), // The widget that will be displayed as the tap target.
title: Text('Add item'),
description: Text('Tap the plus icon to add an item to your list.'),
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.black,
textColor: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children's...
],
),
),
),
);
}
}
My Application Flow
SplashScreen (PushReplacement) -> onBoardingScreen(PushReplacement) -> LoginScreen(PushReplacement) -> Home(push) -> ServicesOffersReviewsPhotos
I have tried placing feature discovery on the top of servicesoffersReviewsPhotos Scaffold but didn't get any output.
I have referred every blog on medium, youtube videos. But didn't found any solution.
Question's probably old and abandoned but I think Feature Discovery is a great plugin with a lot of potential so, here goes...
I had cause to use the feature discovery plugin and ran into the same issue. After hours of reading their documentation, it turns out that the reason it seems like nothing is happening is because once the feature is show cased once or twice, Feature discovery automatically records that you have seen it in the shared preferences without telling you.
So, you'll notice that when you uninstall the app completely and clear all data, feature discovery seems to work again the first few times until it saves to shared preference again and doesn't seem to work again.
This is the expected behaviour in production environment as it saves you the hassle to writing an onComplete callback function that involves shared preferences.
For the sake of development, they provided this function
FeatureDiscovery.clearPreferences
It essentially deletes the shared preferences data. So you can see it as many times as you want.
But the neatest way to stop auto save to shared preferences is to set this
recordStepsInSharedPreferences: false,
or this
persistenceProvider: NoPersistenceProvider(),
as an argument to the FeatureDiscovery widget like this
home: FeatureDiscovery(
recordStepsInSharedPreferences: false,
child: DemoApp()
),
If none of these work, try using only the compulsory parameters of DescribedFeatureOverlay before adding optional parameters one by one and testing each to see the faulty code.
link to the pub
Cheers.

Structure of a flutter project

How to structure a flutter project like this one:
Example restaurant pos image
Do you find this beginning of the tree structure correct:
class HomePageState extends State<HomePage>{
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Row(
children: [
Container( // menu
width:60,
color: Colors.white,
),
Expanded( // body
child: Container(
color: Colors.red,
),
),
Container( // ListProducts
width:300,
color: Colors.green,
),
],
),
backgroundColor: Color.fromARGB(255 , 244 , 246, 250),
)
);
}
}
code preview
You might want to place that MaterialApp into a separate parent widget (I think it will cause issues when using MediaQuery and Theme inside the same build method). It also might be cleaner down the line to extract every part (menu, body, ListProducts) into separate widgets.
Also, I would advise you to take a look at the LayoutBuilder widget,
and the ressources on this page if the app is meant to work on narrower screens.
Oh and if you don't know about state management, definitely check this out.

I would like to create a fixed Appbar for all my screens

I am trying to use the same Appbar for all my screens, but I don't want to add the same code many times, so I thought about creating the class MyAppbar that would have my default Appbar, so that I could use it in my screens without repeating the same code, but I don't know what I am missing, because it is giving me the following error:
The method 'Appbar' isn't defined for the class 'MyAppbar'. Try
correcting the name to the name of an existing method, or defining a
method named 'Appbar'.
This is my code:
class MyAppbar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Appbar(
centerTitle: true,
title: Center(
child: Text("Title", style: TextStyle(fontFamily: 'theboldfont'))),
actions: <Widget>[
IconButton(
icon: Icon(FontAwesomeIcons.bell),
onPressed: () {
}),
IconButton(
icon: CircleAvatar(
radius: 15,
backgroundImage: AssetImage("images/example.png")),
onPressed: () {}),
]);
}
}
Can anyone help me with this error?
Thanks!
you have a syntax error I believe. It's AppBar, not Appbar.

Changing the Bottom Navigation Bar when switching between screens in the body of a Scaffold

HomeScreen() function call the Home screen of App.
How I Can route/move to "Team", "Add", etcetera page without BottomNavigationBar and AppBar.
I want show another page and back button, with new Bottom Navigation Bar.
I have this on my Flutter Project:
class APPMain extends StatefulWidget {
#override
_APPMainState createState() => _APPMainState();
}
class _APPMainState extends State<APPMain> {
int _currentIndex = 0;
_onTapped(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
List<Widget> screens = [
HomeScreen(),
Center(child: Text("Team")),
Center(child: Text("Add")),
Center(child: Text("Search")),
Center(child: Text("Settings")),
];
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xffffffff),
iconTheme: IconThemeData(color: Colors.grey),
title: Text("Test App", style: TextStyle(color: Colors.grey),),
actions: <Widget>[
IconButton(
icon: Icon(Icons.account_circle),
onPressed: (){},
),
],
),
body: Container(
color: Color(0xfff4f4f4),
child: Center(
child: screens[_currentIndex],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
fixedColor: Colors.red,
onTap: _onTapped,
items: [
BottomNavigationBarItem(
title: Text('Home'), icon: Icon(Icons.home)),
BottomNavigationBarItem(
title: Text('Team'), icon: Icon(Icons.group)),
BottomNavigationBarItem(
title: Text('Add'), icon: Icon(Icons.add)),
BottomNavigationBarItem(
title: Text('Search'), icon: Icon(Icons.search)),
BottomNavigationBarItem(
title: Text('Settings'), icon: Icon(Icons.settings)),
]),
);
}
}
Thank you so much for help.
This is almost certainly a duplicate but I wasn't able to find a question asking something similar with a quick search so I'll answer anyways.
The answer is actually quite simple, but requires understanding a bit more about how to write flutter applications - you should be using a Navigator or the navigator built right into MaterialApp or WidgetApp rather than making your own navigation. The simplest way is to use MaterialApp's routes property and pass in a map with each of your pages. Then when you want to switch pages, you simply use Navigator.pushNamed(context, <name>) from wherever you want to switch the page (i.e. a button).
The part that can be slightly confusing when you come from other frameworks is that rather than having one Scaffold and switching the body of it, the entire page should switch and each page should have a Scaffold.
Here's an example in the documentation showing how to navigate between pages.
For the record, although it's a bad idea you could make it work with your original code as well - all you'd have to do is build a different BottomNavigationBar with different options depending on what _currentIndex is set to. But I don't recommend that. With what I've suggested you also get animations between pages, back button functionality, you can hook up analytics to track page usage, and a bunch more things that flutter provides as part of navigation.