Image to be seen big onTapping in flutter - flutter

I am getting posts from a wordpress website into a flutter app.
Each post has 3 pictures and this is the layout of the images
What I am trying to do is when I Tap on IMAGE 1 or IMAGE 2 or IMAGE 3, that image will be shown on MAIN IMAGE.
Does it makes sense?

i Hope That Below Code help you. in following code i used network image but you can also used assert images to.
import 'package:flutter/material.dart';
void main() => runApp(new Demo());
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> with TickerProviderStateMixin {
String image1 = "http://via.placeholder.com/350x150";
String image2 = "http://via.placeholder.com/200x150";
String image3 = "http://via.placeholder.com/200x150";
String currentMainImage = "http://via.placeholder.com/350x150" ;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("table demo"),
),
body: new Container(
child: new Column(
children: <Widget>[
Container(
height:150.0,
child: new Image.network(currentMainImage,fit: BoxFit.fill,)
),
new Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap : (){
setState(() {
currentMainImage = image1;
});
},
child: new Image.network(image1)
)
),
Expanded(
child: InkWell(
onTap : (){
setState(() {
currentMainImage = image2;
});
},
child: new Image.network(image2)
)
),
Expanded(
child: InkWell(
onTap : (){
setState(() {
currentMainImage = image3;
});
},
child: new Image.network(image3)
)
),
],
)
],
)
)
)
);
}
}

You need to use a stateful widget
You may use Column and Row to achieve that layout.
And Image to display the images within the layout.
You may specifically use Image.network(url) constructor to show images from your word press site.
The image1, image2 and image3 can be wrapped in a InkWell widget. And InkWell's onTap can have code to update the url/image of the Main Image widget within a setState()
Hope that helps!

Related

Icon does not changed on tapping in flutter custom widget

I have created a custom widget for list tile where I need to change icon of fav_outline to fav or google but it does not change, although items are adding and removing working properly but only icon does not change..it was working well before I created a custom widget for it
I have BottomNavigation for two screens alimonies and fav movies like that...
when I click on fav icon of all movie screen...it adds to fav movie ,,that's working fine, but only icon does not change
here is my coding of custom widget and my all movie screen..both are stateful
class MyCard extends StatefulWidget {
final Movie e;
final VoidCallback onfavtab;
MyCard({required this.e,required this.onfavtab});
#override
State<MyCard> createState() => _MyCardState();
}
class _MyCardState extends State<MyCard> {
#override
Widget build(BuildContext context) {
return Card(
child: ListTile(
title: Text(widget.e.name.toString()),
subtitle: Text(widget.e.language),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: userlist[0].favmovies.contains(e)==true?Icon(Icons.favorite): Icon(Icons.favorite_outline),onPressed: widget.onfavtab),
IconButton(onPressed: (){}, icon: Icon(Icons.delete)),
],
),
leading: CircleAvatar(
backgroundImage: NetworkImage(widget.e.imageurl),
),
),
);
}
}
and here is my allmovie screen coding where I call custom widget
lass _AllMoviesState extends State<AllMovies> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(children: movielist.map((e) => MyCard(e: e, onfavtab: (){
if(userlist[0].favmovies.contains(e)==true)
userlist[0].favmovies.remove(e);
else
userlist[0].favmovies.add(e);
//looks like this is not working
setState(() {
print(userlist[0].favmovies);
});
},
)).toList(),),
);
}
}
put the icon which you need to edit it in provider class
and whene you click it just change the icon and notify it.

setState() or markNeedsBuild() called when widget tree was locked

