Flutter: How to make chat page bottom text bar - flutter

I am trying to make a chat page on flutter that looks like this: top bar + bottom textField and send button. I have been able to make both the top appbar and the textfield with the send button, but I have not been able to position the textfield at the bottom of the page successfully. I have tried things like Align and Expand, footer, BottomNavigationBar.
The current version of the code I have pasted only shows the top Appbar. If I take out the child Row and the send button, I have a textfield at the bottom of the page. For some reason, as soon as I add the child Row in order to be able to add the send button, the entire textfield does not show up on the screen. I would appreciate any help.
Note: Since I am trying to make a chat screen, I want the middle section to be scrollable (while the top and bottom remain), where I can later add the chat bubbles.
Screenshot of code because of the bad editing of code snippet
Continuation of code snippet
"""
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ColorConstant.whiteA700,
// Top bar
appBar: AppBar(
backgroundColor: ColorConstant.deepOrange300,
title: Text("Match's Name",style: AppStyle.textstyleinterregular15.copyWith(
fontSize: getFontSize(15))),
),
body: Column(
children: [
Expanded(child: SingleChildScrollView(
child: Column(
children: [
// Bubbles
],
),
),
),
Container(
height: 45,
width: double.infinity,
color: ColorConstant.whiteA700,
child: Row(children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "Message...",
hintStyle: TextStyle(color: ColorConstant.bluegray100),
border: OutlineInputBorder(
borderSide: BorderSide(color: ColorConstant.bluegray100)
),
)
),
SizedBox(width: 15,),
// Send Button
FloatingActionButton(
onPressed: (){},
child: Icon(Icons.send,color: ColorConstant.whiteA700,size: 18,),
backgroundColor: ColorConstant.lightBlueA100,
elevation: 0,
),
]),
);
],
),
);
"""

Try this one...
bottomNavigationBar: Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 45,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: Row(
children: [
Expanded(
child: const TextField(
decoration: InputDecoration(
hintText: "Message...",
hintStyle: TextStyle(color: Colors.blue),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue)),
),
),
),
SizedBox(
width: 15,
),
// Send Button
MaterialButton(
color: Colors.red,
onPressed: () {},
child: Icon(
Icons.send,
color: Colors.white,
size: 18,
),
// backgroundColor: ColorConstant.lightBlueA100,
elevation: 0,
),
],
),
),
),

Wrap TextField with Expanded widget it'll work for you.

Related

How to add one search bar use for two tabs in flutter?

