简体   繁体   English

Flutter - 如何制作具有固定高度的自定义圆形标签指示器?

[英]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?并告诉我如何使用 flutter 制作分段可扩展列表视图? Design for listview列表视图设计

Custom indicator with a rounded shape具有圆形形状的自定义指示器

You can use the CustomPainer您可以使用 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上面的片段取自这个包

https://pub.dev/packages/md2_tab_indicator https://pub.dev/packages/md2_tab_indicator

You can use this CustomTabIndicator class.您可以使用此 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())

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM