'Flutter - How to make custom rounded shape tab indicator with fixed height?
I want to make an indicator with a rounded shape like the below image.
I tried a lot for it but I can't make it a shape like a design.
And also tell me how to make sectional expandable listview with flutter? Design for listview
Solution 1:[1]
Custom indicator with a rounded shape
You can use the CustomPainer
final Paint paint = Paint();
paint.color = Color(0xff1967d2);
paint.style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndCorners(rect,
topRight: Radius.circular(8), topLeft: Radius.circular(8)),
paint);
See the live demo here.
Complete sample code given below.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Demo page", style: TextStyle(
color: Colors.black87
),),
backgroundColor: Colors.white,
bottom: TabBar(
labelStyle: TextStyle(
fontWeight: FontWeight.w700
),
indicatorSize: TabBarIndicatorSize.label,
labelColor: Color(0xff1967d2),
unselectedLabelColor: Color(0xff5f6368),
isScrollable: true,
indicator: MD2Indicator(
indicatorSize: MD2IndicatorSize.full,
indicatorHeight: 8.0,
indicatorColor: Colors.green,
),
tabs: <Widget>[
Tab(
text: "Home",
),
Tab(
text: "Personal info",
),
Tab(
text: "Data & personalization",
),
Tab(
text: "Security",
)
],
),
),
)
,
),
);
}
}
enum MD2IndicatorSize {
tiny,
normal,
full,
}
class MD2Indicator extends Decoration {
final double indicatorHeight;
final Color indicatorColor;
final MD2IndicatorSize indicatorSize;
const MD2Indicator(
{@required this.indicatorHeight,
@required this.indicatorColor,
@required this.indicatorSize});
@override
_MD2Painter createBoxPainter([VoidCallback onChanged]) {
return new _MD2Painter(this, onChanged);
}
}
class _MD2Painter extends BoxPainter {
final MD2Indicator decoration;
_MD2Painter(this.decoration, VoidCallback onChanged)
: assert(decoration != null),
super(onChanged);
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
Rect rect;
if (decoration.indicatorSize == MD2IndicatorSize.full) {
rect = Offset(offset.dx,
(configuration.size.height - decoration.indicatorHeight ?? 3)) &
Size(configuration.size.width, decoration.indicatorHeight ?? 3);
} else if (decoration.indicatorSize == MD2IndicatorSize.normal) {
rect = Offset(offset.dx + 6,
(configuration.size.height - decoration.indicatorHeight ?? 3)) &
Size(configuration.size.width - 12, decoration.indicatorHeight ?? 3);
} else if (decoration.indicatorSize == MD2IndicatorSize.tiny) {
rect = Offset(offset.dx + configuration.size.width / 2 - 8,
(configuration.size.height - decoration.indicatorHeight ?? 3)) &
Size(16, decoration.indicatorHeight ?? 3);
}
final Paint paint = Paint();
paint.color = decoration.indicatorColor ?? Color(0xff1967d2);
paint.style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndCorners(rect,
topRight: Radius.circular(8), topLeft: Radius.circular(8)),
paint);
}
}
The above snippet taken from this package
Solution 2:[2]
You can use this CustomTabIndicator class.
import 'package:flutter/material.dart';
class CustomTabIndicator extends Decoration {
final double radius;
final Color color;
final double indicatorHeight;
const CustomTabIndicator({
this.radius = 8,
this.indicatorHeight = 4,
this.color = Colors.blue,
});
@override
_CustomPainter createBoxPainter([VoidCallback? onChanged]) {
return _CustomPainter(
this,
onChanged,
radius,
color,
indicatorHeight,
);
}
}
class _CustomPainter extends BoxPainter {
final CustomTabIndicator decoration;
final double radius;
final Color color;
final double indicatorHeight;
_CustomPainter(
this.decoration,
VoidCallback? onChanged,
this.radius,
this.color,
this.indicatorHeight,
) : super(onChanged);
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration.size != null);
final Paint paint = Paint();
double xAxisPos = offset.dx + configuration.size!.width / 2;
double yAxisPos = offset.dy + configuration.size!.height - indicatorHeight/2;
paint.color = color;
RRect fullRect = RRect.fromRectAndCorners(
Rect.fromCenter(
center: Offset(xAxisPos, yAxisPos),
width: configuration.size!.width / 3,
height: indicatorHeight,
),
topLeft: Radius.circular(radius),
topRight: Radius.circular(radius),
);
canvas.drawRRect(fullRect, paint);
}
}
Usage
Tabbar(indicator: const CustomTabIndicator())
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |