How to fix overlaying one border above another? - flutter

I have a TabBar with tabs inside and when I click on a tab the vertical line(divider) overlays border of a tab(when I click on a tab there are white borders).
It looks like this:
This is how it looks like
This is my TabBar:
TabBar(
indicatorPadding: EdgeInsets.symmetric(vertical: 10),
indicator: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5)),
side: BorderSide(color: Colors.white)),
color: Color(0xFF1C1B20),
),
labelColor: AppColors.whiteE3EAF6,
labelStyle: TextStyle(color: Colors.white),
labelPadding: const EdgeInsets.all(0),
tabs: [
_tab("1M",),
_tab("5M",),
_tab("15M",),
_tab("30M",),
Tab(text: "1H",),
]
)
And this is my custom _tab widget:
Widget _tab(String text) {
return Container(
height: 16,
padding: const EdgeInsets.all(0),
width: double.infinity,
decoration: const BoxDecoration(
border: Border(right: BorderSide(color: Color(0xFF454545), width: 1, style: BorderStyle.solid))),
child: Tab(
text: text,
),
);
}
I want to make this gray line invisible or make it white but I don't know how to fix that

First define new variable out of build method like this:
int selectedTap = 0;
then change your _tab to this:
Widget _tab(String text, int index) {
return Container(
height: 16,
padding: const EdgeInsets.all(0),
width: double.infinity,
decoration: BoxDecoration(
border: index == selectedTap
? null
: Border(
right: BorderSide(
color: Color(0xFF454545),
width: 1,
style: BorderStyle.solid),
)),
child: Tab(
text: text,
),
);
}
and use it like this:
TabBar(
indicatorPadding: EdgeInsets.symmetric(vertical: 10),
indicator: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5)),
side: BorderSide(color: Colors.white)),
color: Color(0xFF1C1B20),
),
labelColor: AppColors.whiteE3EAF6,
labelStyle: TextStyle(color: Colors.white),
labelPadding: const EdgeInsets.all(0),
tabs: [
_tab("1M", 0),
_tab("5M", 1),
_tab("15M", 2),
_tab("30M", 3),
Tab(text: "1H",),
],
onTap: (index) {
setState(() {
selectedTap = index;
});
},
)

Related

How to customize tabBar?

I want to make tapBar looking like this:
But only got this:
This is my code(DefaultTabContainer is wrapped with container with height: 600 and width: 300):
DefaultTabController(
length: 3,
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(35.h),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10.w),
decoration: BoxDecoration(
//color: const Color(0xFF1C1B20),
borderRadius: BorderRadius.circular(12),
),
child: TabBar(
controller: _tabController,
indicatorPadding:
const EdgeInsets.symmetric(vertical: 5),
indicator: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(5)),
),
color: Color(0xFF4F4E51),
),
labelColor: Colors.white,
physics: const NeverScrollableScrollPhysics(),
labelStyle: const TextStyle(
color: Colors.white,
fontSize: 12
),
tabs: const [
Tab(
text: "Day",
),
Tab(
text: "Week",
),
Tab(
text: "Month (Soon)",
),
]),
),
)
)
)
TabController in initState:
_tabController = TabController(vsync: this, length: numberTabs); // numberTabs = 3
I tried to make it like I want but I cannot and I don't understand why...
You can set each tabs as below
tabs:[
Tab(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.red,
),
child: Align(
alignment: Alignment.center,
child: Text(
"Day",
),
),
),
),]

Set state for variable error; This widget has been unmounted, so the State no longer has a context (and should be considered defunct)

I'm fairly new to Flutter and I have a page where I take in two inputs in a search fieldstone them in different variables(_selectedYear and _selectedSem) and based on the inputs I create a url.
On creating the two search fields and running it , if I input in the second field before the first one, I have no error but if I input in the first field before the second field this error pops up.
This widget has been unmounted, so the State no longer has a context (and should be
considered defunct). Consider canceling any active work during dispose or using the getter mounted to determine if the state is still active.
Here's a screenshot of the page:
Here is the code.
class _TestrState extends State<Testr> {
String _selectedYear;
String _selectedSem;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
title: const Text(
'Testr',
style: TextStyle(
color: Colors.black,
),
),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.bottomRight,
colors: [Colors.green, Colors.limeAccent])),
),
),
body: Container(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.64,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.all(20.0),
child: Text(
'Select a Year',
style: TextStyle(fontSize: 16, color: Colors.blueGrey),
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 10),
),
],
),
child: SearchField(
hint: 'Search for Year',
searchInputDecoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blueGrey.shade200,
width: 1,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Colors.blue.withOpacity(0.8),
),
borderRadius: BorderRadius.circular(10),
),
),
maxSuggestionsInViewPort: 4,
itemHeight: 50,
suggestionsDecoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
onTap: (value) {
setState(() {
_selectedYear = value;
});
if (kDebugMode) {
print(value);
}
},
suggestions: const [
'Year One',
'Year Two',
'Year Three',
'Year Four',
],
),
),
const Padding(
padding: EdgeInsets.all(20.0),
child: Text(
'Select a Semester',
style: TextStyle(fontSize: 16, color: Colors.blueGrey),
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 10),
),
],
),
child: SearchField(
hint: 'Search for Semester',
searchInputDecoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blueGrey.shade200,
width: 1,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Colors.blue.withOpacity(0.8),
),
borderRadius: BorderRadius.circular(10),
),
),
maxSuggestionsInViewPort: 4,
itemHeight: 50,
suggestionsDecoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
onTap: (value) {
setState(() {
_selectedSem = value;
});
if (kDebugMode) {
print(value);
}
},
suggestions: const [
'Afghanistan',
'Turkey',
'Germany',
'France',
'Italy',
],
),
),
],
),
),
Container(
height: 90,
padding: const EdgeInsets.only(right: 20, left: 20, bottom: 20),
decoration: const BoxDecoration(
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_selectedYear == null
? const Text(
'Select a Year and a Semester to Continue',
style:
TextStyle(fontSize: 14, color: Colors.blueGrey),
)
: Text(_selectedYear + "->" + _selectedSem,
style: TextStyle(
fontSize: 16,
color: Colors.grey.shade800,
fontWeight: FontWeight.w600)),
MaterialButton(
onPressed: () {
CreateURL(_selectedYear, _selectedSem);
},
color: Colors.black,
minWidth: 50,
height: 50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.all(0),
child: const Icon(
Icons.arrow_forward_ios,
color: Colors.blueGrey,
size: 24,
),
)
],
),
)
],
),
),
),
);
}
}
Ive tried placing the setstate in an 'if(mounted)' and that didn't work after looking at other similar questions.
i just changed the variables initialization and it worked.
String _selectedYear = "";
String _selectedSem = "";
and also added this logic to the setState
setState(() {
_selectedSem = value!;
});
this did the trick for me, try it out and see
I'm not sure but once you try this way. first, initialize value to a variable and then refresh state
_selectedYear = value!;
setState(() {});
or if you are using flutter version 2.5.3 or higher then you need to initialize variable or migrate to null safety.

How to add a side borders of unseleted tabs in tabBar

I want to give borders between UN-selected tabs i tried this but not working. Border between around live so when i switch tabs it will look grey instead of empty space
Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: lightGrey)),
child: TabBar(
indicator: BoxDecoration(
color: Colors.green,
border: Border.symmetric(
vertical: BorderSide(color: lightGrey),
)),
labelStyle: body14_500(Colors.white),
unselectedLabelStyle: body14_500(dark3),
indicatorColor: white,
labelPadding: EdgeInsets.symmetric(horizontal: 24),
unselectedLabelColor: dark3,
labelColor: Colors.white,
tabs: [
Tab(text: "Upcoming"),
Container(
decoration: BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: lightGrey),
),),
child: Tab(text: "Live")),
Tab(text: "Completed"),
],
),
)
this is how it look
Expected this
this worked for me
tabs: [
Tab(text: "Upcoming"),
Tab(
child:Row(
MainAxisAlignment.spaceBetween,
children: <Widget>[
VerticalDivider(),
Text("Lives"),
VerticalDivider(),
]
),
),
Tab(text: "Completed"),
],
You can use CupertinoSegmentedControl to achieve this
CupertinoSegmentedControl<int>(
onValueChanged: (value) => setState(() => selectedIndex = value),
children: cupertinoMap,
padding: const EdgeInsets.all(12),
groupValue: selectedIndex,
selectedColor: Colors.green,
pressedColor: Colors.green.shade100,
unselectedColor: Colors.white,
borderColor: Colors.grey.shade300,
),
Full code at dartpad
Screenshot

Can I custom TextField suffixIcon with background?

I want the text field search icon (suffix) to have a green background, then my text field using shadow not border. Can u help me with this? or this one cannot implement in flutter?
Here my code:
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
width: 0,
style: BorderStyle.solid,
),
),
contentPadding: EdgeInsets.only(left: 25),
hintText: "Bandung, Jawa Barat",
hintStyle: TextStyle(fontSize: 15, color: Colors.black45),
filled: true,
fillColor: Colors.white,
prefixIcon: Image.asset('assets/img/map.png', height: 15),
suffixIcon: Image.asset('assets/img/search.png', color: Colors.green),
suffixIconConstraints: BoxConstraints(
minWidth: 50,
)
),
)
to
To obtain shadow for your TextField widget, one option is Material widget. Wrap your Textfield with Material widget which has properties like elevation, shadowColor, borderRadius. It is cleaner option for shadow than Container widget which has property decoration.
Output
Copy paste this below code to see the effect:
class CustomTextField extends StatefulWidget {
#override
_CustomTextField State createState() => _CustomTextField State();
}
class _CustomTextField State extends State<CustomTextField > {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 25),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Material(
elevation: 5.0,
shadowColor: Colors.green,
borderRadius: BorderRadius.circular(15.0),
child: TextFormField(
obscureText: true,
autofocus: false,
decoration: InputDecoration(
hintText: 'Search here',
hintStyle:
TextStyle(fontSize: 16, color: Colors.black45),
fillColor: Colors.white,
filled: true,
prefixIcon: Icon(Icons.person, color: Colors.green),
suffixIcon: Material(
elevation: 5.0,
color: Colors.green,
shadowColor: Colors.green,
borderRadius: BorderRadius.only(
topRight: Radius.circular(15.0),
bottomRight: Radius.circular(15.0),
),
child: Icon(Icons.search, color: Colors.white),
),
contentPadding:
EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide:
BorderSide(color: Colors.white, width: 3.0))),
),
),
),
],
),
),
),
),
);
}
}

Add vertical line as a divider in tabbar as a divider