Flutter
i am trying to display a widget into Stack IF an condition (true or false ) , and it work with no problems
but when i need to change the condition bool into SetState to hide the Widget again , it is also work but with annoying error messages whish is setState() or markNeedsBuild() called when widget tree was locked.
my code is so complicated but i am gonna show a simple similar example
bool displayWidget = false;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Stack(
children: [
Container(
child: TextButton(
onPressed: () {
final result = await FilePicker.platform.pickFiles(allowMultiple: false );
if (result == null) return;
final path = result.files.single.path;
setState(() => displayWidget = true);
},
child: Text ("studio")
),
),
displayWidget?
GestureDetector(
onTap: ()=> setState(() => displayWidget = false), // the error happen when i click here
child: Container(
child: Image.asset("here is the picture in full secreen"),
),
):Container()
],
),
);
}
}
i know there is a photo viewer better than this way :D but i only give a simple example for other real case
First of all I would like to ask you where is #override? Did you forget to add that in your question? If yes then that error might have something to do with that. If no then try declaring the bool value above #override.
please see if this example can be helpful to you (I simplified yours just a little bit more so it can be easily run in dartpad).
in your case onPressed function should contain your file picking logic and have a return type as you expect it to be (probably, String?) and check if returned value isn't null, then show your image
class MyWidget extends StatefulWidget {
#override
State<MyWidget> createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
bool displayWidget = false;
bool onPressed(bool isShown) {
//instead of this mocked function pickFile here
return !isShown;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
children: [
Container(
child: TextButton(
onPressed: () {
displayWidget = onPressed(displayWidget);
setState(() => displayWidget);
},
child: Text ("Show or hide text"),
),
),
if(displayWidget)
GestureDetector(
onTap: ()=> setState(() => displayWidget = !displayWidget),
child: Container(
child: Text('This text is to be shown'),
),
),
],
),
);
}
}
I found the solution from the official website of flutter
simply wrap set state into
in this solution would be for most cases
if(!mounted) {
setState
}
or
if(mounted) { // depends on your widget case
setState
}
source https://www.kindacode.com/article/flutter-error-setstate-called-after-dispose/
if not , try this
WidgetsBinding.instance
.addPostFrameCallback((_) => setState(() {}));
source https://www.thetopsites.net/article/50288698.shtml
and i find same error with many answers in stackoverflow
press below
Flutter setState() or markNeedsBuild() called when widget tree was locked

Show download percentage in the Flutter Circular Progress Indicator

I am using Flutter advance_pdf_viewer package to show PDF files that are loaded from the URL. At the first time open, The PDF files are downloaded in the application cache and the next time onwards loaded from the cache. Now I am using CircularProgressIndicator() to show the download progress. I want to add the progress percentage here to give the user better visibility of the progress. How can I do that?
Here is my code:
import 'package:flutter/material.dart';
import 'package:advance_pdf_viewer/advance_pdf_viewer.dart';
#override
_MyBanBook createState() => _MyBanBook();
}
class _MyBanBook extends State<BanBook> {
bool _isLoading = true;
PDFDocument document;
#override
void initState() {
super.initState();
loadDocument();
}
loadDocument() async {
document = await PDFDocument.fromURL('http://www.africau.edu/images/default/sample.pdf');
setState(() => _isLoading = false);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
toolbarHeight: 20,
),
body: Center(
child: _isLoading
? Center(child: CircularProgressIndicator())
: PDFViewer(
document: document,
zoomSteps: 1,
),
),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 85.0,
),
),
),
);
}
}
You can do it by specifying the value property in the CircularProgressIndicator like this :
CircularProgressIndicator(
value: _progress,
//width of the width of the border
strokeWidth: 20,
// color of value
valueColor: Colors.amber
);
u can use flutter_cached_pdfview
and this an example to view a pdf from URL and cache it with placeholder
u can replace placeholder with any widget like CircularProgressIndicator
PDF().cachedFromUrl(
'http://africau.edu/images/default/sample.pdf',
placeholder: (progress) => Center(child: CircularProgressIndicator())
)
take a look https://pub.dev/packages/flutter_cached_pdfview

Flutter oddly not reloading widget

