当前位置:网站首页>Fillet the tabbar with the flutter

Fillet the tabbar with the flutter

2022-06-23 08:01:00 Dense information

Reference resources
Make TabBar Fillet of

 Preface 
 Recently started flutter, Then I want to use TabBar, I met some pits , Make a note of .

 The analysis process 
 This is the demand :



 We need to deal with these details :

 Underline fixed width 
 Underline fillet 
 Space between underline and text 
 The space between two words 
 And then use TabBar In the process :

 Underline wants to be fixed 25,indicatorSize There are only two properties , One is with tab Same width as parent layout , Second, it is the same width as the word 
 Fillet to see if you can use custom indicator To achieve 
 default text And the underline is very big , Let's see what we can do 
 The default spacing between text is also quite large , See how to change 
 Look at the source code : So find TabBar There is one indicator Properties of .

 Look at the comments. They generally mean that if you use custom indicator, that indicatorColor、indicatorWeight、indicatorPadding Will be ignored 

 default indicator yes UnderlineTabIndicator, then indicator Of size There are two situations 

  

OK, Let's look for this indicator How to initialize , stay _TabBarState Find :



 And then in UnderlineTabIndicator Found the answer , We put UnderlineTabIndicator Copy it out and change its name 

 Modify the following two places to fix the width and modify the fillet :



 For the spacing between underline and text , find Tab, notice text It's centered , and tab The height is fixed 

 If your Container The height ratio of 46 Small , that indicator Will be cut off , Even cut it off 

 We put tab Copy it out and rename it , Then lower the height 





 For the two tab The problem of wide spacing , After a look, I found that there is a default padding, Then add labelPadding Attributes OK 了 

 Then use it this way finally :
child: TabBar(
   indicator: RoundUnderlineTabIndicator(
      borderSide: BorderSide(
         width: 3.5,
         color: Color(0xff00cdd7),
      )
   ),
   labelColor: Color(0xff333333),
   labelStyle: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
   labelPadding: EdgeInsets.only(left: 0, right: 0),
   unselectedLabelColor: Color(0xff333333),
   unselectedLabelStyle: TextStyle(fontSize: 13, fontWeight: FontWeight.normal),
   controller: controller,
   tabs: [VgTab(text:" Ha ha ha "), VgTab(text:" ha-ha  · 99")],
),
 Modified source code , Save the following code to a new dart In the document , You can use RoundUnderlineTabIndicator and VgTab 了 :

/****************************  The following is the modified source code  ******************************/
 
//  The default height is from 46 Change it to 40
const double _kTabHeight = 40.0;
const double _kTextAndIconTabHeight = 72.0;
 
class RoundUnderlineTabIndicator extends Decoration {
    
  /// Create an underline style selected tab indicator.
  ///
  /// The [borderSide] and [insets] arguments must not be null.
  const RoundUnderlineTabIndicator({
    
    this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
    this.insets = EdgeInsets.zero,
  }) : assert(borderSide != null),
        assert(insets != null);
 
  /// The color and weight of the horizontal line drawn below the selected tab.
  final BorderSide borderSide;
 
  /// Locates the selected tab's underline relative to the tab's boundary.
  ///
  /// The [TabBar.indicatorSize] property can be used to define the
  /// tab indicator's bounds in terms of its (centered) tab widget with
  /// [TabIndicatorSize.label], or the entire tab with [TabIndicatorSize.tab].
  final EdgeInsetsGeometry insets;
 
  @override
  Decoration lerpFrom(Decoration a, double t) {
    
    if (a is UnderlineTabIndicator) {
    
      return UnderlineTabIndicator(
        borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
        insets: EdgeInsetsGeometry.lerp(a.insets, insets, t),
      );
    }
    return super.lerpFrom(a, t);
  }
 
  @override
  Decoration lerpTo(Decoration b, double t) {
    
    if (b is UnderlineTabIndicator) {
    
      return UnderlineTabIndicator(
        borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
        insets: EdgeInsetsGeometry.lerp(insets, b.insets, t),
      );
    }
    return super.lerpTo(b, t);
  }
 
  @override
  _UnderlinePainter createBoxPainter([ VoidCallback onChanged ]) {
    
    return _UnderlinePainter(this, onChanged);
  }
}
 
class _UnderlinePainter extends BoxPainter {
    
  _UnderlinePainter(this.decoration, VoidCallback onChanged)
      : assert(decoration != null),
        super(onChanged);
 
  final RoundUnderlineTabIndicator decoration;
 
  BorderSide get borderSide => decoration.borderSide;
  EdgeInsetsGeometry get insets => decoration.insets;
 
  Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
    
    assert(rect != null);
    assert(textDirection != null);
    final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
// return Rect.fromLTWH(
// indicator.left,
// indicator.bottom - borderSide.width,
// indicator.width,
// borderSide.width,
// );
    // The desired width 
    double wantWidth = 25;
    // Take the middle coordinate 
    double cw = (indicator.left + indicator.right) / 2;
    return Rect.fromLTWH(cw - wantWidth / 2,
        indicator.bottom - borderSide.width, wantWidth, borderSide.width);
  }
 
  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    
    assert(configuration != null);
    assert(configuration.size != null);
    final Rect rect = offset & configuration.size;
    final TextDirection textDirection = configuration.textDirection;
    final Rect indicator = _indicatorRectFor(rect, textDirection).deflate(borderSide.width / 2.0);
// final Paint paint = borderSide.toPaint()..strokeCap = StrokeCap.square;
    //  Change to fillet 
    final Paint paint = borderSide.toPaint()..strokeCap = StrokeCap.round;
    canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
  }
}
 
 
 
 
 
 
class VgTab extends StatelessWidget {
    
  /// Creates a material design [TabBar] tab.
  ///
  /// At least one of [text], [icon], and [child] must be non-null. The [text]
  /// and [child] arguments must not be used at the same time.
  const VgTab({
    
    Key key,
    this.text,
    this.icon,
    this.child,
  }) : assert(text != null || child != null || icon != null),
        assert(!(text != null && null != child)), // TODO(goderbauer): https://github.com/dart-lang/sdk/issues/34180
        super(key: key);
 
  /// The text to display as the tab's label.
  ///
  /// Must not be used in combination with [child].
  final String text;
 
  /// The widget to be used as the tab's label.
  ///
  /// Usually a [Text] widget, possibly wrapped in a [Semantics] widget.
  ///
  /// Must not be used in combination with [text].
  final Widget child;
 
  /// An icon to display as the tab's label.
  final Widget icon;
 
  Widget _buildLabelText() {
    
    return child ?? Text(text, softWrap: false, overflow: TextOverflow.fade);
  }
 
  @override
  Widget build(BuildContext context) {
    
    assert(debugCheckHasMaterial(context));
 
    double height;
    Widget label;
    if (icon == null) {
    
      height = _kTabHeight;
      label = _buildLabelText();
    } else if (text == null && child == null) {
    
      height = _kTabHeight;
      label = icon;
    } else {
    
      height = _kTextAndIconTabHeight;
      label = Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            child: icon,
            margin: const EdgeInsets.only(bottom: 10.0),
          ),
          _buildLabelText(),
        ],
      );
    }
 
    return SizedBox(
      height: height,
      child: Center(
        child: label,
        widthFactor: 1.0,
      ),
    );
  }
 
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    
    super.debugFillProperties(properties);
    properties.add(StringProperty('text', text, defaultValue: null));
    properties.add(DiagnosticsProperty<Widget>('icon', icon, defaultValue: null));
  }
}
 summary 
 Of course, these width and height attributes can also be extracted , It's coming in from the outside , More flexible .
 To import the following 
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

 Analyzed from the source code , Finally realized the demand . recorded , I hope that helps .
————————————————
 Copyright notice : This paper is about CSDN Blogger 「pengboboer」 The original article of , follow CC 4.0 BY-SA Copyright agreement , For reprint, please attach the original source link and this statement .
 Link to the original text :https://blog.csdn.net/pengbo6665631/article/details/103645037
原网站

版权声明
本文为[Dense information]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/174/202206230717128005.html