How to change place of children widgets in Column? - flutter

I need to change the place of the widget in my UI. But I could not achieve it.
I tried this code But it does not work for me. If someone knows how to do it please help.
Change Place of BankCard Widget to Another BankCard Widget, or change the place of any widgets in a Column.
Below you can find code that I tried:
Widget nonNullBody(List<GetConversionCards> cards) {
_column=Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"fromSum".tr(),
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w700),
textAlign: TextAlign.left,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: BankCard(
card: Bank.CreditCardModel.fromUzCard(
cards[bloc.selectedIndex.value])),
),
IconButton(
icon: Icon(Icons.sync),
onPressed: () {
_key.currentState.setState(() {
Widget t=_column.children[0];
_column.children[0]=_column.children[3];
_column.children[3]=t;
});
},
),
Text("toVisa".tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700),
textAlign: TextAlign.left),
Padding(
padding: const EdgeInsets.all(8.0),
child: BankCard(
card: Bank.CreditCardModel.fromVisaCard(
cards[bloc.selectedIndex.value])),
),
],);
bloc.tokenCardUzs = cards[0].uzsCardId;
final size = MediaQuery.of(context).size;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SingleChildScrollView(
child: Container(
height: size.height - appBar().preferredSize.height + 5,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 30,
child: ValueListenableBuilder(
valueListenable: bloc.selectedIndex,
builder: (context, v, w) {
return ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: cards.length,
itemBuilder: (context, index) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(
vertical: 12.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: bloc.selectedIndex.value == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4)),
);
});
}),
),
Flexible(
fit: FlexFit.loose,
flex: 5,
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: cards.length,
onPageChanged: (_) {
bloc.tokenCardUzs = cards[_].uzsCardId;
bloc.selectedIndex.value = _;
},
itemBuilder: (BuildContext context, int index) {
return StatefulBuilder(
key: _key,
builder: (BuildContext context,
void Function(void Function()) state) {
return _column; );
}),
),
Flexible(
child: TextFieldWidget(
controller: bloc.amountFieldController,
iconData: Icons.monetization_on,
validator: null,
hintText: "enterAmount".tr(),
labelText: "dollarCurrency".tr(),
),
),
ConfirmButton(
text: 'next'.tr(),
onPressed: () {
showPopUp(context, () async {
Navigator.of(context, rootNavigator: true).pop();
waitTransactionWidget(context);
int usd =
(double.parse(bloc.amountFieldController.text) * 100)
.toInt();
bool result = await Repository.getInstance()
.convUzsUsd(bloc.tokenCardUzs, usd);
print("result conv $result");
Navigator.of(context, rootNavigator: true).pop();
Navigator.pushReplacement(
context,
PageTransition(
child: MyHomePage(),
type: PageTransitionType.fade));
},
title: Text("wouldYouLikeToExchange".tr()),
subtitle: Text("${bloc.amountFieldController.text} " +
"dollarCurrency".tr()));
},
),
],
),
),
),
);
}

I recommend you create a list that contains widgets then assign it to the childrens parameters of Column. So when you change something about the list it will change the column as well.
like this :
List<Widget> list = new List();
#override
Widget build(BuildContext context) {
Column(
children: list,
);
}
adjustWidgetList() {
setState(() {
list.add(Text("lorem ipsum"));
list.add(Text("dolar sit amet."));
.
.
.
list.remove(0);
});
}
But don't forget to make your changes inside of setState.

Related

Implement pagination in Flutter with a bloc pattern

