How to give a gradient line in tab bar indicator - android

I have a tab bar functionality in which I show a Donut chart and list of vehicles but I need to show which tab the user selected for that I have indicatorColor in TabBar but I need to fill with gradient line as shown in the image please help me out.
PS: If possible please let me know how to give theme color means primary color in main as a gradient???
return Scaffold(
body: new DefaultTabController(
length: 2,
child: new Column(
children: <Widget>[
new Container(
width: 1200.0,
child: new Container(
color: Colors.white,
child: new TabBar(
labelColor: Colors.black,
tabs: [
Tab(
child: new Text("Visual",
style: new TextStyle(fontSize: 20.0)
),
),
Tab(
child: new Text("Tabular",
style: new TextStyle(fontSize: 20.0)),
),
],
),
),
),
new Expanded(
child: new TabBarView(
children: [
Tab(
child: new RefreshIndicator(
child: new Text('DONUT CHART'),
onRefresh: refreshList,
key: refreshKey1,
),
),
Tab(
child: new RefreshIndicator(
child: new Text('List of vehicles'),
onRefresh: refreshList,
key: refreshKey2,
),
),
],
),
),
],
),
),
);

Instead of changing core files here is a better answer that worked for me.
TabBar(
controller: tabController,
indicatorPadding: EdgeInsets.all(0.0),
indicatorWeight: 4.0,
labelPadding: EdgeInsets.only(left: 0.0, right: 0.0),
indicator: ShapeDecoration(
shape: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
width: 4.0,
style: BorderStyle.solid)),
gradient: LinearGradient(colors: [pinkLight, pinkDark])),
tabs: <Widget>[
Center(
child: Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Rating",
style: themeData.accentTextTheme.title,
),
),
),
Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Category",
style: themeData.accentTextTheme.title,
),
),
Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Friend",
style: themeData.accentTextTheme.title,
),
),
],
),
make indicator padding to zero, label padding to zero and indicatorWeight to 4.0 or your require size after that instead of using text in tabs use Container at top and give it color.

I think the only way is to create your custom TabBar.
You can copy the code of TabBar from tabs.dart and in _TabBarState you have to change Decoration get _indicator.
Something like:
return ShapeDecoration(shape: UnderlineInputBorder(), gradient: LinearGradient(
colors: [Colors.blue, Colors.green]));
UPD:
Got it. ShapeDecoration doesn't work. With it I can set gradient for whole tab. For underline - there is _IndicatorPainter class in same file. And there is Rect indicatorRect method of this class.
return Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height);
This string return rect for decoration. If you change it - you can get underline:
return Rect.fromLTWH(tabLeft, tabBarSize.height - 4.0, tabRight - tabLeft, 4.0);
And inside Decoration get _indicator don't forget change return UnderlineTabIndicator to
return ShapeDecoration(shape: RoundedRectangleBorder(), gradient: LinearGradient(
colors: [Colors.blue, Colors.green]));
And here's result

Related

How to add width to icon without Materialbutton - Flutter

I want to display a bold icon in my app, but I don't want to use a material icon since it would display a splash effect when I press on it, and I don't want that. Is there a method to make icons wider in Flutter?
My icon:-
My desire result:-
Here is my code:-
Padding(
padding: const EdgeInsets.only(left: 10),
child: Icon(
Icons.add,
color: DarkBlueColor,
),
),
Try to use font_awesome_flutter.
Example code:
FaIcon(FontAwesomeIcons.plus),
You can use icons inside the text widget and assign font size, font weight, font family and package also this makes your icon bold
Text(
String.fromCharCode(CupertinoIcons.exclamationmark_circle.codePoint),
style: TextStyle(
inherit: false,
color: Colors.red,
fontSize: 30.0,
fontWeight: FontWeight.w700,
fontFamily: CupertinoIcons.exclamationmark_circle.fontFamily,
package: CupertinoIcons.exclamationmark_circle.fontPackage,
),
)
If you can achieve the effect by simply removing the splash/ripple, you can set ThemeData.splashColor to transparent.
Theme(
data: ThemeData(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
child: Widget(), // Set your button here
);
Otherwise, if what you meant on "width" of the icon is "boldness" or "weight". Here's a workaround for that.
You can use custom icon just download the add ' + ' icon online and paste it in your assets folder.
Now use that icon like this --
Image.asset('assets/add.png', width: 25, height: 25),
Now you can set the width according to your need.
And if you want to get rid of that splash effect just set
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
hoverColor: Colors.transparent,
simply you can set the splash color to transparent
You can use, Container and RichText combo. As shown below.
InkWell(
child: Container(
width: 150,
height: 50,
decoration: BoxDecoration(color: Colors.green,border: Border.all(width: 1, color: Colors.green),borderRadius: BorderRadius.circular(25) ),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Icon(
Icons.add,
color: Colors.indigo,
size: 34,
),
Text(
"Add Offer",
style: TextStyle(color: Colors.indigo, fontSize: 20),
),
],
),
),
onTap: (){
doSomething();
},
),
void doSomething() {}
InkWell(
onTap: () {
print("object");
},
child: SizedBox(
child: Material(
shape: const CircleBorder(),
child: Container(
height: 50,
width: 180,
decoration: BoxDecoration(
color: Color(0xff59e7ba),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(25.0),
),
child: ClipRRect(
child: Align(
alignment: Alignment.centerLeft,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
Icons.add,
size: 40,
color: Colors.black,
),
Padding(
padding: EdgeInsets.only(left: 10),
child: Text(
"Add Offer",
style: TextStyle(
//set your fonts
//fontFamily: "Font2",
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
)
],
),
),
),
),
),
),
),
Theme(
data: ThemeData(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
child: InkWell(
onTap: () {},
child: Container(
height: 50,
width: 180,
decoration: BoxDecoration(
color: Color(0xff59e7ba),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(25.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
Icons.add,
size: 40,
color: Colors.black,
),
Padding(
padding: EdgeInsets.only(left: 10),
child: Text(
"Add Offer",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
)
],
),
),
), // Set your button here
)

How to create row with multiple lines in flutter

I'm trying to replicate a flutter design that looks like this, I was able to achieve something similar by using Listtile widget, my only issue was that the leading icon didn't align vertically with the title. Please is there any other way to achieve this? I tried using a row widget but the multiple line text won't fit into the screen.
You can try this code
Container(
color: Colors.white,
padding: const EdgeInsets.all(10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: Icon(
Icons.message,
color: Colors.white,
),
),
SizedBox(width: 10,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Message", style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16
),),
Text("How to create row with multiple lines in flutter How to create row with multiple lines in flutter")
],
),
),
],
),
),
Result:-
Please let me know if it work.
You can try as well as my code.
Widget ListItem({
String imageUrl,
String text,
String caption,
double imageSize = 50,
double horizontalSpacing = 15,
double verticalspacing = 20,
bool showDetailIndicatorIcon = true,
GestureTapCallback onTap,
}) {
return InkWell(
onTap: onTap,
child: Container(
margin: EdgeInsets.only(top: 2),
padding: EdgeInsets.symmetric(
horizontal: horizontalSpacing, vertical: verticalspacing),
child: Row(
children: [
ClipRRect(
child: Image.network(
imageUrl,
fit: BoxFit.cover,
height: imageSize,
width: imageSize,
),
borderRadius: BorderRadius.circular(imageSize / 2),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
text,
style: TextStyle(
color: ColorRes.lightWhite,
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(height: 5),
Text(
caption,
style: TextStyle(
color: ColorRes.grey,
fontSize: 12,
fontWeight: FontWeight.normal,
),
maxLines: 3,
),
],
),
),
),
],
),
),
);
}
I hope it's work. Please let me know.

Flutter overflow bottom when keyboard appears

i got this error and i cant get why, in a new screen i got a simple form on top (start of the column), when i focus the textfield the keyboard appears and overflow the date select and the button, but i dont know why.
Here is the initial state whiout focus on the textfield
and here is when i focus the textfield.
This is the widget i got to do this.
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
TopBarWidget(page: 'New Event', title: 'Nuevo Evento'),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: (value) {
eDisplayName = value;
},
maxLength: 18,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.sentences,
cursorColor: Color(0xFFFC4A1A),
decoration: InputDecoration(
labelText: "Nombre del Evento",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(5.0),
),
),
),
SizedBox(
height: 16.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
OutlineButton(
focusColor: Theme.of(context).primaryColor,
highlightedBorderColor: Theme.of(context).primaryColor,
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
),
textColor: Theme.of(context).primaryColor,
onPressed: () => _selectDate(context),
child: Text('Cambiar Fecha'),
),
Text(
"${formatedDate(selectedDate.toLocal())}",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryColor),
),
// Text("${selectedDate.toLocal()}"),
],
),
SizedBox(
height: 16.0,
),
RaisedButton(
disabledColor: Colors.grey[200],
disabledTextColor: Colors.black,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0)),
onPressed: eDisplayName.length == 0
? null
: () {
// print(newEvent);
Navigator.pop(context);
},
child: Text(
'ACEPTAR',
// style: TextStyle(fontSize: 20),
),
),
],
),
),
],
)),
);
Yo can set to false the resizeToAvoidBottomInset in your Scaffold()
Like this
return Scaffold(
resizeToAvoidBottomInset: false,
body: // ...
// ...
)
Documentation reference: Scaffold - resizeToAvoidBottomInset
It's beginner level problem. Don't know why most tutorial don't cover this problem before showing TextField Widget.
Column widget is fixed and does not scroll. So change Column to ListView. And do nothing else. The Widget will gain scroll feature and overflow problem will not happen anymore.

Add bottom border of to tabs in Flutter

What I'm trying to do is adding a bottom border of tabBar, so it will be under tabs title and above the indicatorColor and for both active and Inactive tabs, just like the attached image.
Red line is what I am trying to add, green line is the indicatorColor.
Note, usually I do this for appBar using 'bottom' but here bottom is reserved to the TabBar.
Is this possible?
Thanks a lot
You can set the AppBar shape property as abdulrahmanAbdullah says. But if you strictly need the border above the indicator, you can put it inside of each tab bar item. Here's one take on it:
import 'package:flutter/material.dart';
void main() {
runApp(TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
Widget _createTab(String text) {
return Tab(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(
child: Center(child: Text(text)),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.black)))
)
),
]
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.white,
),
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
elevation: 0,
bottom: TabBar(
labelPadding: EdgeInsets.all(0),
tabs: [
_createTab("Tab 1"),
_createTab("Tab 2"),
_createTab("Tab 3"),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
),
);
}
}
Try to set appBar border :
appBar: AppBar(
shape: Border(bottom: BorderSide(color: Colors.red)),
....
Simply you can wrap TabBar into DecoratedBox as below:
DecoratedBox(
decoration: BoxDecoration(
//This is for background color
color: Colors.white.withOpacity(0.0),
//This is for bottom border that is needed
border: Border(
bottom: BorderSide(color: AppColors.color4, width: 2.sp)),
),
child: TabBar(
...
),
),
Hope you will get help.
I managed to do that using 'flexibleSpace' property instead 'bottom' property, as flexibleSpace can have any widget not only 'PreferredSizeWidget' like bottom.
So I gave a Column to the flexibleSpace, then I was able to put TabBar and the container inside that column, then using Matrix4.translationValues(0.0, -2.6, 0.0) I gave the container, which contain the border, a nigative-padding(or similar) so it moved to the top of the indicatorColor.
return SafeArea(
top: true,
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
backgroundColor: Theme.of(context).buttonColor,
title: Text(
'AppBar',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.title,
),
centerTitle: true,
elevation: 0.0,
flexibleSpace: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: Column(
children: <Widget>[
// Tab Bar
new TabBar(
indicatorColor: Theme.of(context).accentColor,
tabs: <Tab>[
new Tab(
text: 'Tab1',
),
new Tab(
text: 'Tab2',
),
],
controller: _tabController,
),
// Border
Container(
// Negative padding
transform: Matrix4.translationValues(0.0, -2.6, 0.0),
// Add top border
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Color(0xFFc3c3c3),
width: 0.6,
),
),
),
),
],
),
),
),
),
body: new TabBarView(
children: <Widget>[
new Tab1(),
new Tab2(),
],
controller: _tabController,
),
),
);
And the magic happened ^^
Another approach is to use a stack and place the line underneath the tabs
Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.white70, width: 1),
)),
),
TabBar(
indicatorWeight: 3.0,
tabs: [
Tab(
icon: Icon(Icons.home),
),
Tab(
icon: Icon(Icons.show_chart),
),
],
),
],
),
Here's my version of spenster's solution;
Instead of a function, I created a new widget "BorderedTab" which implements Tab:
import 'package:flutter/material.dart';
class BorderedTab extends StatelessWidget implements Tab {
const BorderedTab({
Key key,
this.text,
this.borderColor=Colors.grey,
this.width=0.5,
}) : super(key: key);
final String text;
final Color borderColor;
final double width;
#override
Widget build(BuildContext context) {
return Tab(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(
child: Center(
child: Text(text)
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: width,
color: borderColor,
),
),
),
),
),
]
),
);
}
#override
// TODO: implement child
Widget get child => null;
#override
// TODO: implement icon
Widget get icon => null;
}
then I used BorderedTab just like the regular Tab, but with:
labelPadding: EdgeInsets.all(0.0), // Important to remove default padding
Final AppBar:
import 'package:../widgets/bordered_tab.dart';
...
appBar: AppBar(
backgroundColor: Theme.of(context).buttonColor,
title: Text(
'TabBar',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.title,
),
centerTitle: true,
elevation: 0.0,
bottom: new TabBar(
labelColor: Theme.of(context).primaryColor,
indicatorColor:Theme.of(context).accentColor,
labelPadding: EdgeInsets.all(0.0), // Important to remove default padding
tabs: <Tab>[
BorderedTab(
text: 'Tab1',
borderColor: Color(0xFFc3c3c3),
),
BorderedTab(
text: 'Tab2',
borderColor: Color(0xFFc3c3),
),
],
controller: _tabController,
),
),
Use DecoratedBox and PreferredSize
First put TabBar inside of PreferredSize :
child: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(50),
child: TabBar(
tabs: [
Tab(
text: 'tab-1',
),
Tab(
text: 'tab-2',
),
Tab(
text: 'tab-3',
),
],
),
),
),
then wrap TabBar with DecoratedBox
child: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(50),
child: DecoratedBox(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 2,color: Color.fromARGB(255, 255, 0, 0)))
),
child: TabBar(
tabs: [
Tab(
text: 'tab-1',
),
Tab(
text: 'tab-2',
),
Tab(
text: 'tab-3',
),
],
),
),
),
),
Easiest way without using additional elements, is to use BoxShadow with TabBar like below:
TabBar(
controller: _tabController,
indicator: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.red,
offset: Offset(0, 2.0),
)
],
color: Colors.white,
),
labelColor: Colors.red,
unselectedLabelColor: Colors.grey.shade900,
labelPadding: EdgeInsets.symmetric(horizontal: 10.0),
isScrollable: false,
tabs: [
Tab(
text: 'T1',
),
Tab(
text: 'T2',
),
Tab(
text: 'T3',
),
Tab(
text: 'T4',
),
],
),
Or using UnderlineTabIndicator as indicator parameter of TabBar:
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 3.0),
insets: EdgeInsets.symmetric(horizontal: 30.0),
),

