美文网首页
SCRM-项目搭建-首页搭建-02

SCRM-项目搭建-首页搭建-02

作者: SuDream | 来源:发表于2020-06-23 16:09 被阅读0次
    image.png

    首页 ui是这样

    技术点分析
    首页.gif

    可以看到首页需要这种可以滚动分页切换的 采用 tabbar+TabBarView

    问题:但是tabbar 下面的indicator(指示器)默认不是圆角的 而且不能自定义 宽度 系统默认只提供了2种

    //根据文字宽度
    TabBarIndicatorSize.label
    //根据tab的宽度
    TabBarIndicatorSize.tab
    

    1. flutter 自定义 indicator(指示器)

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    // 默认高度从46改为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,
    //    );
        //希望的宽度
        double wantWidth = 25;
        //取中间坐标
        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;
        // 改为圆角
        final Paint paint = borderSide.toPaint()..strokeCap = StrokeCap.round;
        canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
      }
    }
    

    Copy一份系统的 从新命名一个 RoundUnderlineTabIndicator 类 修改 修改参数即可

    使用方式

     TabBar(
             ..............
    
                indicator: RoundUnderlineTabIndicator(
                    borderSide: BorderSide(
                  width: 3.5,
                  color: ColorsUtils.main_color,
                )),
             ......
            )
               
    

    问题2

    image.png

    上面区域有阴影,可以自己写,我这是用的ui给的一张背景图,这时候就涉及到 图片拉伸的问题 需要指定区域拉伸, 就和iOS原生的 Show Slicing ,android 的.9处理 是一样的效果,当然你可以选择用card组件去实现

    使用image的centerSlice 拉伸指定区域 这里需要 Rect.fromLTRB 或者 Rect.fromLTWH,这里需要注意的是
    1.组件不能比你图片大
    2.fromLTRB 和 fromLTWH 指定位置的问题

    return Container(
            width: 300,
            height: 195,
            decoration: BoxDecoration(
                image: DecorationImage(
                    centerSlice: Rect.fromLTRB(60, 60, 71, 71),
                    image: AssetImage("assets/images/beijing.png"),
                    fit: BoxFit.fill),
                color: Colors.red),
            child: Text("哈哈"));
    

    上图 Rect.fromLTRB(60, 60, 71, 71) 我以为 会是这样的

    image.png
    但实际上却不是这样的 实际上是这样的
    image.png
    为啥会是这样呢 Rect.fromLTRB ltrb都是距离左上角的距离

    fromLTWH 这个就更好理解一点了

    image.png

    问题3

    指示器.gif

    这里的搭配 pageView+Indicator 可以看出指示器需要自定义 而且带动画的

    flutter 自定义指示器(Indicator)

    
        
    /// An indicator showing the currently selected page of a PageController
    class CSTIndicator extends AnimatedWidget {
      CSTIndicator({
        this.controller,
        this.itemCount,
        this.onPageSelected,
        this.color:ColorsUtils.yelllow_color ,
      }) : super(listenable: controller);
    
      /// The PageController that this DotsIndicator is representing.
      final PageController controller;
    
      /// The number of items managed by the PageController
      final int itemCount;
    
      /// Called when a dot is tapped
      final ValueChanged<int> onPageSelected;
    
      /// The color of the dots.
      ///
      /// Defaults to `Colors.white`.
      final Color color;
    
      // The base size of the dots
      static const double _kDotSize = 8.0;
    
      // The increase in the size of the selected dot
      static const double _kMaxZoom = 2.5;
    
      // The distance between the center of each dot
      static const double _kDotSpacing = 25.0;
    
      Widget _buildDot(int index) {
        double selectedness = Curves.easeOut.transform(
          max(
            0.0,
            1.0 - ((controller.page ?? controller.initialPage) - index).abs(),
          ),
        );
        double zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness;
        return new Container(
          width: _kDotSpacing,
          child: new Center(
            child: new Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(_kDotSize/2),
                  color: color,
                ),
            
                width: _kDotSize * zoom,
                height: _kDotSize ,
                child: new InkWell(
                  onTap: () => onPageSelected(index),
                ),
              ),
          ),
        );
      }
    
      Widget build(BuildContext context) {
        return new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: new List<Widget>.generate(itemCount, _buildDot),
        );
      }
    }
    

    使用方式

        CSTIndicator(
                controller: pageCtr,   //注意这个controller是 PageController 
                itemCount: 3,
    
    /*  
                如需要点击 指示器切换pageView  需要实现此事件,我上面用不上,所以不实现
                 onPageSelected: (int page) {
                   pageCtr.animateToPage(
                     page,
                   duration:time,
                    curve:curve,
              );
    */
              )
    

    以上理解如有误请大佬能够指出,3q

    ok,以梦为马,不负韶华

    image.png

    相关文章

      网友评论

          本文标题:SCRM-项目搭建-首页搭建-02

          本文链接:https://www.haomeiwen.com/subject/psyhfktx.html