“This is the 12th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge juejin.cn/post/698796…

I just learned how to use the TabBar, and the use of the indicator is less. Try a custom label indicator today;

TabBar provides the Indicator attribute. Users are allowed to customize indicators, but custom indicators will invalidate indicatorColor/indicatorWeight/indicatorPadding. The default indicator is UnderlineTabIndicator;

Decoration get _indicator { if (widget.indicator ! = null) return widget.indicator; final TabBarTheme tabBarTheme = TabBarTheme.of(context); if (tabBarTheme.indicator ! = null) return tabBarTheme.indicator; Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor; if (color.value == Material.of(context).color? .value) color = Colors.white; return UnderlineTabIndicator( insets: widget.indicatorPadding, borderSide: BorderSide(width: widget.indicatorWeight, color: color)); }Copy the code

Source code analysis

class ACETabBarIndicator extends Decoration {
  @override
  BoxPainter createBoxPainter([onChanged]) => _ACETabBarIndicatorPainter(this, onChanged);
}

class _ACETabBarIndicatorPainter extends BoxPainter {
  final ACETabBarIndicator decoration;
  _ACETabBarIndicatorPainter(this.decoration, VoidCallback onChanged);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    // TODO: implement paint
  }
}
Copy the code

According to the source code analysis, all customized indicators should be inherited from Decoration; When drawing BoxPainter, you can obtain the corresponding Tab size and position by Offset and ImageConfiguration.

Case try

The custom ACETabBarIndicator is isolated in the side dish. There is no custom TabBar. Therefore, the properties in the TabBar cannot be used directly. If you want to use the ACETabBarIndicator directly in the TabBar, you can try to customize it by placing the ACETabBarIndicator in the TabBar source.

The customization is mainly to implement the various styles of paint process, the side dish is simple to try the following several indicator styles;

1. ACETabBarIndicatorType. Circle – > solid dot

To set height to diameter, draw a circle in the middle of the bottom of the Tab. Note that the starting position is the center of the bottom, minus the radius;

canvas.drawCircle(
    Offset(offset.dx + (configuration.size.width) / 2, configuration.size.height - _height),
    _height, _paint);
Copy the code

2. ACETabBarIndicatorType. Triangle – > upper triangular

The side dish generates an upper triangle by drawing Path; Which needs to be compatible with a triangle height upper limit;

if (_height > configuration.size.height) _height = _kIndicatorHeight; Path _path = Path() .. moveTo(offset.dx + (configuration.size.width) / 2 - _height, configuration.size.height) .. lineTo(_height * tan(pi / 6) + offset.dx + (configuration.size.width - _height) / 2, configuration.size.height - _height) .. lineTo(_height * tan(pi / 6) + offset.dx + (configuration.size.width + _height) / 2, configuration.size.height); canvas.drawPath(_path, _paint);Copy the code

3. ACETabBarIndicatorType. Rrect – > rounded rectangle (the entire Tab)

Draw a rounded rectangle with an Offset position and a Tab size of ImageConfiguration;

canvas.drawRRect(
    RRect.fromRectAndRadius(
        Rect.fromLTWH(offset.dx, offset.dy, configuration.size.width, configuration.size.height),
        Radius.circular(_kIndicatorAngle)),
    _paint);
Copy the code

4. ACETabBarIndicatorType. Rrect_inner – > rounded rectangle (padding)

< span style = “font-size: 15px; color: RGB (50, 50, 50);” The start height of the rectangle needs to be reduced by 1, because Paint defaults to a line width of 1.

canvas.drawRRect(
    RRect.fromRectAndRadius(
        Rect.fromLTWH(
            offset.dx + height, height - 1,
            configuration.size.width - height * 2,
            configuration.size.height - height * 2 - 2),
        Radius.circular(_kIndicatorAngle)),
    _paint);
Copy the code

5. ACETabBarIndicatorType. Runderline – > rounded corners underscore

The default TabBar indicator style is UnderlineTabIndicator; Just change the Paint line style to round.

canvas.drawLine( Offset(offset.dx, configuration.size.height - height / 2), Offset(offset.dx + configuration.size.width, configuration.size.height - height / 2), _paint.. strokeWidth = height / 2);Copy the code

6. ACETabBarIndicatorType. Runderline_fixed – > fixed-length rounded corners underscore

< span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 20px; font-size: 15px! Important; word-break: block;”

if (_width > configuration.size.width) _width = configuration.size.width / 3; canvas.drawLine( Offset(offset.dx + (configuration.size.width - _width) / 2, configuration.size.height - height / 2), Offset(offset.dx + (configuration.size.width + _width) / 2, configuration.size.height - height / 2), _paint.. strokeWidth = height / 2);Copy the code


ACETabBarIndicator case source code


The adaptation test of the customized label indicator is not complete, if there are mistakes, please guide!

Source: Young Monk Atze