Cheung Brian
Cheung Brian

Reputation: 755

Flutter tabBar with triangle indicator

I want to create a tabBar with triangular indicator, just like the following

enter image description here

Here is the code.

@override
Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
          appBar: AppBar(
          bottom: TabBar(
          indicator: <What should I put in here?>,
          tabs: <Widget>[
            Tab(text: "Tab1"),
            Tab(text: "Tab2"),
            Tab(text: "Tab3")
          ],
        ),
      ),
    body: TabBarView(
      children: <Widget>[
        Text("Content1"),
        Text("Content2"),
        Text("Content3")
      ],
    ),
  ),
);

}

I have tried BoxDecoration with image. But the image won't show until you click on the tab. For FlutterLogoDecoration, it seems no way to change the icon.

Thank you very much.

Upvotes: 0

Views: 1472

Answers (1)

chunhunghan
chunhunghan

Reputation: 54365

You can copy paste run full code below
You need custom indicator

code snippet

TabBar(
        indicator: TriangleTabIndicator(color: kMainColor),
...
class TriangleTabIndicator extends Decoration {
...
class DrawTriangle extends BoxPainter {

Working demo

enter image description here

full code

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

const kMainColor = Color(0xFF573851);

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(title: 'Flutter Custom Tab Indicator Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          backgroundColor: Colors.white,
          bottom: TabBar(
            indicator: TriangleTabIndicator(color: kMainColor),
            tabs: <Widget>[
              Tab(
                child: Text('fruits', style: TextStyle(color: kMainColor)),
              ),
              Tab(
                child: Text('vegetables', style: TextStyle(color: kMainColor)),
              ),
              Tab(
                child: Text('berries', style: TextStyle(color: kMainColor)),
              ),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            Center(child: Text('Tab 1')),
            Center(child: Text('Tab 2')),
            Center(child: Text('Tab 3')),
          ],
        ),
      ),
    );
  }
}

class TriangleTabIndicator extends Decoration {
  final BoxPainter _painter;

  TriangleTabIndicator({@required Color color, @required double radius})
      : _painter = DrawTriangle(color);

  @override
  BoxPainter createBoxPainter([onChanged]) => _painter;
}

class DrawTriangle extends BoxPainter {
  Paint _paint;

  DrawTriangle(Color color) {
    _paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill;
  }

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration cfg) {
    final Offset triangleOffset =
        offset + Offset(cfg.size.width / 2, cfg.size.height - 10);
    var path = Path();

    path.moveTo(triangleOffset.dx, triangleOffset.dy);
    path.lineTo(triangleOffset.dx + 10, triangleOffset.dy + 10);
    path.lineTo(triangleOffset.dx - 10, triangleOffset.dy + 10);

    path.close();
    canvas.drawPath(path, _paint);
  }
}

Upvotes: 11

Related Questions