At my mobile apps homepage i have tabbar with two tabs act as category. both of those tabs display a listview with content depends on the category. (for example, a listview of book with fiction and non-fiction category.) and i want to add a single search function to search a book regardless their category.
The problem is:
One search bar can only search on one category. means the search bar can only search on fiction category. i try to add 2nd search bar in each tab but in result it act like the problem below
that whenever i click on the 2nd tab and then click on search bar, it will automatically go back to first tabs which is the default tab.
Solution that i think of:
Is to add setState so the tabs doesnt move back to default tab whenever i click on the search bar, but i dont know how.
Here is my code:
// Tab Bar MOF and CIDB
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(16),
bottomRight: Radius.circular(16)
),
color: Theme.of(context).primaryColor,
),
width: double.infinity,
child: TabBar(
controller: _tabController,
indicatorSize: TabBarIndicatorSize.tab,
indicatorPadding: EdgeInsets.all(6),
indicator: const UnderlineTabIndicator(borderSide: BorderSide(color: Colors.red, width: 100.0),
insets: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 42.0),
),
unselectedLabelColor: Colors.grey,
tabs: [
Tab(child: Text('MOF', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w300, ))),
Tab(child: Text('CIDB', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w300)))
]
),
),
SizedBox(
height: 30,
),
//Space for Tender Listview
Expanded(
child: Container(
width: double.infinity,
//Tender List tile
child: TabBarView(
controller: _tabController,
children: [
//MOF List
Column(
children: [
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: MOFs.length,
itemBuilder: (context, index) {
final MOF = MOFs[index];
return Card(
margin: EdgeInsets.fromLTRB(15, 20, 15, 20),
child: InkWell(
onTap: (){},
child: Container(
margin: EdgeInsets.all(4),
height: 200,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12),
//color: Colors.blue
),
child: Center(child: Text(MOF.title)),
),
),
);
}),
),
Container(
//color: Colors.pink,
margin: EdgeInsets.fromLTRB(150, 10, 150, 10),
child: TextField(
controller: controller,
onChanged: searchMOF,
decoration: InputDecoration(
hintText: 'Search by Keyword',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(color: Colors.green))
),
),
),
],
),
//CIDB List
Column(
children: [
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: CIDBs.length,
itemBuilder: (context, index) {
final CIDB = CIDBs[index];
return Container(
margin: EdgeInsets.all(10),
height: 200,
width: 50,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20),
//color: Colors.purple
),
child: InkWell(
onTap: (){},
child: Card
(child: Center(child: Text(CIDB.title))),
),
//List testing
);
}),
),
Container(
//color: Colors.pink,
margin: EdgeInsets.fromLTRB(150, 10, 150, 10),
child: TextField(
controller: controller,
onChanged: searchCIDB,
decoration: InputDecoration(
hintText: 'Search by Keyword',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(color: Colors.green))
),
),
),
],
),
],
),
),
),
],
),
);
}
You can make the search bar works globally by creating a parent stateful widget with search bar and child widget with tabs and tabs' body. In each tab body, you can check if search text field controller is not empty and if yes, you make only the books that contains search text appears and if no, you make the whole list appears
the whole step is too wide. i'll suggest some outline.
first of all, you have to know behaviour of ListView in flutter:
Creation and Destruction
Only visible children will be rendered in a listview. When a child is
scrolled out of view, the associated element subtree, states and
render objects are destroyed
second is the lifecycle. When you call setState it means flutter re-execute build method. the method below.
#override
Widget build(BuildContext context) {
return
thats why, everytime you call setState, the tabs is back to first tab. because it execute build method from the begining.
how to avoid rebuild entire widget is: Separate into new class.
eg:
class TabMOF extend StatelessWidget{
...
#override
Widget build(BuildContext context) {
return your MOF list
...
class TabCIBD extend StatelessWidget{
...
#override
Widget build(BuildContext context) {
return your CIBD list
then use is as a widget in your main Screen
...
body : Column(
children: [
// here will be your search bar
...
// next is your tabbar
Container(
child: TabBar(
tabs: [tab1, tab2 ]
)
Expanded(
child: TabBarView(
children:[
TabMOF(),
TabCIBD(),
]
]
with this way, your tab will not rebuild. but you have to update the List data for each tab.
if you need to rebuild your stateFullwidget tab, you can change the valuekey. article
actually its hard to explain very detail, hope you got what i mean. thank you

How should I make a text box continous instead of making a new line after it completes a line in Flutter?

I am new to flutter, and I want to put a textbox which only continues to take text without creating a new line after it reaches the screen size limit, like I want it to be scrollable in Horizontal direction if it reaches the screen size limit, so how to do that? Here is the code for only the textbox part
Expanded(
flex: 1,
child: Container(
child: Padding(
padding: EdgeInsets.fromLTRB(0, 0, 12, 25),
child: Text(
_input,
style: GoogleFonts.titilliumWeb(
fontSize: 50.0,
color: Colors.grey[800],
),
),
),
alignment: Alignment(1.0, 1.0),
),
)
Here is a solution for both a Text and a TextField:
Scrollable Text
In order to achieve this, place your scrollable content (here, your container) inside a SingleChildScrollView.
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.amber.shade300,
padding: EdgeInsets.all(16.0),
child: Text(
'Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.',
style: GoogleFonts.titilliumWeb(
fontSize: 24.0,
color: Colors.grey[800],
),
),
),
)
Scrollable TextField
Here, I used IntrinsicWidth to make the text centered with its prefixed icon and then scrollable.
Container(
height: 48.0,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0),
margin: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.amber.shade300,
border: Border.all(
color: Colors.brown,
width: 3.0,
),
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: IntrinsicWidth(
child: TextField(
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: 'Search',
border: InputBorder.none,
),
),
),
),
)
Full source code for easy copy-paste
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.amber.shade300,
padding: EdgeInsets.all(16.0),
child: Text(
'Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.',
style: GoogleFonts.titilliumWeb(
fontSize: 24.0,
color: Colors.grey[800],
),
),
),
),
),
);
}
}

How To Make a Squared App Bar Button in Flutter?

I am wondering how do we make an App Bar action button like the one in the picture. It seems that adding a background or wrapping a widget on an Icon will not achieve the look of the button in the picture below.
I made a demo of what you are trying to achieve:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
title: Text(
'Title',
),
centerTitle: true,
actions: [
// squared button/icon
Padding(
padding: const EdgeInsets.only(right: 20.0, top: 10.0, bottom: 10.0),
child: Container(
width: 35,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white.withOpacity(0.5),
),
child: Center(
child: Icon(
Icons.settings,
color: Colors.white,
),
),
),
),
],
),
body: .... YOUR WIDGETS ...
RESULT:
You can use an Icon inside a Container with equal width and heigth (so you obtain a square), then you can round it with BorderRadius to obtain that effect.
Of course you should use the color property of the Container to fill the background.

Placing the cursor at the top left of a vertically stretched TextField?

I'm trying to make a page through which the user can create a note for my Notes app. This is my build method so far:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Note"),
actions: <Widget>[
FlatButton(
child: Icon(
Icons.save,
color: Colors.white,
),
)
],
),
body: Center(
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField (
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Title",
),
textCapitalization: TextCapitalization.words,
),
SizedBox(
height: 16,
),
Expanded(
child: Container(
child: TextField (
expands: true,
maxLines: 25,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
),
)
],
),
),
)
);
}
This is how the page looks right now. How do I ensure that the cursor of the second TextField is placed at the top left and make said TextField stretch to fit the remaining height?
You should set the textAlign property of the TextField to start
textAlign: start
Edit:
based on #Andy_519's and community input please use the following
textAlignVertical: top

How to handle the flutter widget size compatible to all device?

Here I'm taking two widgets one is textfield widget and another one is Icon widget both are placed in seperate container. I'm very new to flutter, I dont know how to place two widgets parallely each other with different size. But somehow designed for my mobile but when i run my app on different mobile its widgets are overflowing.Can anybody help me out from this issue. Thanks in advance!!! For More reference see the image given.
Here is my code
Padding(
padding: const EdgeInsets.only(
top: 10.0, bottom: 4.0, right: 20.0, left: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
child: Material(
color: Colors.white,
elevation: 3.0,
// CONTAINER BACKSIDE SHADOW DEPTH
borderRadius: BorderRadius.circular(5.0),
shadowColor: Color(0xFF90A4AE),
//CONTAINER BACKSIDE SHADOW COLOR
child: Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: IconButton(
icon: Icon(
Icons.search,
color: Colors.pink,
),
onPressed: () {},
),
hintText: "Search for restaurant",
hintStyle: TextStyle(fontSize: 15),
),
onChanged: (input) {
print(input);
},
),
),
),
height: 55.0,
width: MediaQuery
.of(context)
.size
.width - 120,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(5.0),
),
),
Container(
child: Material(
color: Colors.white,
elevation: 3.0,
// CONTAINER BACKSIDE SHADOW DEPTH
borderRadius: BorderRadius.circular(5.0),
shadowColor: Color(
0xFF90A4AE),
child: IconButton(
icon: Icon(Icons.tune),
color: Colors.pink,
onPressed: () {
[enter image description here][1]
},
), //CONTAINER BACKSIDE SHADOW COLOR
),
height: 55.0,
width: MediaQuery
.of(context)
.size
.width - 300,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(5.0)),
)
],
),
),
From the screenshot and the code, I see there are two widgets in a row and the screen is overflown as it couldn't accommodate and show both of them.
There are two solutions:
To show the row children in the next line automatically if overflown.
To make the row children scrollable row-wise.
NOTE: SMLink is my custom widget. Just used here for demonstration purposes.
SOLUTION-1
The simple workaround would be to use the Wrap widget instead of the Row widget.
The Wrap widget simply takes the children who are prone to screen overflow and places them on the next line. You can set the direction, spacing etc, in addition to the options that Row widget can offer. Try it & let me know.
// By default, it behaves as Row, you can set the direction attribute to Axi.vertical to mimic the Column widget.
Wrap(
spacing: 8.0,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
alignment: WrapAlignment.center,
children:
[
SMLink(logo: 'Medium', link: Constants.LINK_MEDIUM),
SMLink(logo: 'linkedin', link: Constants.LINK_LINKEDIN),
SMLink(logo: 'facebook', link: Constants.LINK_FAEBOOK),
SMLink(logo: 'Qwiklabs', link: Constants.LINK_QWIKLABS),
],
)
SOLUTION-2
From the screenshot, the other way to fix would be by making the row scrollable. This makes UI look consistent in your case. We can use ListView widget for this.
ListView(
scrollDirection: Axis.horizontal,
children:
[
SMLink(logo: 'Medium', link: Constants.LINK_MEDIUM),
SMLink(logo: 'linkedin', link: Constants.LINK_LINKEDIN),
SMLink(logo: 'facebook', link: Constants.LINK_FAEBOOK),
SMLink(logo: 'Qwiklabs', link: Constants.LINK_QWIKLABS),
],
)