Flutter Container BoxShadow doesn't show

Here it's my code in this moment:
ClipRRect(
borderRadius: BorderRadius.circular(11),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: FractionalOffset.bottomLeft,
end: FractionalOffset.topRight,
colors: <Color>[Colors.purple, AppBaseColors.orange],
),
boxShadow: [BoxShadow(color: Colors.yellow)]
),
child: Material(
child: InkWell(
onTap: () {
print("tapped");
},
child: Container(
width: ButtonTheme.of(context).minWidth,
height: ButtonTheme.of(context).height,
child: Center(
child: Text(
"log in",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
),
),
),
color: Colors.transparent,
),
),
),
WHAT HAVE I TRIED:
Add the boxShadow in the first Container
Add the boxShadow in the second Container
Add another Container with boxShadow as a parent of ClipRRect
Add the boxShadow in Material as shadowColor (ofc is not working because I don't have any kind of shadow)
Adding also the spreadRadius and blurRadius in all of the cases from above, but nothing changed.
Any idea what I did wrong?
You need to do these changes:
remove the ClipRRect widget.
add borderRadius inside BoxDecoration.
add an Offset to your BoxShadow.
Container(
decoration: BoxDecoration(
color: Colors.blue,
gradient: LinearGradient(
begin: FractionalOffset.bottomLeft,
end: FractionalOffset.topRight,
colors: <Color>[Colors.purple, Colors.orange],
),
borderRadius: BorderRadius.circular(11),
boxShadow: [
BoxShadow(color: Colors.yellow, offset: Offset(5.0, 5.0))
]),
child: Material(
borderRadius: BorderRadius.circular(11),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: () {
print("tapped");
},
child: Container(
width: ButtonTheme.of(context).minWidth,
height: ButtonTheme.of(context).height,
child: Center(
child: Text(
"log in",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
),
),
),
color: Colors.transparent,
),
),
I fixed mine by removing the clipBehavior or setting it to Clip.none.

Categories

Resources