Cupertino Sliverapp bar not scrolling - flutter

Hello guys i am working in this Platform specific flutter application and wanted have sliver like the gif listed bellow i was able to achieve part of it but the search bar is not moving with scrolling.Please help.
Widget _buildContent(context, productBloc, isIOS) {
return CustomScrollView(slivers: <Widget>\[
CupertinoSliverNavigationBar(
border: null,
backgroundColor: Colors.grey\[50\],
leading: Padding(
padding: const EdgeInsets.only(bottom: 16, left: 10),
child: Transform.scale(
scale: 4.5,
child: Image.asset('assets/images/whitelogo.png'),
),
),
largeTitle: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: \[
SizedBox(
width: MediaQuery.of(context).size.width * 0.75,
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20),
child: CupertinoTextField(
placeholderStyle: TextStyle(color: Colors.grey\[300\]),
placeholder: 'Enter Product Name',
prefix: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
FrinoIcons.f_search_2,
size: 20,
),
),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey\[300\]),
borderRadius: BorderRadius.circular(5),
color: Colors.white,
),
),
),
),
\],
),
trailing: GestureDetector(
child: const Icon(
FrinoIcons.f_cart,
color: const Color(0xFFf79B34),
size: 28,
),
onTap: () => Navigator.of(context).pushNamed('/cart'),
),
)]

Try replacing CustomScrollView with NestedScrollView:
Widget _buildContent(context, productBloc, isIOS) {
return NestedScrollView(slivers: <Widget>\[
CupertinoSliverNavigationBar(
border: null,
backgroundColor: Colors.grey\[50\],
leading: Padding(
padding: const EdgeInsets.only(bottom: 16, left: 10),
child: Transform.scale(
scale: 4.5,
child: Image.asset('assets/images/whitelogo.png'),
),
),
}
}

Related

Flutter Dismissible background goes up after list item is dismissed

I just started learning flutter and am trying to build a todo app, the problem I encountered was the widget buildActionSwipeLeft() set as dismissible background goes up rather than left to right after the list item is dismissed although I set the direction of the dismissible from left to right or start to end. Any help would be appreciated.
My code:
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(
bottom: 15.0
),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: ClipRRect(
clipBehavior: Clip.antiAlias,
child: Dismissible(
background: buildActionSwipeLeft(),
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
});
},
direction: DismissDirection.startToEnd,
key: UniqueKey(),
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 13.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
),
),
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
color: Colors.redAccent,
),
padding: const EdgeInsets.symmetric(horizontal: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
I figured out that this was not an issue as this is the default animation thats played when a list tile wrapped in a dismissible widget is dismissed. And the dismiss direction just determines the direction in which you can swipe the widget and not the direction in which the widget animates after dismissal.

automatic height of the container in the flutter

I wrote a page, at the top everything is fine, as it should be. And at the bottom I have a history of events. The width of my container is determined automatically (depending on the width of the screen), and the height - no, on different devices different heights (indents at the bottom are different). Is it possible to determine the height automatically (to the end of the screen) ?? Also, I'd like to add a scroll bar at the bottom for this container so that when events appear there, I can scroll through them both bottom and top. I will be grateful for your help.
My page:
My code:
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
color:Colors.white12
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
textColor: Colors.blueGrey,
color: Colors.transparent,
child: Text('yes',textScaleFactor: 2.5),
onPressed: null,
padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
),
FlatButton(
textColor: Colors.blueGrey,
color: Colors.transparent,
child: Text('no',textScaleFactor: 2.5),
onPressed: null,
padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
)
],
),
SizedBox(height: 15.0),
Container(
child: Text(('20000' == null ? '' : '10000'), style: TextStyle(fontSize: 45.0,color: Colors.blueGrey)),
padding: EdgeInsets.fromLTRB(0, 0.0, 0, 20.0),
),
Container(
child: Text("weight", style: TextStyle(fontSize: 20.0,color: Colors.blueGrey)),
padding: EdgeInsets.only(top: 2, bottom:40, left:0, right:0),
),
Center(
child: Container(
alignment: Alignment.center,
width: double.infinity,
height: 430,
decoration: BoxDecoration(
border: Border.all(
width: 1.5
),
borderRadius: BorderRadius.circular(25)
),
child: new Column(
children: [
Container(
child: Text("history events", style: TextStyle(fontSize: 20.0,color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)
),
],
),
)//Container
)
]
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_scanQR();
});
},
child: const Icon(Icons.qr_code),
backgroundColor: Colors.pink,
),
);
}
My scrin (after updating the code)
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
textColor: Colors.blueGrey,
color: Colors.transparent,
child: Text('yes', textScaleFactor: 2.5),
onPressed: null,
padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
),
FlatButton(
textColor: Colors.blueGrey,
color: Colors.transparent,
child: Text('no', textScaleFactor: 2.5),
onPressed: null,
padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
)
],
),
SizedBox(height: 15.0),
Container(
child: Text(('20000' == null ? '' : '10000'), style: TextStyle(fontSize: 45.0, color: Colors.blueGrey)),
padding: EdgeInsets.fromLTRB(0, 0.0, 0, 20.0),
),
Container(
child: Text("weight", style: TextStyle(fontSize: 20.0, color: Colors.blueGrey)),
padding: EdgeInsets.only(top: 2, bottom: 40, left: 0, right: 0),
),
Expanded(
child: Padding(
padding: EdgeInsets.fromLTRB(7, 0, 7, 7),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all(width: 1.5), borderRadius: BorderRadius.circular(25)),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 45,
child: Text("history events", style: TextStyle(fontSize: 25.0, color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)),
Expanded(
child: Scrollbar(
child: new ListView(
shrinkWrap: true,
children: [
Container(
child: Text("Event 1", style: TextStyle(fontSize: 50.0, color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)),
SizedBox(
height: 200,
),
Container(
child: Text("Event 2", style: TextStyle(fontSize: 50.0, color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)),
SizedBox(
height: 200,
),
Container(
child: Text("Event 3", style: TextStyle(fontSize: 50.0, color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)),
SizedBox(
height: 50,
),
],
))),
],
))))
]),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
// _scanQR();
});
},
child: const Icon(Icons.qr_code),
backgroundColor: Colors.pink,
),
);
}
You can alter the responsive height or width by using Media Query .To do that you need to wrap your Scaffold with Material App or Cupetino App which allows you to use MediaQuery .
void main() {
runApp(MaterialApp(home: MyApp()));
}
To make the list scrollable simply you can use ListView.builder
Center(
child: Container(
margin: new EdgeInsets.only(bottom: 20,right: 15,left: 15),
alignment: Alignment.center,
width: double.infinity,
height: MediaQuery.of(context).size.height/1.5,
decoration: BoxDecoration(
border: Border.all(width: 1.5),
borderRadius: BorderRadius.circular(25)),
child: new Column(
children: [
Container(
child: Text("history events",
style: TextStyle(
fontSize: 20.0, color: Colors.blueGrey)),
padding: EdgeInsets.all(2.0)),
],
),
) //Container
)
I added a little margin to make it looks better.Ofcourse you can also use MediaQuery for margin or padding if you want to.
https://i.stack.imgur.com/W6oXd.png