Using the NotificationListener, I am trying to integrate pagination with the ListView.Builder, but I don't get the expected result. While the list is working, it scrolls very slowly.
The code I wrote is below
NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (_controller.position.maxScrollExtent ==
_controller.offset) {
if (state is LoghistorySuccess) {
if (logsData.length == _index) {
if (pagecount > page) {
setState(() {
page = page + 1;
print(page);
BlocProvider.of<LogHistoryBloc>(
context)
.add(LogHistoryFetchEvent(
page: page));
});
}
}
}
}
if (scrollNotification
is ScrollStartNotification) {
_onStartScroll(scrollNotification.metrics);
} else if (scrollNotification
is ScrollUpdateNotification) {
_onUpdateScroll(scrollNotification.metrics);
} else if (scrollNotification
is ScrollEndNotification) {
_onEndScroll(scrollNotification.metrics);
}
return true;
},
child: logsData.isNotEmpty
? ListView.builder(
controller: _controller,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: logsData.length,
//state.logHistoryModel.results?.logs?.length ?? 0,
itemBuilder: (context, index) {
return Padding(
padding:
const EdgeInsets.only(top: 12.0),
child: DottedBorder(
borderType: BorderType.RRect,
strokeWidth: 1,
dashPattern: [2.5, 2.5],
color:
HexColor(Constants.primary),
radius: Radius.circular(10),
child: Padding(
padding: const EdgeInsets.only(
top: 15.0,
left: 15,
right: 15,
bottom: 8.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Container(
width: MediaQuery.of(
context)
.size
.width /
2,
child: Text(
"${logsData[index].date}",
style: TextStyle(
overflow:
TextOverflow
.ellipsis,
fontWeight:
FontWeight
.w500,
fontSize: 16,
color: HexColor(
Constants
.primary),
)),
),
// Text(
// "${state.logHistoryEntity.logs?[index]["entry_date"]}",
// style: TextStyle(
// color:
// Color(0xff555B5F)),
// ),
],
),
Container(
margin: EdgeInsets.only(
top: 15,
),
child: ListView.builder(
shrinkWrap: true,
physics:
NeverScrollableScrollPhysics(),
itemCount:
logsData[index]
.log
?.length ??
0,
//state.logHistoryModel.results?.logs?[index].log?.length ?? 0,
itemBuilder:
(context, _index) {
var _data =
logsData[index]
.log?[_index];
return Padding(
padding:
const EdgeInsets
.only(
bottom:
8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
InkWell(
onTap: () {
summaryPopUp(
context,
_data!);
},
child: Text(
"• ${_data?.startTime} to ${_data?.endTime}",
style: TextStyle(
color: Color(
0xff555B5F)),
),
),
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
"${_data?.logtype}",
style: TextStyle(
color:
Color(0xffED5B2E)),
),
SizedBox(
width: 20,
),
_data?.createdDate ==
formatted
? Row(
children: [
InkWell(
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => EditLogsScreen(log: _data!),
));
},
child: ImageIcon(
AssetImage("assets/icons/pencil.png"),
color: Color(0xff18A558),
size: 20,
),
),
SizedBox(
width: 8,
),
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DeletLogConfPopUp(
logId: _data?.id,
log: logsData[_index].log,
index: _index,
);
},
);
},
child: ImageIcon(
AssetImage("assets/icons/delete_icon.png"),
color: Color(0xffE72323),
size: 18,
),
),
],
)
: Container()
],
)
],
),
);
},
),
)
],
),
)),
);
},
)
: Container(),
// Center(
// child: Column(
// children: [
// Image(
// image: AssetImage(
// "assets/images/no_task.png")),
// Text("You don't have any logs yet")
// ],
// ),
// ),
)
with this code pagination works fine but not scrolling fast.

List view childs get out of container