I have been working with flutter just a while now but I have never experienced such a weird problem. basically I'm checking if there is a logged on username show them the main page and if not show them the signup page. after the user signs up (and logs in at the same time) I want to take him to my main page. even though I return a new Scaffold the mobile screen doesn't change at all. not with a hot load or anything. but after stopping the program and running it again (because the user is logged in) it automatically goes to my main page (which I want to do without having to stop the program and running it again. any ideas why this is happening couldn't find anything related to this.
import 'package:sociagrowapp/models/user.dart';
import 'package:sociagrowapp/Authenticate/SignIn.dart';
import 'package:sociagrowapp/HomePages/Home.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Wrapper extends StatefulWidget{
#override
createState() => _Wrapper();
}
class _Wrapper extends State<Wrapper> {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
// return either the Home or Authenticate widget
if (user == null){
print('Should Changed 3');
return Scaffold(
body: SignIn()
);
}
else {
print('Should Changed');
print('Should Changed2');
return PageData()
}
}
}
Just in case I will add the PagesData Code but I don't think it is related to that.
import 'package:flutter/material.dart';
import 'package:sociagrowapp/services/auth.dart';
int selectedbotnavi = 0;
class DailyTasks extends StatefulWidget
{
#override
createState() => _DailyTasks();
}
class _DailyTasks extends State<DailyTasks>
{
Widget build(BuildContext context)
{
return Center(
child: Text("15")
);
}
}
class Settings extends StatefulWidget
{
#override
createState() => _Settings();
}
class _Settings extends State<Settings>
{
String _httpdataretrieved;
Widget build(BuildContext context)
{
return Column(
children: <Widget>[
Container(width:MediaQuery.of(context).size.width,
child: Text('Your Account Username',style: TextStyle(fontWeight: FontWeight.w400),),
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 20, 0, 0),
),
Container(width:MediaQuery.of(context).size.width,
child: Text(' Important: Your Account must be public for SociaGrow. \n There are limited Features available to private Accounts',style: TextStyle(fontWeight: FontWeight.w900,fontSize:14),
),
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 5, 0, 20),
),
Container(child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
),
width: MediaQuery.of(context).size.width * 0.8,
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 15),
),
Container(
child: RaisedButton(
child: Text('Change Username'),
),
)
],
);
}
}
List <Widget> Pages = [new DailyTasks(),new DailyTasks(),new DailyTasks()];
class PageData extends StatefulWidget
{
#override
createState() => _PageData();
}
class _PageData extends State<PageData>
{
void _changeselectbotnaviindex(int index)
{
selectedbotnavi = index;
setState(() {
});
}
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(title: Container(
child: Image.asset('assets/Logo.png',width: 100,height: 200,),
padding: EdgeInsetsDirectional.fromSTEB(0, 10, 0 , 0),
),
actions: <Widget>[
FlatButton(
child: Text('Sign out'),
onPressed: () async {
await this._auth.signOut();
},
),
],
),
body: Pages[selectedbotnavi],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items :[
BottomNavigationBarItem(icon: Icon(Icons.timelapse),title:Text('Daily Tasks')),
BottomNavigationBarItem(icon: Icon(Icons.call_made),title:Text('Growth')),
BottomNavigationBarItem(icon: Icon(Icons.settings),title:Text('Settings')),],
currentIndex: selectedbotnavi,
onTap: _changeselectbotnaviindex,
selectedItemColor: Colors.amber[800],
unselectedItemColor: Colors.black,
showUnselectedLabels: true,
)
);
}
}
That is not the way you navigate to a new page in Flutter.
In Flutter, the way to navigate between pages is with Navigator, which is a widget that manages a set of child widgets with a stack discipline. That is, Navigator has everything ready for you to navigate between pages easily. When you create an app with MaterialApp, Flutter attaches a Navigator to the top of the widget tree for you under the hood. This way, you can access the Navigator in your widget tree via context, by calling Navigator.of(context).
In your case, when the user taps the sign up button in your sign up page, you should do something like:
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => PageData()));
This way, your app will navigate to PageData when the user signs in.
Check out this Flutter.dev article on navigating pages for more details on the topic.
You have to call SetState() so your build method is called again.
You could add a VoidListener to your SignIn(onLogin:(){setState(() {});})

Fix last element of ListView to the bottom of screen

