How to make a container 'lighten' on hold / on tap in Flutter? - flutter

I am trying to create an app with a scroll view and the objects are clickable like the google news app. Can anyone answer how to animate the container to have a white glow on holding the tile?
Here is the list view builder I have for the app
Container(
padding: EdgeInsets.only(top: 16),
child: ListView.builder(
physics: ClampingScrollPhysics(),
itemCount: article.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
return news_tile(
imageurl: article[index].urlToimage,
news_title: article[index].title,
news_desc: article[index].description,
web_url: article[index].url
);
}),
)
and this is the contents of the tile which the list view builder calls
class news_tile extends StatelessWidget {
String imageurl, news_title, news_desc,web_url;
news_tile({this.imageurl, this.news_title, this.news_desc,this.web_url});
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => article_view(
web_url: web_url,
)
));
},
child: Container(
margin: EdgeInsets.only(bottom: 16),
child: Column(
children: <Widget>[
ClipRRect(borderRadius: BorderRadius.circular(6), child: Image.network(imageurl)),
SizedBox(
height: 8,
),
Text(news_title, style: TextStyle(fontSize: 17,fontWeight: FontWeight.w600)),
SizedBox(
height: 8,
),
Text(news_desc, style: TextStyle(color: Colors.black54))
],
),
),
);
}
}

You could go with the InkWell Widget. It provides a tapping/holding color effect similar to that. Have a look at the official docs here:
https://api.flutter.dev/flutter/material/InkWell-class.html
Note that you need a Material Widget as an ancestor of your InkWell, but the docs explain that more.
Hope it works for you!
Edit: Sorry, since you are working with a Container, Ink is also important for you:
https://api.flutter.dev/flutter/material/Ink-class.html
Check the docs section "The ink splashes aren't visible!" for why that is.

Related

How can I prevent options view of the RawAutocomplete widget from overflowing on screen in Flutter?

I'm currently using a custom widget similar to this chips_input library. However, I don't want to give the options view (the popup list) a static maximum height. What I want to achieve is to dynamically set a maximum height of screen height - popup y offset. In this way, bottom of the options view will be at the bottom of the screen and all of the content inside the options view will be visible through scrolling. Is there any that I can access the textfield's or options view's offset to calculate the height?
My autocomplete widget looks similar to this:
RawAutocomplete<T>(
...
optionsViewBuilder: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: textFieldWidth,
child: Material(
elevation: 16,
child: ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final T option = options.elementAt(index);
return suggestionBuilder(context, option);
},
),
),
),
),
);
You can do this by putting a height on your SizedBox that uses MediaQuery to get the screen height:
popupOffset = 20;
RawAutocomplete<T>(
...
optionsViewBuilder: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: textFieldWidth,
height: MediaQuery.of(context).size.height - popupOffset,
child: Material(
elevation: 16,
child: ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final T option = options.elementAt(index);
return suggestionBuilder(context, option);
},
),
),
),
),
);

Use of Listview.builder makes the screen go away

I want to show Listview underneath my two widgets but when i hot reload, nothing happens and if i run again, UI shows blank screen. If i remove Listview.builder it works fine.
Below is my code.
import 'package:flutter/material.dart';
import 'package:plant_clone/constants.dart';
import 'package:plant_clone/model/model.dart';
import 'package:plant_clone/screens/home/components/header_with_searchbox.dart';
import 'package:plant_clone/screens/home/components/title_with_more_btn.dart';
import 'package:plant_clone/viewmodel/recommended_plants_viewmodel.dart';
class Body extends StatelessWidget {
RecommendedPlantViewModel recommendedPlantViewModel =
new RecommendedPlantViewModel();
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
recommendedPlantViewModel.setWidgetsData();
return SingleChildScrollView(
child: Column(
children: [
HeaderWithSearchBox(size: size),
TitleWithMoreButton(
title: "Recommended",
press: () {},
),
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Card(
child: ListTile(
onTap: (){},
title: Text('Hello'),
),
);
})
],
),
);
}
}
It doesn't look like there's any other way than setting height constraint using a SizedBox that's wrapping a ListView.
Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: size.height,
child: ListView.builder(
...
),
),
],
)
https://flutter.dev/docs/cookbook/lists/horizontal-list
i think it happened because the list view should have a height,,
the esiest way is to test that put it inside a container and give a height to it..
and the second way is wrap the listview inside a Expanded widget and it will fix ..
if not then post the error from debug log
In order to make this to work, you must wrap your ListView with a Container and define the height property as it is part of a Column. You also need to wrap the widget returned by the itemBuilder with a Container and define the width property as the scrollDirection is set to Axis.horizontal.
Container(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
width: 100,
child: Card(
child: ListTile(
onTap: () {},
title: Text('Hello'),
),
),
);
},
),
)

Need to accomodate gridView in my flutter

