I have a chat messenger screen which looks like the given screenshot .
As you can see , bottom message is hidden behind the text input area .
The messages are listview , built using streambuilder .
I want the messages above the text input area .
https://i.stack.imgur.com/A82X2.png
return Scaffold(
appBar: AppBarMain(context),
body: Container(
child: Stack(
children: [
chatMessageList(),
Positioned(
bottom: 0,
child: Container(
color: Color(0x54ffffff),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 14, vertical: 20),
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Expanded(
child: TextField(
controller: messageController,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: ' Message!...',
hintStyle: TextStyle(color: Colors.white54),
border: InputBorder.none),
),
),
InkWell(
onTap: () {
sendMessage();
},
child: Container(
padding: EdgeInsets.all(9),
height: 40,
width: 40,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0x36FFFFFF),
Color(0xFFFFFFFF)
],
),
borderRadius: BorderRadius.circular(40)),
child: Image.asset('assets/images/send.png')),
)
],
),
),
),
)
],
),
),
);
}
}
Your structure should be something like
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: chatMessageList(),
),
MessageFieldWidget(),
],
)
This will ensure that your chatMessageList will take up all of the space available in the screen and your Message Field will take up only the space that it needs. You don't need to use Positioned or Padding.
Related
I would like to create a UI for some screens with a nav bar and FAB in flutter below:
UI design for floating Nav bar And FAB
here is what I have currently:
floatingActionButton: InkWell(
onTap: (){
log('Action Button Tapped');
},
child: Stack(
alignment: Alignment(0,-0.2),
children:[
SvgPicture.asset('assets/svg/floating_button.svg'),
SvgPicture.asset('assets/svg/floating_button_icon.svg'),
]),
),
bottomNavigationBar: Container(
color: Colors.transparent,
padding: EdgeInsets.only(bottom: 30,left: 15, right: 15),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(25)),
child: Material(
elevation: 100.0,
child: Container(
height: 55,
color: Colors.black12.withOpacity(0.15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset('assets/svg/colored_home_icon.svg'),
SizedBox(
height: 1.5,
),
Text('Home', style: GoogleFonts.outfit(
color: AppColors.primaryGreen,
fontSize: AppFontSize.s12
),)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset('assets/svg/grey_transfer_icon.svg'),
SizedBox(
height: 1.5,
),
Text('Transactions', style: GoogleFonts.outfit(
color: AppColors.homeDullText,
fontSize: AppFontSize.s12
),)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset('assets/svg/grey_more_icon.svg'),
SizedBox(
height: 1.5,
),
Text('More', style: GoogleFonts.outfit(
color: AppColors.homeDullText,
fontSize: AppFontSize.s12
),)
],
),
],
),
),
),
),
),
and here is the result:result of UI flutter code,
I need help transitioning from what I currently have to the UI requirement... Thanks.
As fast decision you can use floating_navbar lib (https://pub.dev/packages/floating_navbar, but if you want to made it by yourself, you can try this implementation (https://codenameakshay.medium.com/flutter-floating-bottom-bar-how-to-4164a9981afb).
My flutter ecommerce app is connected to Cloud Firestore backend. I have cart collection that has several documents with title as products which user adds. Each product has a field of order_status that maybe either in_cart or checked_out value. Now I want to render them on my Cart screen and Checked out screen based on the value of order_status. I am using ListView.Builder approach but as there is an itemCount I cannot render specific documents from same collection. What is correct way to do this? Should I store products on two collections?
Code:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
if (snapshot.data[index]['order_status'] == 'in_cart') {
_total = _total + snapshot.data[index]['total'];
return Container(
padding: EdgeInsets.only(bottom: 12.5),
child: Column(
children: [
Container(
height: (MediaQuery.of(context).size.height) / 7,
width: MediaQuery.of(context).size.width,
child: Container(
height: 105,
width: 85,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.black12,
),
child: Container(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
SizedBox(
width: 12.0,
),
IconButton(
icon: Image.network(
),
iconSize: 75.0,
onPressed: () {},
),
SizedBox(
width: 30.0,
),
Column(
children: [
Text(
snapshot.data[index]['title'],
style: kHeading1.copyWith(
fontSize: 22.5),
),
SizedBox(
height: 5.0,
),
Text(
'Rs.' +
snapshot.data[index]['price']
.toString() +
'/' +
snapshot.data[index]
['product_unit'],
style: kTitle1,
),
SizedBox(
height: 5.0,
),
Text(
'Total Rs.' +
snapshot.data[index]['total']
.toString(),
style: kTitle1,
),
],
),
SizedBox(
width: 20.0,
),
Row(
children: [
IconButton(
icon: Icon(
Icons.keyboard_arrow_up,
color: Colors.black,
),
onPressed: () {
increaseCart(
snapshot.data[index]
['title'],
snapshot.data[index]
['unit'],
snapshot.data[index]
['price']);
}),
Text(
snapshot.data[index]['unit']
.toString(),
style: kHeading2,
),
IconButton(
icon: Icon(
Icons.keyboard_arrow_down,
color: Colors.black),
onPressed: () {
decreaseCart(
snapshot.data[index]
['title'],
snapshot.data[index]
['unit'],
snapshot.data[index]
['price']);
}),
],
),
],
),
),
),
),
),
],
),
);
} else {
return null;
}
}),
body: StreamBuilder(
stream: Firestore.instance.collection('students').document(_userId).snapshots(),
builder: (context,snapshot) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 20.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left:20.0),
child: Align(
alignment: Alignment.centerRight,
child: CircleAvatar(
radius: 100,
backgroundColor: Colors.white,
child: ClipOval(
child: new SizedBox(
width: 180.0,
height: 180.0,
child: (_image!=null)?Image.file(
_image,
fit: BoxFit.fill,
):
Image.network(""),
),
),
),
),
),
Padding(
padding: EdgeInsets.only(top: 60.0),
child: IconButton(
icon: Icon(
Icons.camera,
size: 30.0,
),
onPressed: () {
getImage();
},
),
),
],
),
SizedBox(
height: 20.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left:40.0),
child: Align(
alignment: Alignment.center,
child: Container(
child: Column(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Text('Student Name',
style: TextStyle(
color: Colors.white, fontSize: 20.0)),
),
Align(
alignment: Alignment.center,
child: Text(snapshot.data['first_name'],
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
)),
),
],
),
),
),
),
i want to display student name from cloud firestore but it gives an error upon first loading but after hotreload the app works correctly.
here is my student id retrieving function
FirebaseAuth.instance.currentUser().then((user) {
_userId = user.uid;
});
i am using this id for retrieving a particular student details but it give error upon first loading the error are enter image description here
The database snap are enter image description here
I want to make a Button that looks like the picture above with Flutter.
But I have no idea how to make it... help me, please!
Widget _startButton(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 250.0),
child: Stack(
children: <Widget>[
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildSideButtons(context, Icons.settings, palette.limeYellow,
const EdgeInsets.only(right: 30.0)),
_buildSideButtons(context, Icons.lightbulb_outline,
palette.limeGreen, const EdgeInsets.only(left: 30.0)),
],
),
),
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.35,
height: MediaQuery.of(context).size.height,
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [palette.limeYellow, palette.limeGreen])),
))),
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.275,
height: MediaQuery.of(context).size.height,
child: new RaisedButton(
elevation: 0.0,
color: Colors.white,
child: new Text(
"START",
style: TextStyle(
fontFamily: "Bebas Neue",
fontSize: 25.0,
fontWeight: FontWeight.bold),
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => CountDown())),
shape: CircleBorder())))
],
),
);
}
Widget _buildSideButtons(
BuildContext context, IconData icon, Color coverColor, EdgeInsets pad,
{VoidCallback navigate}) {
return Container(
height: MediaQuery.of(context).size.height * 0.07,
child: RaisedButton(
elevation: 5.0,
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(50.0))),
child: Container(
child: Padding(
padding: pad,
child: Icon(icon, color: Colors.black),
),
),
color: coverColor,
textColor: Colors.white,
),
);
}
I used Stack and Raised Buttons and finally made it! Thank you for the advice. I simply need to add boxShadow to make it close to the example picture I uploaded above.
To make a similar compound Button you should use a stack widget, you can see that both the side buttons are same so they are identical buttons in a row with a BorderRadius. they design of the middle button can be done by clipping button border by half of its width and then lay it out at the middle of the row.
You can make use of an IconButton with an asset image which contain a transparent background.
IconButton(
icon: Image.asset('assets/your/transperantBG/icon.png'),
onPressed: (){},
)
Raised button taking too much width and I want to decrease according to my layout...
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
onPressed:()=>print("a"),
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Text('SORT BY',style: TextStyle(fontSize: 12.0),),
),
Icon(Icons.keyboard_arrow_down,size: 20.0,),
],
),
),
),
I got the answer
We need to add padding in Raised button for removing default padding
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
padding: const EdgeInsets.all(8.0),
onPressed: () => print("a"),
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Icon(
Icons.filter,
size: 16.0,
),
),
Text(
'FILTER',
style: TextStyle(fontSize: 12.0),
),
],
),
),
),
You are using Row widget inside your RaisedButton and it's taking the maximum width, you can fix it using the min space mainAxisSize: MainAxisSize.min like this:
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
onPressed: () => print("a"),
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Text(
'SORT BY',
style: TextStyle(fontSize: 12.0),
),
),
Icon(
Icons.keyboard_arrow_down,
size: 20.0,
),
],
),
),
),