I have a tab bar and i need to put a vertical line as a divider between tabs, how to do that?
this how i used my tabbar:
new TabBar(
unselectedLabelColor: Color.fromRGBO(119, 119, 119, 1),
labelColor: Colors.black,
controller: controller,
tabs: <Tab>[
new Tab(text: "Girls"),
new Tab(text: "Hero"),
new Tab(text: "Open"),
]),
and I need it to be like this:
Finally It worked for me
TabBar(
tabs: [
_individualTab('assets/icons/bottom_nav/Home.png'),
_individualTab('assets/icons/bottom_nav/Guys.png'),
_individualTab('assets/icons/bottom_nav/Notes.png'),
Tab(
icon: ImageIcon(
AssetImage('assets/icons/bottom_nav/Email.png')
),
),
],
labelColor: STColors.PRIMARY_COLOR,
unselectedLabelColor: Colors.grey,
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.tab,
labelPadding: EdgeInsets.all(0),
indicatorPadding: EdgeInsets.all(0),
),
Individual Tab Function
Widget _individualTab(String imagePath) {
return Container(
height: 50 + MediaQuery
.of(context)
.padding
.bottom,
padding: EdgeInsets.all(0),
width: double.infinity,
decoration: BoxDecoration(border: Border(right: BorderSide(color: STColors.LIGHT_BORDER, width: 1, style: BorderStyle.solid))),
child: Tab(
icon: ImageIcon(AssetImage(imagePath)),
),
);
}
To achieve small size separator you can use this.
Widget _individualTab(String imagePath) {
return Container(
height: 50,
width: double.infinity,
decoration: BoxDecoration(
border: Border(right: BorderSide(color: STColors.LIGHT_BORDER,
width: 0,
style: BorderStyle.solid),
),
),
child: Stack(children: <Widget>[
Center(
child: Tab(
icon: ImageIcon(AssetImage(imagePath)),
),
),
Align(
alignment: Alignment.centerRight,
child: Container(
color: STColors.appBlackMedium,
width: 1,
height: 25,
),
)
],)
);
}
All you need is
indicator: BoxDecoration(
border: Border(
left: BorderSide(color: Colors.grey), // provides to left side
right: BorderSide(color: Colors.grey), // for right side
),
),
Your solution:
new TabBar(
indicator: BoxDecoration(border: Border(right: BorderSide(color: Colors.orange))),
unselectedLabelColor: Color.fromRGBO(119, 119, 119, 1),
labelColor: Colors.black,
controller: controller,
tabs: <Tab>[
new Tab(text: "Girls"),
new Tab(text: "Hero"),
new Tab(text: "Open"),
]),
Here is the Header I want to achieve
Yea, so I added a var called rightDivider which lets you render divider but the last tab on my custom tab widget.
import 'package:flutter/material.dart';
class TabWidget extends StatelessWidget {
final String label;
final bool rightDivider;
TabWidget({
required this.label,
required this.rightDivider,
});
#override
Widget build(BuildContext context) {
return Container(
height: 32 + MediaQuery.of(context).padding.bottom,
width: double.infinity,
padding: EdgeInsets.all(0),
decoration: (rightDivider)
? BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 1,
style: BorderStyle.solid,
),
),
)
: null,
child: Center(child: Text(label)),
);
}
}
And called this widget like this
TabBar(
controller: _tabController,
tabs: [
TabWidget(
label: 'Today',
rightDivider: true,
),
TabWidget(
label: 'Calendar',
rightDivider: true,
),
TabWidget(
label: 'Report',
rightDivider: false,
),
],
)
That's how I achieve this behavior...
HomeTab({required String title, bool isSeprator = true}) {
return Tab(
child: Container(
width: 100,
height: 20,
child: Center(
child: Text(title),
),
decoration: isSeprator
? BoxDecoration(
border: Border(
left: BorderSide(
color: Colors.grey,
width: 1,
style: BorderStyle.solid,
),
),
)
: null,
),
);
}
isSeparator is to show separator or not ... because on the last index I am not showing...
Following is the list of tabs ...
List<Widget> _tabScroll() => [
HomeTab(title: "Tab1"),
HomeTab(title: "Tab2"),
HomeTab(title: "Tab3", isSeparator: false),
];
and following is the most important TabBar Code...
TabBar(
labelPadding: EdgeInsets.symmetric(horizontal: 0), //removing extra space
controller: _controller,
isScrollable: true,
indicatorColor: Colors.black,
indicatorSize: TabBarIndicatorSize.label,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 3.0), //hight of indicator
insets: EdgeInsets.symmetric(horizontal: 30.0), //give some padding to reduce the size of indicator
),
unselectedLabelColor: Colors.grey,
tabs: _tabScroll(), //list of tabs
),
The end result looks like this...
Working solution is to create border for individual tabs. Tabs parameter actually accept other elements as a child. So you can use custom containers. That way you can control which side border you want to show (left, rigth or any side):
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: 1.0),
isScrollable: false,
tabs: [
Container(
child: Center(
child: Text('T1'),
),
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 2,
style: BorderStyle.solid,
),
),
)),
Container(
child: Center(
child: Text('T2'),
),
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 2,
style: BorderStyle.solid,
),
),
)),
Container(
child: Center(
child: Text('T3'),
),
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 2,
style: BorderStyle.solid,
),
),
)),
Tab(
text: 'T4',
),
],
),
Thats how i have done this
I am using screenutils package from pub you can also use it
SizedBox(
width: 342.w,
height: 41.h,
child: Material(
color: const Color(0xffE2E2E2),
borderRadius: BorderRadius.circular(5),
child: Padding(
padding: EdgeInsets.all(2),
child: TabBar(
padding: EdgeInsets.zero,
indicatorPadding: EdgeInsets.zero,
labelPadding: EdgeInsets.zero,
indicator: BoxDecoration(
color: Color(0xffFFFFFF),
// borderRadius: BorderRadius.circular(5.0)
),
labelColor: Colors.black,
unselectedLabelColor: Color(0xff999BA2),
tabs: [
Container(
width: 1.sw,
decoration: BoxDecoration(
// color: Colors.black,
border: Border(right: BorderSide(color: Colors.white))
),
child: Tab(
text: 'Call',
),
),
Container(
width: 1.sw,
decoration: BoxDecoration(
border: Border(right: BorderSide(color: Colors.white))
),
child: Tab(
text: 'Missed Call',
),
// child: Tab(text: 'Phone',),
),
Container(
child: Tab(
text: 'No Call',
),
// child: Tab(text: 'No Call'),
),
],
),
),
),
)
enter image description here