I am trying to make a list view only occupy part of the screen, but it keeps growing till the end not respecting the contianer constraints. I tried to use a sizedbox too but it didn' work. List tiles outside the container are shown without any widget inside, but the background is shown anyways
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: pedidos,
builder: (context, AsyncSnapshot<List<Pedido>> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: ListView.builder(
itemCount: snapshot.data!.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Hero(
tag:
"pedidos_card${snapshot.data![index].idPedido}",
child: ListTile(
tileColor: Colors.white,
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle),
child: Center(
child: Text(
style: Theme.of(context)
.textTheme
.headlineSmall,
"${snapshot.data![index].idPedido}"),
),
),
title: Text(
'Pedido: ${snapshot.data![index].idPedido}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Text(
'Estado: ${snapshot.data![index].estadoPedido.last.tipoEstadoPedido.name}'),
SizedBox(height: 10),
Text(
"Cliente: ${snapshot.data![index].cliente.nombre}")
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
trailing: Checkbox(
value: pedidosSeleccion
.contains(snapshot.data![index]),
onChanged: (bool? value) {
// value = checkboxList[index];
// setState(() {});
},
),
onTap: () {
bool isSelected = pedidosSeleccion
.contains(snapshot.data![index]);
if (isSelected) {
pedidosSeleccion
.remove(snapshot.data![index]);
} else {
pedidosSeleccion.add(snapshot.data![index]);
}
setState(() {});
},
),
));
}),
),
ElevatedButton(
onPressed: () {}, child: Text('Ver ultima milla')),
],
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
}
example
you can use Expanded instead of Sizedbox
eg:-
Column(
children:[
Expanded(flex:9,
child: ListView(
padding: const EdgeInsets.only(top: 10.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
),
),
Expanded(flex:1,
child:
ElevatedButton(
// fill in required params
),
)
])

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 NeverScrollableScrollPhysics pagenation not work

I am trying to bind NestedScrollView and GridView with pagenation.
However, I put NeverScrollableScrollPhysics() in the GridView, the pagenation function does not work.
I guess it is caused by scrollcontroller.
How can I solve this problem?
I will attach my code.
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
//infinite scroll
List<DocumentSnapshot> products = []; // stores fetched products
bool isLoading = false; // track if products fetching
bool hasMore = true; // flag for more products available or not
int documentLimit = 20; // documents to be fetched per request
DocumentSnapshot
lastDocument; // flag for last document from where next 10 records to be fetched
ScrollController _scrollController =
ScrollController(); // listener for listview scrolling
#override
void initState() {
getProducts();
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getProducts();
}
});
}
#override
void dispose() {
_scrollController?.dispose();
super.dispose();
}
getProducts() async {
//...
//get items from firebase
//...
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.backgroundwhite,
title: Image(
width: 132.0,
height: 40.0,
image: AssetImage('images/logo_horiz.png'),
),
),
body: NestedScrollView(
headerSliverBuilder: (context, isScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildListDelegate([
Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"다른 유저가 키우는",
style: TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
),
Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 5.0)),
Row(
children: <Widget>[
Text(
"율마",
style: new TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
Text(
"가 궁금하신가요?",
style: new TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
),
],
),
Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 25.0)),
Container(
color: Colors.transparent,
width: double.infinity,
height: 46,
child: FlatButton(
color: Theme.of(context).colorScheme.lightGrey,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchPage()),
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: Row(
children: <Widget>[
Icon(Icons.search,
size: 30.0, color: Colors.black12),
Padding(
padding:
const EdgeInsets.only(right: 10.0),
),
Text(
"율마",
style: new TextStyle(
fontSize: 20.0,
color: Theme.of(context)
.colorScheme
.textBlack,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
)
],
))),
]),
),
]))
];
},
body: LayoutBuilder(
builder:(BuildContext context, BoxConstraints viewportConstraints) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(children: <Widget>[
Flexible(
// this will host our Tab Views
child: GridView.builder(
// physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1.0,
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0),
controller: _scrollController,
itemCount: products.length,
itemBuilder: (context, index) {
return _buildListItem(context, products[index]);
},
)),
])));
}),
));
}
Widget _buildListItem(BuildContext context, item) {
return Hero(
tag: item.documentID,
child: Material(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPostPage(item)),
);
},
child: Image.network(item['imageUrls'][0]['url'], fit: BoxFit.cover),
),
),
);
}
}
Thank you so much
Oh! finally I have solved this problem using CustomScrollView instead of NestedScrollview.
In addition, I wraped the CustomScrollView as LayoutBuilder.
Hense the final code of the body part of Scaffold is following:
LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: CustomScrollView(
// physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
_buildHeader()
])),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1.0,
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0),
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return _buildListItem(context, products[index]);
},
childCount: products.length,
),
)
]
)
);
}),
I hope it would be helpful for you!

Handle listview item height?

So i have this script which is build a listview
class NewProductsLists extends StatelessWidget {
final List<NewProducts> newlist;
NewProductsLists({Key key, this.newlist}) : super(key: key);
final formatCurrency =
new NumberFormat.simpleCurrency(locale: "id", decimalDigits: 2);
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
itemCount: newlist.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
print("Product detail");
},
child: Card(
child: Container(
width: MediaQuery.of(context).size.width * 0.50,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.network(
Configuration.url +
"assets/app_assets/" +
newlist[index].productImage,
width: 90,
height: 90,
filterQuality: FilterQuality.low),
ListTile(
title: Center(
child: Text(
newlist[index].productName,
style: TextStyle(fontSize: 18),
)),
subtitle: Center(
child: Text(
formatCurrency.format(
int.parse(newlist[index].productPrice)),
style: TextStyle(color: Colors.red, fontSize: 15),
)),
),
],
)),
),
);
}));
}
}
and the result looks like this
[
As you can see the card is expanding so hard. I know it is because the Expanded widget. Is it possible to make the card wrap_content ?
For horizontal list view needs fixed height if its not going to be vertical scrollable view you can use Expanded widget with varying flex to get it working.
Working build widget by using expanded widget.
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
centerTitle: false,
title: const Text('November'),
),
body: new Container(
child: Column(
children: <Widget>[
new Expanded(flex: 1,child: new Container(color: Colors.grey[300],),),
Expanded(flex: 2,
child: ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
print("Product detail");
},
child: Card(
child: Container(
width: MediaQuery.of(context).size.width * 0.50,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.network(
'https://homepages.cae.wisc.edu/~ece533/images/watch.png',
width: 90,
height: 90,
filterQuality: FilterQuality.low),
ListTile(
title: Center(
child: Text(
'item Name ${index}',
style: TextStyle(fontSize: 18),
)),
subtitle: Center(
child: Text(
'\$10',
style: TextStyle(
color: Colors.red, fontSize: 15),
)),
),
],
)),
),
);
}),
),
new Expanded(flex: 3,child: new Container(color: Colors.amber[100],),),
],
)));
}
Result screen
Let me know if it suits your requirement.