Im building an app that shows diets and also have a search bar to look for the diets.
I cant manage accomodate the search bar correctly like outside the gridviewer. heres the code of my view and how it actually looks. I dont want to be like another card
body: Container(
child: GridView.builder(
padding: EdgeInsets.all(15),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: dietsForDisplay.length + 1,
itemBuilder: (BuildContext context, int index) {
if (diets.length == 0) {
return Container(
child: Padding(
padding: const EdgeInsets.all(60.0),
child: Text(
"No existen Dietas registradas por la nutriĆ³loga.",
style: TextStyle(
color: Color(0xFF002D53),
fontFamily: 'Montserrat',
fontSize: 25,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
);
} else {
return index == 0
? _searchBar()
: _listItem(
context,
index - 1,
);
}
}),
));
}
and the code for the searchBar and listItem are Cards
Wrap your material app inside a Safe Area Widget
https://api.flutter.dev/flutter/widgets/SafeArea-class.html
I would suggest you to wrap your Scaffold widget with SafeArea so that your appbar won't get obstructed due to the notch. If you would want to add a search bar in your Scaffold's body, I would suggest using a Column to place your search bar on the top and your GridView.builder() on the bottom. Here is how it looks like after my suggestions:
SafeArea(
child:Scaffold(
body: Column(
children: <Widget>[
//Search Bar here
Expanded(
child: //GridView.builder() here
);
],
),
),
);
*If you want that page to be scrollable then replace Column with ListView

Flutter GridView.builder is Generating Unwanted Extra Space

I am trying to display a row of buttons. Since the number of buttons depends on the number of elements in a List, I have to use GridView.builder to dynamically create the right amount of buttons. Unfortunately it seems that GridView.builder is taking up alot of unnecessary space. Anyone know what is wrong here?
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Dice buttons
Flexible(
child: GridView.builder(
itemCount: dices.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: dices.length,
),
itemBuilder: (BuildContext context, int index) {
return new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonTheme(
minWidth: 50.0,
height: 50.0,
child: RaisedButton(
child: Text(
dices[index].toString(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
color: usedDices[index] || !expectNum
? Colors.grey
: Colors.black,
onPressed: () {
if (!usedDices[index] && expectNum) {
setState(() {
numUsed[turn] = dices[index].toString();
numUsedIndex[turn] = index;
});
expectNum = false;
usedDices[index] = true;
}
},
),
),
]);
})),
Link to Pic: https://drive.google.com/file/d/1_Jr4rz9GJ-D8-Xjxs2w8Sn8lOdnBBqTc/view?usp=sharing
As you can see are lots of unnecessary space here and it seems to be the reuslt of GridView.builder
That space is the result of Flexible, which fills the available space. You will see that if you replace it with a Container and give it a height, it won't produce that much space below.
Just had this problem, top SliverPadding is set to 20.0 by default. Looking at docs I see:
/// By default, [ListView] will automatically pad the list's scrollable
/// extremities to avoid partial obstructions indicated by [MediaQuery]'s
/// padding. To avoid this behavior, override with a zero [padding] property.
So,
GridView.builder(
// shrinkWrap: true,
padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 1,
mainAxisSpacing: 1,
crossAxisCount: 3,
),
itemBuilder: (context, index) {
return Container(
color: Colors.black,
);
},
itemCount: 10,
),
or
If you put a widget before the ListView, you should wrap the ListView with a
MediaQuery.removePadding widget (with removeTop: true)

ListView.builder show anything

AlertCardWidget is a widget that i wrote. I return it in itemBuilder but nothing shown. Here is my code:
Flexible(
child: Padding(
child: SingleChildScrollView(
child: ListView.builder(
itemCount: state.data.length,
itemBuilder: (BuildContext context, int index) {
state.data["datas"].map<Widget>((f) {
return AlertCardWidget(
positionId: "${f["8020074"]}",
shipowner: "${f["8020076"]}",
customer: "${f["8020170"]}",
salesRepresenter: "${f["8020176"]}",
operationRepresenter: "${f["8020177"]}",
textContentFontColor:
AppTheme(Theme.of(context).brightness)
.cardFontBackgroundColor,
textfont: Colors.redAccent,
);
}).toList();
},
),
),
),
),
No error to show.
I have items that why I use ListView. The problom of using Listview instead ListView.builder is taking "Vertical viewport was given unbounded height error". The problem has solved when writing Listview like child of Expanded widget. Here is my code:
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: ListView(
children: state.data["datas"].map<Widget>((f) => AlertCardWidget(positionId: "${f["8020074"]}",
shipowner: "${f["8020076"]}",
customer: "${f["8020170"]}",
salesRepresenter: "${f["8020176"]}",
operationRepresenter: "${f["8020177"]}",
textContentFontColor: AppTheme(Theme.of(context).brightness).cardFontBackgroundColor,
textfont: Colors.redAccent,)).toList(),
),
),
),
Maybe a silly question, but why are you mapping a list into a ListView.builder?
Have you tried using the index for each iteration instead?
Because what I understand from that code is that every ["datas"] item you've got will generate the whole list for as many times as state.data.length has.
Maybe try this out:
Flexible(
child: Padding(
child: SingleChildScrollView(
child: ListView.builder(
itemCount: state.data.length,
itemBuilder: (BuildContext context, int index) {
return AlertCardWidget(
positionId: state.data[index]["datas"]["8020074"],
shipowner: state.data[index]["datas"]["8020076"],
customer: state.data[index]["datas"]["8020170"],
salesRepresenter: state.data[index]["datas"]["8020176"],
operationRepresenter: state.data[index]["datas"]["8020177"],
textContentFontColor:
AppTheme(Theme.of(context).brightness)
.cardFontBackgroundColor,
textfont: Colors.redAccent,
);
},
),
),
),
),
If that doesn't work, would you mind showing us which data are you trying to retrieve?
Your itemBuilder function does not return a value.
Edit: It should return a single Widget for every entry in your list.
Something like this should work.
Also, Padding Widget is missing the padding property.
Flexible(
child: Padding(
child: SingleChildScrollView(
child: ListView.builder(
itemCount: state.data.length,
itemBuilder: (BuildContext context, int index) {
final f = state.data[index];
return AlertCardWidget(
positionId: "${f["8020074"]}",
shipowner: "${f["8020076"]}",
customer: "${f["8020170"]}",
salesRepresenter: "${f["8020176"]}",
operationRepresenter: "${f["8020177"]}",
textContentFontColor:
AppTheme(Theme.of(context).brightness)
.cardFontBackgroundColor,
textfont: Colors.redAccent,
);
},
),
),
),
),