I am trying to implement a custom navigation drawer using Flutter. I would like to attach log out option to the bottom of the drawer. The problem is that number of elements above log out option is unknow (from 3 to 17).
So if these widgets take half of the space of a drawer, then log out option will be on the bottom, and if there is too much of them and you have to scroll to see them all, then the log out option will be simply the last.
I am also trying to give the first two options a green background color. Which widget tree would you recommend me? I had a thought about the ListView widget, it takes List of widgets as an argument in constructor.
Therefore I can solve the different background color for the first two items. But I still can't figure out how to attach the log out option to the bottom. In this case it's at the bottom of drawer, but it can happen, that other options will be bigger than screen size and in that case, it should be placed at the bottom of whole list.
EDIT: I've add a design to the question. The logout option is the one called Odhlášení. In this case it's at the bottom of drawer, but it can happen, that other options will be bigger than the screen size and in that case, it should be placed at the bottom of whole list.
Design:
You can simply use ListView to manage the "17" navigation options. Wrap this ListView inside an Column. The ListView will be the first child of the Column the second child, therefore placing at the bottom, will be your logout action.
If you are using transparent widgets (like ListTile) inside your ListView to display the navigation options, you can simply wrap it inside a Container. The Container, besides many other widgets, allows you to set a new background color with its color attribute.
Using this approach the widget tree would look like the following:
- Column // Column to place your LogutButton always below the ListView
- ListView // ListView to wrap all your navigation scrollable
- Container // Container for setting the color to green
- GreenNavigation
- Container
- GreenNavigation
- Navigation
- Navigation
- ...
- LogOutButton
Update 1 - Sticky LogOutButton :
To achieve the LogOutButton sticking to the end of the ListView you'll neeed to do two things:
Replace the Expanded with an Flexible
Set shrinkWrap: true inside the ListView
Update 2 - Spaced LogOutButton until large List:
Achieving the described behavior is a more difficult step. You'll have to check if the ListView exceeds the screen and is scrollable.
To do this I wrote this short snippet:
bool isListLarge() {
return controller.positions.isNotEmpty && physics.shouldAcceptUserOffset(controller.position);
}
It will return true if the ListView exceeds its limitations. Now we can refresh the state of the view, depending on the result of isListViewLarge. Below again a full code example.
Standalone code example (Update 2: Spaced LogOutButton until large List):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: MyDrawer(),
),
);
}
}
class MyDrawer extends StatefulWidget {
#override
_MyDrawerState createState() => _MyDrawerState();
}
class _MyDrawerState extends State<MyDrawer> {
ScrollController controller = ScrollController();
ScrollPhysics physics = ScrollPhysics();
int entries = 4;
#override
Widget build(BuildContext context) {
Widget logout = IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () => {setState(() => entries += 4)});
List<Widget> navigationEntries = List<int>.generate(entries, (i) => i)
.map<Widget>((i) => ListTile(
title: Text(i.toString()),
))
.toList();
if (this.isListLarge()) { // if the List is large, add the logout to the scrollable list
navigationEntries.add(logout);
}
return Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // place the logout at the end of the drawer
children: <Widget>[
Flexible(
child: ListView(
controller: controller,
physics: physics,
shrinkWrap: true,
children: navigationEntries,
),
),
this.isListLarge() ? Container() : logout // if the List is small, add the logout at the end of the drawer
],
),
);
}
bool isListLarge() {
return controller.positions.isNotEmpty && physics.shouldAcceptUserOffset(controller.position);
}
}
Standalone code example (Update 1: Sticky LogOutButton):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: MyDrawer(),
),
);
}
}
class MyDrawer extends StatefulWidget {
#override
_MyDrawerState createState() => _MyDrawerState();
}
class _MyDrawerState extends State<MyDrawer> {
int entries = 4;
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Flexible(
child: ListView(
shrinkWrap: true,
children: List<int>.generate(entries, (i) => i)
.map((i) => ListTile(
title: Text(i.toString()),
))
.toList(),
),
),
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () => {setState(() => entries += 4)})
],
),
);
}
}
Standalone code example (Old: Sticking to bottom):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: MyDrawer(),
),
);
}
}
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
children: List<int>.generate(40, (i) => i + 1)
.map((i) => ListTile(
title: Text(i.toString()),
))
.toList(),
),
),
IconButton(icon: Icon(Icons.exit_to_app), onPressed: () => {})
],
),
);
}
}