I have simplified this question please have a look :---
How can I add OnTap event,ICONS & TITLES to below List view code
ListView.builder(
padding: EdgeInsets.all(10.0),
shrinkWrap: false,
itemCount: 200,
itemBuilder: (BuildContext context, int index) {
return listItem(context, index);
},
Widget listItem(BuildContext context, int index) {
return Card(
child: Row(
children: <Widget>[
Container(margin: EdgeInsets.all(10),child: Text("1")),
Container(height: 20,width: 1,color: Colors.blue,),
Container(margin:EdgeInsets.all(10),child: Text("ram ram ram"))
],
),
);
}
Consider changing your Containers with ListTiles, check out the documentation on ListTile. It has an onTap parameter that you can set in order to trigger a function when a ListTile is tapped, and it also has leading, title, and subtitle parameters, where you can pass the icons and titles you need.
Another way of adding onTap detector to any widget is wrapping it with a GestureDetector, or an InkWell, which is basically a GestureDetector with animations and color effects, roughly speaking. Both GestureDetector and InkWell have onTap parameters that you can use to detect taps and trigger functions.
Related
I am developing a Flutter app and would like to keep my button always in the bottom of the screen UNLESS what is in top of it is high enough to make the screen scroll. Examples:
Example A (what is on top of the button does not have height enough to scroll the screen)
Example B (what is on top of the button has height enough to scroll the screen, so the button will just go offscreen and allow the screen to scroll)
So summarizing: the button should be forced to stay at the bottom of the screen when the rest of the list is shorter than the device height, but if the list height is greater than the device height the button should behave normally and stay below the list.
What I tried:
Using a ListView, which will normally scroll if necessary, but I couldn't find a way to send the button to the botton of the screen;
Using a Column. With the help of a Spacer I could make the button go to the bottom of the screen, but a Column will not scroll, and if I add a SingleChildScrollViewto wrap it, the Spacer will no longer work because SingleChildScrollView has the potential to have infinite height;
Thanks.
I got it. The right way of doing this is using LayoutBuilder, ConstrainedBox, IntrinsicHeight and Expanded, like this:
(In this example, _widgets is a list of widgets that I want it to be on top. _buttons is a list of buttons that I want to be in the bottom)
return Scaffold(
appBar: buildAppBar(),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
Expanded(
child: Column(
children: _widgets,
),
),
Column(
children: _buttons,
)
],
),
),
),
);
},
),
);
The documentation says to avoid this, though, as it can be expensive. You can read more about this solution and other details in the documentation.
Stack(
children:[
//Use list widget,
yourList.length<7? Postioned(
bottom :10, margin from bottom
child: //button widget):Container()
])
In listbuilder
ListView.builder(
physics: ScrollPhysics(),
itemCount: yourList+1,
itemBuilder: (BuildContext ctxt, int index) {
if (index== yourList.length) {
return yourList.length >7? //your button widget:Container();
} else {
return //list item}
});
i have a simple listview in flutter
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
}
);
when i click/tap on it, there is a circle ripple effect that then expand to the rest of the element i clicked in the list. i would like to change this behavior and remove the circle ripple effect. instead when someone click on an element of the list, i want that element to highlight and fade away for the whole element. one examples is whatsapp app. when you click on a conversation, you will see that the element you click in the list will flash with ripple effect of the full element. you will see a rectangle ripple effect not a circle ripple effect where you click and then expands to the rest of the element
how can i change the default behavior on listview in flutter? if im not clear, let me know
thanks in advance
In the 8 number line in your code snippet
return the InkWell() class instead of Container()
like this
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, i) {
return InkWell(
onTap: (){},
child: Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
);
},
),
For more information visit flutter.dev Documentation
I'm using Rubber library at the moment, do you know an approach without using 3rd parts libraries?
The Bottom Sheet must be persistent (not dismissable, not triggered by any button instead, always displayed) and draggable (It must be expanded and collapsed by dragging gestures)
Perhaps DraggableScrollableSheet could work?
I haven't yet tried it out myself, but maybe you could fiddle with a listview to make it work.
I'm guessing something like having it's child be a listview, and then limit both the max child size and the maximum scroll extent
If you do not care that the bottom sheet must snap to different positions you can use the widget from the following package (snapping_sheet) I made.
Or, if you do not want to use it as a 3rd part library, you can copy the code and use it as your own widget from repository here: Github - Snapping sheet
Use DraggableScrollableSheet. Here's an example:
Stack(
children: [
Container(), //the page under the DraggableScrollableSheet goes here
Container(
height: MediaQuery.of(context).size.height,
child: DraggableScrollableSheet(
builder: (BuildContext context, myscrollController) {
return Container(
color: Colors.blue,
child: ListView.builder(
controller: myscrollController,
itemCount: 40,
itemBuilder:(BuildContext context, int index) {
return ListTile(title: Text('Item $index',
style: TextStyle(color: Colors.black),
));
},
),
);
},
),
),
],),
I have a ListView, at the top of which I have a map, I want the map to scroll out of view when the ListView is scrolled, but I also want the user to be able to interact with the map. So scrolling should only happen when the user scrolls on the other ListView widgets and not when they scroll on the map, then I want the gesture to be applied directly to the map.
Currently though, when the user scrolls on the map, it scrolls the whole ListView.
I have tried the other suggestion that I have come across on here
In Flutter, how can a child widget prevent the scrolling of its scrollable parent?
I added a GestureDetector as suggested in the answer to the post above wrapping the map container in the sample below, however this just blocked scrolling of both the ListView and the Map when scrolling on the map. Video link https://imgur.com/SeCRzUC
Here is the widget that is returned by my build method. This code depends on the google_maps_flutter plugin.
Container(
height: MediaQuery.of(context).size.height,
child:
ListView.builder(
itemCount: 12 + 1,
itemBuilder: (context, index) {
if (index == 0) return GestureDetector(
onVerticalDragUpdate: (_){},
child: Container(
height: MediaQuery.of(context).size.height / 2,
child: GoogleMap(initialCameraPosition: initalPosition),
),
);
else return ListTile(title: Text("$index"),);
}
)
),
I had hoped the map would capture gestures but it doesn't, the listview which contains it captures all. Could anyone suggest how I could force all gestures for this item in the list to be passed directly to the map, and still have the list scroll when other items in the list are scrolled?
The accepted answer (Eset Mehmet's answer was marked as excepted as of time of writing) is way to complicated and in my case it did not even work! It provided left-to-right scrolling, panning, and scaling, however top-to-bottom scrolling still scrolled the ListView.
A real solution is very simple, since GoogleMap by default has those gesture detectors. You must just specify that gesture detection must be prioritized by GoogleMap and not ListView. This is achieved by giving GoogleMap object an EagerGestureRecognizer in the following way for example.
ListView(
children: <Widget>[
Text('a'),
Text('b'),
GoogleMap(
...,
gestureRecognizers: {
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
},
),
],
)
In this way, all gestures that happen on or over the GoogleMap object will be prioritized by GoogleMap instead of any other widget.
Edit: campovski 's answer down below is the updated answer.
Depreciated Answer:
Wrap everything with ListView if you want to move out GoogleMap widget from the screen when scrolling.
Override ListView scrolling phyics with GoogleMap gestureRecognizers.
Disable ListView.builder scrolling physics due to conflict between ListView physics.
First import the dependencies:
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
build method:
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 2,
child: GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(41, 29), zoom: 10),
gestureRecognizers: Set()
..add(
Factory<PanGestureRecognizer>(() => PanGestureRecognizer()))
..add(
Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()),
)
..add(
Factory<HorizontalDragGestureRecognizer>(
() => HorizontalDragGestureRecognizer()),
)
..add(
Factory<ScaleGestureRecognizer>(
() => ScaleGestureRecognizer()),
),
),
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: 12,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
},
)
],
),
);
}
I have tried BottomNavigationBar but it requires an Icon.
This instead is text only, sort of represents analytics history and it's scrollable.
For the bottom bar you could make your own custom widget like this:
Container(
height: 80.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: List.generate(10, (int index) {
return new Text("$index");
}),
),
),
Replace the children with actual children that you want for the ListView and adjust its wrapping to have a height that suits your need and there you go