When keyboard open/close at that time ChangeNotifierProvider call multiple time - flutter

I am facing issue When keyboard open/close at that time ChangeNotifierProvider call multiple time so my full screen reload multiple time. In this widget I have attach video so widget is calling so many times then my instance is fail.
return Scaffold(
backgroundColor: ColorManager.colorBackgroundGray,
body: ChangeNotifierProvider<CreateRouteStep2ViewModel>(
create: (BuildContext context) => modelProvider,
builder: (context, snapshot) {
printValue(label: "ChangeNotifierProvider", value: "");
return Consumer<CreateRouteStep2ViewModel>(
builder: (context, provider, c) {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
provider.viewType == CreateRouteStep2ViewType.map
? SizedBox(
height: 300,
child: GoogleMapForCreateRoute(
modelProvider: modelProvider),
)
: const SizedBox(),
],
),
)
],
),
Expanded(
flex: 1,
child: Container(
color: ColorManager.colorWhite,
child: SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 10),
itemCount: provider.listRouteName.length,
itemBuilder: (BuildContext context, index) {
return CreateStepsItem(
routeModel:
provider.listRouteName[index],
modelProvider: modelProvider,
index: index,
removeIndex: () {
// Todo Remove index from marker pin and location array.
modelProvider
.removeIndexFromPinAndList(index);
},
edtLocationNameFocus: () {
modelProvider.focusMap(index);
},
edtAudioFocus:
(mainPosition, subPosition) {
modelProvider.focusAudioComponent(
index, subPosition);
},
edtVideoFocus:
(mainPosition, subPosition) {
modelProvider.focusVideoComponent(
index, subPosition);
},
);
},
scrollDirection: Axis.vertical,
),
),
)),
Visibility(
visible:
MediaQuery.of(context).viewInsets.bottom == 0,
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(
left: 24.0, right: 24.0, bottom: 20.0),
child: CommonButton(
onPressed: () {},
lable: AppStrings.constTourSpichern,
isEnable: false,
),
),
),
)
],
),
),
const SizedBox(
height: 20,
)
],
),
);
});
}),
);
Is there any widget behaviour is attach with keyboard?. If any one know that then please let me know.

Related

flutter :Inkwell not working in stack widget

I created a stack viewpager by this reference :
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
Positioned.fill(
child: Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: _itemWidth,
child: FractionallySizedBox(
child: InkWell(
onTap: () => debugPrint("clicked"), ///this part not works
child: PageViewItem(
index: _firstItemIndex,
width: _itemWidth,
url: model[_firstItemIndex],
),
),
),
),
),
),
SizedBox(
height: 250,
child: PageView.builder(
padEnds: false,
controller: _controller,
itemBuilder: (context, index) {
return Opacity(
opacity: index <= _firstItemIndex ? 0 : 1,
child: PageViewItem(
index: index,
width: _itemWidth,
url: model[index],
),
);
},
itemCount: model.length,
),
),
],
),
],
in this part :
InkWell(
onTap: () => debugPrint("clicked"), ///this part not works
child: PageViewItem(
index: _firstItemIndex,
width: _itemWidth,
url: model[_firstItemIndex],
),
),
onTap Not working because is under PageView.builder . do you have any idea to fix this issue?
That's because top widget in the stack, stack works as a layers, the last child in the children list will be the greatest zIndex one, so any widget below it is not accessible, you need to bring it to front to activate the click, swap the children and making the InkWell's positioned Widget the last child in the children will solve your issue
Stack(
children: [
SizedBox(
height: 250,
child: PageView.builder(
padEnds: false,
controller: _controller,
itemBuilder: (context, index) {
return Opacity(
opacity: index <= _firstItemIndex ? 0 : 1,
child: PageViewItem(
index: index,
width: _itemWidth,
url: model[index],
),
);
},
itemCount: model.length,
),
),
Positioned.fill(
child: Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: _itemWidth,
child: FractionallySizedBox(
child: InkWell(
onTap: () => debugPrint("clicked"), ///this part not works
child: PageViewItem(
index: _firstItemIndex,
width: _itemWidth,
url: model[_firstItemIndex],
),
),
),
),
),
),
],
),

How To Add TabBar with Horizontal And Vertical ListView In One Tab Scrolling In Respective Directions