Dynamically expand a component and compress another component in flutter

I have the following code
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
height: 32.0,
padding: EdgeInsets.symmetric(
horizontal: 12.0, vertical: 5.0),
decoration: BoxDecoration(
color: Colors.green.shade300,
borderRadius: BorderRadius.circular(7.0),
),
child: Row(
children: <Widget>[
Flexible(
child: Text(
'Save 20%',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.poppins(
fontSize: 12.0,
color: Colors.white,
fontWeight: FontWeight.w500,
letterSpacing: 0.5,
),
),
),
],
),
),
),
SizedBox(
width: 8.0,
),
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Material(
child: InkWell(
splashColor: Colors.green.withOpacity(0.5),
onTap: () {
print('Add to cart');
if (FirebaseAuth.instance.currentUser == null) {
Navigator.pushNamed(context, '/sign_in');
return;
}
cartBloc.add(
AddToCartEvent(product.id, currentUser.uid));
},
child: Container(
width: 38.0,
height: 35.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.01),
borderRadius: BorderRadius.circular(8.0),
border: Border.all(
width: 0.8,
color: Colors.black.withOpacity(0.15),
),
),
child: Icon(
FontAwesomeIcons.cartPlus,
color: Colors.black45,
size: 18.0,
),
),
),
),
),
],
),
),
which results in the following view
I want to have the following criteria
When I click the cart icon for the first time
1. add to cart button should expand if quantity > 0
2. "You save 20%" component should compress to square box "20%"
Something like this
I would highly appreciate any kind of feedback, comments, hints, solution pointers. Thx
I think in your case you can use an AnimatedContainer class.
pseudocode
var isClickedOnCart;
AnimatedContainer(
....
width: isClickedOnCart? 100 : 20;
...
/// YOUR CODE HERE///
)
/// ONPRESSED CART CARD
onPressed(){
if(quantity > 0){
setState(){
isClickedOnCart = !isClickedOnCart;
}
}
}
You can use this. Remember that, I have used only setState.
String text = 'Save 20%';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
height: 32.0,
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 5.0),
decoration: BoxDecoration(
color: Colors.green.shade300,
borderRadius: BorderRadius.circular(7.0),
),
child: Center(
child: Text(
text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
color: Colors.white,
fontWeight: FontWeight.w500,
letterSpacing: 0.5,
),
),
),
),
SizedBox(
width: 8.0,
),
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Material(
child: InkWell(
splashColor: Colors.green.withOpacity(0.5),
onTap: () {
//here I use setState for sate management
//TODO: implement your logic to change the text
setState(() {
text = text == 'Save 20%' ? '20%' : 'Save 20%';
});
},
child: Container(
width: 38.0,
height: 35.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.01),
borderRadius: BorderRadius.circular(8.0),
border: Border.all(
width: 0.8,
color: Colors.black.withOpacity(0.15),
),
),
child: Icon(
Icons.shopping_cart,
color: Colors.black45,
size: 18.0,
),
),
),
),
),
],
),
));
}

How to change shape of leading in ListTile in Flutter?

I want to show an image in a ListTile widget which should looks something like this.
Here is my code:
Padding(
padding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 20.0),
child: Card(
color: Colors.white,
child: ListTile(
leading: Container(
child: Image.network((orientation == Orientation.portrait
? image.portrait
: image.landscape),
fit: BoxFit.cover)
),
title: Text(terms[index].title),
subtitle: Text(terms[index].videoNumber.toString() + " Videos"),
trailing: Icon(
Icons.arrow_forward_ios,
color: Colors.lightBlueAccent,
),
),
),
);
This results in below output
What should I do so the image looks spread out as above.
You can set the padding of ListTile to 0:
...
child: ListTile(
contentPadding: EdgeInsets.all(0),
leading: ...
);
But even so, you can see that the leading only take the upper half, not the entire height of the card:
...
Card(
color: Colors.blue,
child: ListTile(
contentPadding: EdgeInsets.all(0),
leading: ...
Which result in:
You can use a Stack to include both ListTile and the leading Icons but lots of things have to be hardcorded. In this case, I recommend using ClipRRect with Row:
Padding(
padding: EdgeInsets.symmetric(
vertical: 0.0, horizontal: 20.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
height: 70,
color: Colors.white,
child: Row(
children: <Widget>[
Container(
color: Colors.red,
width: 70,
height: 70,
child: Icon(Icons.cake, color: Colors.white),
),
SizedBox(width: 10),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text('Test Title'),
Text('Test Video',
style: TextStyle(color: Colors.grey))
],
),
),
Icon(Icons.arrow_forward_ios,
color: Colors.blue),
],
),
),
),
);
Result:
Widget buildCard(_user) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
child: Card(
color: Colors.blue.shade100,
child: Row(
children: <Widget>[
Container(
margin: const EdgeInsets.all(0),
decoration: BoxDecoration(
color: Colors.blue.shade200,
shape: BoxShape.rectangle,
borderRadius:const BorderRadius.only(
topLeft: Radius.circular(4.0),
bottomLeft: Radius.circular(4.0),
),
),
width: 20,
height: 73,
),
const SizedBox(width: 10),
Expanded(
child: ListTile(
title: Text('${_user.state?.email!.substring(0, 6)}'),
subtitle: Text('${_user.state?.createdAt}'),
),
),
//const Icon(Icons.arrow_forward_ios, color: Colors.blue),
],
),
),
),
);
}

Make container clickable

I want to make the whole row clickable, but the print will only show if I tap Text or Icon.
Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: Container(
width: double.infinity,
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
decoration: BoxDecoration(
border: Border.all(width: 0.5),
borderRadius: BorderRadius.all(Radius.circular(15.0))),
child: GestureDetector(
onTap: () {
print('click');
},
child: Row(
children: <Widget>[
Padding(
child: Text(
Localization.of(context).location,
style: TextStyle(fontSize: 18),
),
padding: EdgeInsets.only(left: 10.0),
),
Spacer(),
Padding(
child: Container(
child: Icon(Icons.locations),
height: 25.0,
),
padding: EdgeInsets.only(right: 15.0),
)
],
),
)))
#John Joe, I think the simplest way to make a Container clickable is by using InkWell as,
InkWell(
child: Container(
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
border: Border.all(width: 1.0, color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(5.0))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Locations', style: TextStyle(color: Colors.grey)),
Icon(Icons.edit_location, color: Colors.grey)
])),
onTap: () {
setState(() {
text = 'Locations Tapped!';
});
},
)
Try this:
Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: GestureDetector(
onTap: () {
print('click');
},
child: Container(
width: double.infinity,
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
decoration: BoxDecoration(border: Border.all(width: 0.5), borderRadius: BorderRadius.all(Radius.circular(15.0))),
child: Row(
children: <Widget>[
Padding(
child: Text(
Localization.of(context).location,
style: TextStyle(fontSize: 18),
),
padding: EdgeInsets.only(left: 10.0),
),
Spacer(),
Padding(
child: Container(
child: Icon(Icons.locations),
height: 25.0,
),
padding: EdgeInsets.only(right: 15.0),
)
],
),
),
),
);
Enclose the Widget (probably the Padding widget from your code snippet) , in GestureDetector. Basically, move GestureDetector from the current level to the Widget for which you want the tap to be detected.