I'm using a TabBar widget and I'd like to customize the height and width of the indicator. I can't see any other property besides color I can modify.
You can use indicatorSize: TabBarIndicatorSize.label on the TabBar to make the indicator the same size as the label.
Or you could set the indicator directly, this is a Decoration which you can customize:
AppBar(
bottom: TabBar(
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 5.0),
insets: EdgeInsets.symmetric(horizontal:16.0)
),
tabs: [
Tab(text: 'tab 1'),
Tab(text: 'tab 2'),
Tab(text: 'tab 3'),
],
),
);
For more customisation options check this post
Give your TabBar a property of isScrollable: true if you don't want the tabs to expand to fill the screen horizontally the way they do by default.
You can use a Container wrapped in a PreferredSize to size the TabBar. (The PreferredSize is only necessary if you want it to live in the bottom slot of an AppBar.) This has the effect of making the indicators appear narrower because the TabBar doesn't fill the screen. However, the indicator has a hard coded height. If you don't like it, you'll have to import your own copy of tabs.dart and customize the constants in that file.
Note that you can also use a Container to set the height of the individual Tabs, although that doesn't seem like what you're trying to do.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new DefaultTabController(
length: 2,
child: new Scaffold(
appBar: new AppBar(
title: new Text('Tabs Demo'),
bottom: new PreferredSize(
preferredSize: new Size(200.0, 200.0),
child: new Container(
width: 200.0,
child: new TabBar(
tabs: [
new Container(
height: 200.0,
child: new Tab(text: 'hello'),
),
new Container(
height: 200.0,
child: new Tab(text: 'world'),
),
],
),
),
),
),
// body: ...
),
);
}
}
In the same way as this answer https://stackoverflow.com/a/44273493/5938089, The best is to use containers, but I will only use one.
For a change, I will use a bottom bar
bottomNavigationBar: new Material(
color: Colors.teal,
child: new Container(
height: 60.0,
child: new TabBar(
controller: controller,
tabs: <Widget>[
new Tab(icon: new Icon(Icons.access_alarm)),
new Tab(icon: new Icon(Icons.account_balance)),
]
),
)
),
Screen Shot
You can adjust the spacing between the tabs -> labelPadding: EdgeInsets.symmetric (horizontal: 5),
You can use property TabBar(indicatorWeight:detail Height).
Check out Tab Indicator Styler package for more advanced styling.
appBar: new AppBar(
title: Text("TabBar demo"),
bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Align(
alignment: Alignment.centerLeft,
child: new TabBar(
controller: _tabController,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 3.0, color: Colors.red),
insets: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10),
),
indicatorSize: TabBarIndicatorSize.label,
isScrollable: true,
onTap: (index) {
print(index);
_currentIndex = index;
setState(() {});
},
tabs: [
new Container(
height: 50.0,
width: 80,
// color: Colors.red,
child: new Tab(text: '1'),
),
new Container(
height: 50.0,
width: 80,
// color: Colors.red,
child: new Tab(text: '222'),
),
new Container(
height: 50.0,
width: 80,
// color: Colors.red,
child: new Tab(text: '333333'),
),
],
),
),
),
),
// body: ...
);
Try to do this in the TabBar
indicatorWeight: 0,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
width: 0.1,
color: AppColor.themeColor,
),
You can design the underline indicator with border-radius, and the length of the indicator according to the text container length.
child: TabBar(
indicatoenter code herer: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: widgetBlueColor,
),
indicatorPadding: const EdgeInsets.only(top: 33, bottom: 2),
labelColor: widgetBlueColor,
unselectedLabelColor: Colors.black87,
labelPadding: const EdgeInsets.only(bottom: 16),
indicatorSize: TabBarIndicatorSize.label,
labelStyle: const TextStyle(fontWeight: FontWeight.w500),
tabs: const [
Tab(
child: SizedBox(
width: 60,
child: Text(
"DETAILS",
textAlign: TextAlign.center,
),
),
),
Tab(
child: SizedBox(
width: 85,
child: Text(
"DOCUMENTS",
textAlign: TextAlign.center,
),
)
)
]
)
if you decrease default tab bar size use SizeBox().
SizedBox(
height: 40,
child: TabBar(
isScrollable: true,
indicatorSize: TabBarIndicatorSize.tab,
labelColor: Colors.black,
unselectedLabelColor: Colors.grey,
labelStyle: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500),
unselectedLabelStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400),
padding:
EdgeInsets.symmetric(horizontal: 12),
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: AppTheme().orange),
tabs: getTab(),
controller: _tabController),
),
Related
I'm trying to make e-commerce app in flutter.
I wanted to make Appbar transparent and have animation, so I use Sliverappbar but I can't make it transparent without scrolling down.
I tried to use stack, but it doesn't work and has error.
I want appbar transparent when it's on top and change white when I scroll down.
This is my flutter code
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: Icon(
Icons.menu,
size: 30,
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.tune, color: Colors.black, size: 30),
)
],
),
body: _buildBody(),
);
}
Widget _buildBody() {
return CustomScrollView(
slivers: <Widget>[
SliverAppBar(
leading: Icon(
Icons.menu,
size: 30,
),
backgroundColor: Colors.transparent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.tune,
color: Colors.black,
size: 30,
),
)
],
floating: true,
elevation: 0.0,
snap: false,
),
SliverToBoxAdapter(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.7,
width: MediaQuery.of(context).size.width,
child: Carousel(
images: [
Image.network(
'https://i.pinimg.com/564x/83/32/37/8332374f18162612dd9f2a4af2fda794.jpg',
fit: BoxFit.cover),
Image.network(
'https://i.pinimg.com/originals/e2/8e/50/e28e5090b7193ec9b2d5b5c6dfaf501c.jpg',
fit: BoxFit.cover),
Image.network(
'https://image-cdn.hypb.st/https%3A%2F%2Fhypebeast.com%2Fwp-content%2Fblogs.dir%2F6%2Ffiles%2F2019%2F09%2Fmschf-fall-winter-lookbook-streetwear-seoul-korea-47.jpg?q=75&w=800&cbr=1&fit=max',
fit: BoxFit.cover)
],
showIndicator: false,
)),
),
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.only(
left: 25.0, top: 20.0, right: 0.0, bottom: 20.0),
child: Text('Recommended for You',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25)),
),
),
SliverPadding(
padding: EdgeInsets.only(left: 35.0, right: 35.0),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20.0,
crossAxisSpacing: 25.0,
childAspectRatio: 0.67,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return _buildListItem(context, index);
},
childCount: 13,
),
))
],
);
Best solution I can find is, instead of using SliverAppBar, use a regular AppBar in a SliverToBoxAdapter. You would set the flexibleSpace property to your Carousel, or put the AppBar and carousel into a Stack.
The flexibleSpace property, as far as I can tell, behaves differently in a SliverAppBar and a regular AppBar. It wont collapse in a regular AppBar and you also won't need to put your carousel in a FlexibleSpaceBar().
You may need to do a few additional things to get the exact look you're going for (e.g. change the elevation).
You can simply warp SliverAppBar with SliverOpacity widget
SliverOpacity (
opacity: 0.5,
sliver: SliverAppBar(
leading: Icon(
Icons.menu,
size: 30, ),
backgroundColor: Colors.transparent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.tune,
color: Colors.black,
size: 30,
),
)
],
floating: true,
elevation: 0.0,
snap: false,
),
)
I can't figure out how to make the FAB smaller inside the first Container in the list. It seems to want to occupy the complete container, no matter what I try. Ive even tried a container within a container. The complete Orange area is clickable. I tried SizedBox, same result. Here is the code.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'Horizontal List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
padding: EdgeInsets.all(30),
height: 200.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160,
color: Colors.yellowAccent,
child: SizedBox(
height: 50,
width: 50,
child: FittedBox(
child: FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add, size: 20),
onPressed: () {},
),
),
),
),
Container(
width: 160.0,
color: Colors.red,
),
Container(
width: 160.0,
color: Colors.blue,
),
Container(
width: 160.0,
color: Colors.green,
),
Container(
width: 160.0,
color: Colors.yellow,
),
Container(
width: 160.0,
color: Colors.orange,
),
],
),
),
),
);
}
}
I have 2 samples. And Please refer Basic Widgets for more detail.
Use margin of Container. Please refer the code as below:
child: SizedBox(
height: 50,
width: 50,
child: Container(
margin: EdgeInsets.only(left:80.0, top:80.0, bottom: 10.0) ,
child: FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add),
onPressed: () {},
),
),
),
Use Row or Column. Please refer the code as below:
child: SizedBox(
height: 50,
width: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add),
onPressed: () {},
),
]),
),
I need to add shadows to some icons in my flutter project. I've checked the icon class constructors but nothing points to that. Any idea on how to implement that?
I got what i wanted eventually using this workaround. I hope it helps whoever might need something similar.
Stack(
children: <Widget>[
Positioned(
left: 1.0,
top: 2.0,
child: Icon(icon, color: Colors.black54),
),
Icon(icon, color: Colors.white),
],
),
The Icon widget has a shadows property with which you can give shadows to an icon.
const Icon(
icon,
shadows: <Shadow>[Shadow(color: Colors.black, blurRadius: 15.0)],
size: 60,
color: Colors.white,
)
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 5.0,
),
]
),
child: Icon(
Icons.fiber_manual_record,
color: Colors.amber,
size:15,
)
),
You can use IconShadowWidget().
How to use:
1. add dependencies to pubspec.yaml:
icon_shadow: ^1.0.1
2. Import your Dart code :
import 'package:icon_shadow/icon_shadow.dart';
3. add icons:
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
),
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
shadowColor: Colors.black,
),
IconShadowWidget(
Icon(
Icons.add_circle,
color: Colors.red,
size: 100.0,
),
shadowColor: Colors.black,
showShadow: false,
),
],
),
),
You can also check my GitHub Repository
Whenever you need elevation/shadow, remember the Card widget. So, you can wrap it with Card and SizedBox:
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(35.0),
),
child: SizedBox(
width: 35,
height: 35,
child: Icon(
Icons.close,
color: Colors.black,
size: 19,
),
),
)
Even better, here is an icon button with material bubble effect + shadow (in below GIF, shadow's quality looks like bad, it is because of GIF itself)
:
Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(35.0),
),
child: ClipOval(
child: Material(
color: Colors.transparent, // button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(
width: 35,
height: 35,
child: Icon(
Icons.close,
color: Colors.black,
size: 19,
),
),
onTap: () {},
),
),
),
)
Took the idea from #Dzeri answer (https://stackoverflow.com/a/55668093/414635) and encapsulated it into a Widget so it became reusable.
Widget
class ShadowIcon extends StatelessWidget {
final IconData icon;
final Color color;
ShadowIcon(this.icon, {Key key, this.color: kLight}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
left: 0.5,
top: 0.5,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 1.0,
sigmaY: 1.0,
),
child: FaIcon(this.icon, color: kDark.withOpacity(0.7)),
),
),
FaIcon(this.icon, color: color),
],
);
}
}
The BackdropFilter doesn't seem to be working as expected but anyway all I needed was a subtle drop shadow. I'm also using the package font_awesome_flutter but you can replace the FaIcon by the native Icon widget.
Usage
Your can simply replace the native Icon by the ShadowIcon widget call:
IconButton(
icon: ShadowIcon(FontAwesomeIcons.chevronLeft, color: kLight),
onPressed: () => Get.back(),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: .5,
),
]),
child: Icon(
Icons.clear,
color: Colors.black,
size: 25,
)),
),
result will be like this pic:
:
Right now, it's not possible to directly add shadows to an Icon widget. You can however use the additional information from your IconData icon to display the icon as a styled text.
Text(
String.fromCharCode(Icons.add.codePoint),
style: TextStyle(
fontFamily: Icons.add.fontFamily,
color: Colors.white,
fontSize: 20.0,
shadows: [
BoxShadow(
color: ColorTheme.blackLight,
spreadRadius: 2,
blurRadius: 2,
)
],
height: 1 //if this isn't set, the shadow will be cut off on the top and bottom
)
);
Try this, use the icon font.
GestureDetector(
child: Container(
padding: EdgeInsets.only(right: 10, top: 10),
child: Text('\u{e5d3}',
style: TextStyle(
fontSize: 22,
color: Colors.white,
fontFamily: 'MaterialIcons',
shadows: [
BoxShadow(color: Colors.black, blurRadius: 2)
])),
),
onTap: () {}
)
Icon data from icons.dart
/// <i class="material-icons md-36">more_horiz</i> — material icon named "more horiz".
static const IconData more_horiz = IconData(0xe5d3, fontFamily: 'MaterialIcons');
You can use decorated icon plugin to do shadow on icon
Code here :
Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DecoratedIcon(
Icons.android,
color: Colors.purple,
size: 60.0,
shadows: [
BoxShadow(
blurRadius: 42.0,
color: Colors.purpleAccent,
),
BoxShadow(
blurRadius: 12.0,
color: Colors.white,
),
],
),
DecoratedIcon(
Icons.favorite,
color: Colors.lightBlue.shade50,
size: 60.0,
shadows: [
BoxShadow(
blurRadius: 12.0,
color: Colors.blue,
),
BoxShadow(
blurRadius: 12.0,
color: Colors.green,
offset: Offset(0, 6.0),
),
],
),
DecoratedIcon(
Icons.fingerprint,
color: Colors.orange,
size: 60.0,
shadows: [
BoxShadow(
color: Colors.black,
offset: Offset(3.0, 3.0),
),
],
),
],
),
),
);
I know this is pretty late, but for anyone looking to add a shadow in circular form should wrap the icon with a CircleAvatar widget and set the backgroundColor proprety of CircleAvatar to Colors.grey.withOpacity (0.5) or to any other color for the shadow. Here's the code snippet
CircleAvatar (
bacgroundColor: Colors.grey.withOpacity (0.5),
child: Icon (
Icons.yourIcon
)
Material(
color: Colors.transparent,
elevation: 10,
child: Icon(
icons.add,
),
),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
boxShadow: const [
BoxShadow(color: Colors.grey, blurRadius: 1),
],
),
child: const Icon(
FontAwesomeIcons.checkCircle,
size: 30,
color: Colors.green,
),
),
If the container size is the same as the icon size, then 3 pixels will be always downward, This is because I don't know. but this solution will clear it.
Make sure that the container size will increase by 3 pixels with icons size.
Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
boxShadow: const [
BoxShadow(color: Colors.grey, blurRadius: 1),
]),
child: const Icon(
FontAwesomeIcons.checkCircle,
size: 30,
color: Colors.green,
),
),
base on this answer you can use this code and maybe add some change
import 'package:flutter/material.dart';
class IconShadowView extends Icon {
const IconShadowView(super.icon,
{super.key,
super.color,
super.semanticLabel,
super.shadows,
super.size,
super.textDirection});
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 1.0,
top: 2.0,
child: Icon(
icon,
color: Colors.black,
key: key,
semanticLabel: semanticLabel,
shadows: shadows,
size: size,
textDirection: textDirection,
),
),
super.build(context),
],
);
}
}
I've a Material widget to wrap a MaterialButton to make border radius, but I can't set the width attribute to it. I tried use a SizedBox but not works, the Material widget keep using all space of screen.
Code:
return new SizedBox(
width: 40,
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias,
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
),
),
);
Result:
Clearly it not have 40.0 of width size.
A better approach is using Container widget. When you need to change width, height or add padding/margin to any widget you should wrap the target widget into a container. The container widget is for this kind of job.
Container(
width: myWidthValue, // Container child widget will get this width value
height: myHeghtValue, // Container child widget will get this height value
padding: allowPaddingToo, // padding is allowed too
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias, // Add This
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
onPressed: () {
setState(() {
_isNeedHelp = false;
});
},
),
),
);
This is how you can set the size, padding, and margin of widgets in general. here is an example for Button:
Container(
margin: EdgeInsets.only(top: 10), // Top Margin
child:
ElevatedButton(
style: TextButton.styleFrom(
// Inside Padding
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 20),
// Width,Height
minimumSize: Size(300, 30),
),
child: Text('Upload Data'),
onPressed: () {submitForm();},
),
),
Solved using Padding:
return Padding(
padding: EdgeInsets.fromLTRB(50, 0, 50, 0),
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias, // Add This
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
onPressed: () {
setState(() {
_isNeedHelp = false;
});
},
),
),
);
Result:
I am using BottomNavigationBarItem to display bottom navigation UI with icons and text. I would like to be able to add badges with numeric values on those. Here is my current attempt:
bottomNavigationBar:
new BottomNavigationBar(items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(
icon: new Stack(
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: 0.0,
left: 0.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0),
color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
title: new Text("Home")),
new BottomNavigationBarItem(
icon: const Icon(Icons.star), title: new Text("Star")),
],
type: BottomNavigationBarType.fixed),
However, the badge is positioned with the icon's bounding box, so it overlaps heavily with the icon:
What I would like, instead, is something like that:
Is it possible to achieve this using the BottomNavigationBarItem widget? If not, what would be a good workaround?
make sure that the badge position is right, and the overflowing children should be visible
icon: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: -1.0,
right: -6.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0), color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
If it is useful to anyone, I made one that works in the AppBar.
static Widget makeIconWithBadge(String badgeText, GestureTapCallback onTap) {
return Container(
padding: EdgeInsets.only(right: 16.0),
child: Center(
child: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.inbox),
new Positioned(
top: -6.0,
right: -6.0,
child: Container(
padding: EdgeInsets.all(2.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.white,
),
child: new Container(
padding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.red),
child: Center(
child: new Text(
"12",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 12.0,),
),
),
),
),
),
Positioned.fill(
child: Material(
borderRadius: BorderRadius.all(Radius.circular(99.0)),
color: Colors.transparent,
child: InkWell(onTap: onTap),
),
)
],
),
),
);
}