Flutter newbie here if my code looks too messy. Managed to figure out a few basic layouts and have implemented a TabBar. In 2nd Tab(COMICS). I have a horizontal ListView and a vertical one. I just can't figure out how to make the horizontal ListView scroll without changing tabs.
How i create the tabs:
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text('NestedScrollView'),
)
];
},
body: Scaffold(
appBar: AppBar(
toolbarHeight: 40,
centerTitle: true,
backgroundColor: Color(0xFFb92136),
title: Text('Kata Kata African Cartoons'),
// actions: [
// IconButton(onPressed: () {}, icon: Icon(Icons.search)),
// IconButton(onPressed: () {}, icon: Icon(Icons.more_vert))
// ],
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
text: "VIDEOS",
),
Tab(
text: "COMICS",
),
Tab(
text: "MAGAZINE",
),
],
),
),
body: TabBarView(
controller: tabController,
children: [
VideosTab(),
ComicsTab(),
Magazines(),
],
),
));
Main body of comics tab
return Column(children: [
Container(child: Card(
elevation: 20,
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text("Katakata Long Comics"))
]),
Card(
child: StreamBuilder(
stream: ref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
lists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
lists.add(values);
});
return Container(
height: 200,
child: new ListView.builder(
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String pdfurl = lists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFViewer(
url: pdfurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: [
Container(
height: 100,
width: 100,
child: Image(
image:
NetworkImage(lists[index]["image"]),
),
),
Text(lists[index]["name"]),
],
),
],
),
),
),
);
},
),
);
}
return Container(child: Text("Add Plants"));
},
),
),
],
),
)),
Container(child: Card(
elevation: 20,
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text("Continuous Humour"))
]),
Card(
child: StreamBuilder(
stream: secref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
seclists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
seclists.add(values);
});
return new ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: seclists.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String pdfurl = seclists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFViewer(url: pdfurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 200,
width: 400,
child: Image(
image:
NetworkImage(seclists[index]["image"]),
),
),
Text(seclists[index]["name"]),
],
),
),
),
);
},
);
}
return Container(child: Text("Add Plants"));
},
),
),
],
),
)),
]);
You have NeverScrollableScrollPhysics() defined as the physics for your listviews. That means they won't scroll even when there is no tabview around them. Also they won't absorb the scroll event and defer them to the tabview.

Flutter Visibility with Condition (How can I hide only one widget with condition)

I have a problem with using Visibility widget.
What I want to do is hiding certain listview's by depending user's click on my Row. But when User click on row, all Listview is showing. When clicked again, all listview widget's are going away.
What I want to do is with images:
This is how my page looks
This is what happens when I click on arrow button or "Sezon 1" Text
This is what I want to do when I click on arrow button or "Sezon 1" Text
What I'm trying to do is When I click Season 2, it will show season 2 episodes. When I click season 3 it will show season 3 episodes etc.
Here is my code (I know It's a little messy for right now, apologize for that) :
GestureDetector is working same for every click.
bool viewVisible = false;
void hideWidget() {
setState(() {
viewVisible = !viewVisible;
print(viewVisible);
});
StreamBuilder<QuerySnapshot>(
stream: seasons.snapshots(),
builder:
(BuildContext context, AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.hasError) {
return Center(
child:
Text('Error'));
} else {
if (asyncSnapshot.hasData) {
List<DocumentSnapshot> listOfDocumentSnap =
asyncSnapshot.data.docs;
return Padding(
padding: const EdgeInsets.only(top: 0, left: 0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount: listOfDocumentSnap.length,
itemBuilder: (context, index) {
var episodes = firestore
.collection('shows')
.doc(data.id)
.collection('Seasons')
.doc(listOfDocumentSnap[index].id)
.collection('Episodes');
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 0, left: 18, right: 18),
child: GestureDetector(
onTap: () {
hideWidget();
},
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(
8),
border: Border.all(
color: Colors.pink)),
child: Row(
children: [
SizedBox(
width: 20,
),
Text(
listOfDocumentSnap[index]
.get('name')
.toString()
.toUpperCase(),
style: TextStyle(
fontSize: 20,
color:
Colors.grey[800],
fontWeight:
FontWeight.w700),
),
Spacer(flex: 1),
Icon(
Icons.arrow_drop_down,
size: 45,
color: Colors.pink,
),
],
),
),
),
),
StreamBuilder<QuerySnapshot>(
stream: episodes.snapshots(),
builder: (BuildContext context,
AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.hasError) {
return Center(
child: Text(
'Error'));
} else {
if (asyncSnapshot.hasData) {
List<DocumentSnapshot>
listOfDocumentSnap =
asyncSnapshot.data.docs;
return Padding(
padding:
const EdgeInsets.only(
top: 5, left: 18.0),
child: Visibility(
visible: viewVisible,
child: Align(
alignment:
Alignment.topLeft,
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount:
listOfDocumentSnap
.length,
itemBuilder:
(context,
index) {
return ListTile(
onTap: () {
setState(
() {
selectedIndex =
index;
});
},
trailing:
Icon(Icons
.play_arrow),
title: Text(listOfDocumentSnap[
index]
.id
.toString()),
);
/* return Text(
listOfDocumentSnap[
index]
.get(
'name'));*/
},
),
],
),
),
),
);
} else {
return Center(
child:
CircularProgressIndicator());
}
}
},
),
SizedBox(
height: 30,
)
],
);
},
),
],
),
),
);
} else {
return Center(child: CircularProgressIndicator());
}
}
},
),
Sorry, I did not check what is wrong with your code. But, instead of writing your own hide/show logic for each row, try to use Flutter's ExpansionTile widget. It will handle the expanded/collapsed states for you:
https://medium.com/flutterdevs/expansion-tile-in-flutter-d2b7ba4a1f4b
There are two different way I know to handle widget visibility. Create a bool to switch visibility. I'm using _show.
Using if condition
inside (column or any widget)
if (_show) Container(),
Using Visibility Widget
Column(
children: [
Visibility(
visible: _show,
child: Container(),
),
)

Flutter - Container width and height fit parent

I have a Card widget which includes Column with several other Widgets. One of them is Container.
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Container(
width: 300,
height: 200,
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
)),
),
],
);
}
Here, if I don't specify width and height I get error. But, is there a way to make them to fit parent element?
EDIT
Full code:
return ListView(
children: <Widget>[
Center(
child: Container(
child: Card(
margin: new EdgeInsets.all(20.0),
child: new Container(
margin: EdgeInsets.all(20.0),
width: double.infinity,
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: Column(
children: <Widget>[
FormBuilderDropdown(
onChanged: (t) {
setState(() {
text = t.vrsta;
});
},
validators: [FormBuilderValidators.required()],
items: user.map((v) {
return DropdownMenuItem(
value: v,
child: ListTile(
leading: Image.asset(
'assets/img/car.png',
width: 50,
height: 50,
),
title: Text("${v.vrsta}"),
));
}).toList(),
),
],
),
),
Container(child: _renderWidget()),
text.isEmpty
? Container()
: RaisedButton(
child: Text("Submit"),
onPressed: () {
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value.toString());
print(formData.startLocation);
getAutocomplete();
}
},
)
],
),
)),
),
),
],
);
}
Just set the height and width property of your Container to double.infinity
Solution Code:
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Container(
width: double.infinity,
height: double.infinity,
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
)),
),
],
);
}
You are using ListView inside Column which is why you need to specify height in your Container to prevent errors.
The best way is to use Expanded or Flexible as parent of your ListView
Expanded(
child: ListView.builder(...)
)
Update:
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Expanded(
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
),
),
),
],
);
}

How to make ListView Items align at bottom of a container with a fixed height without using reverse in Flutter?

In my Flutter project, I have a container with a fixed height. Inside that container I have a Listview.
Here's the code-
return new Scaffold(
appBar: AppBar(
title: Text("All Values"),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
height: isLoading ? 50.0 : 0,
color: Colors.white70,
child: Center(
child: new CircularProgressIndicator(),
),
),
Expanded(
child: Container(
height: 350,
color: Colors.red,
alignment: Alignment.bottomLeft,
child:
new ListView.builder(
itemCount: data.length-8,
itemBuilder: (BuildContext cxtx, int index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0.0, 10, 0),
child: Container(
child: showCard(index, radius),
),
);
},
controller: _scrollController,
),
),),
],
),
resizeToAvoidBottomPadding: false,
);
The code outputs like below-
So, the problem is I want to align these items at bottom left of the container. I could have done that using reverse: true but I need the list items with the same sequence. So, I need suggestion how can I do that?
You need those items in a row or a column? Follow with a row possibility:
Try this:
return new Scaffold(
appBar: AppBar(
title: Text("All Values"),
),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
if(isLoading)
Container(
height: 50.0 ,
color: Colors.white70,
child: Center(
child: new CircularProgressIndicator(),
),
),
Expanded(
child: Container(
height: 350,
color: Colors.red,
alignment: Alignment.bottomLeft,
child: new ListView.builder(
itemCount: data.length - 8,
itemBuilder: (BuildContext cxtx, int index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0.0, 10, 0),
child: Container(
child: Text('asdf'),
),
);
},
controller: _scrollController,
),
),
),
],
),
resizeToAvoidBottomPadding: false,
);
StoreConnector<_ViewModel, List<Message>>(
converter: (store) {
// check mark ,reverse data list
if (isReverse) return store.state.dialogList;
return store.state.dialogList.reversed.toList();
},
builder: (context, dialogs) {
// Add a callback when UI render after. then change it direction;
WidgetsBinding.instance.addPostFrameCallback((t) {
// check it's items could be scroll
bool newMark = _listViewController.position.maxScrollExtent > 0;
if (isReverse != newMark) { // need
isReverse = newMark; // rebuild listview
setState(() {});
}
});
return ListView.builder(
reverse: isReverse, // 反转列表,insert数据时,刷新到0,加载更多时,滚动偏移不变
controller: _listViewController,
itemBuilder: (context, index) => _bubbleItem(context, dialogs[index], index),
itemCount: dialogs.length,
);
},
)