• 和小胖
    2019-09-05
    关于第二道思考题目的解决方法,请老师看一下:

    //绘制自定义view,其中画笔 paint ,画布 canvas,而 CustomPainter 负责具体的绘制逻辑处理
    class WheelPainter extends CustomPainter {
      List<double> _list;
      List<Color> _listColor;
      double _total; //总份数

      WheelPainter(this._list, this._listColor);

      @override
      void paint(Canvas canvas, Size size) {
        double wheelSize = min(size.width, size.height) / 2; //饼图的尺寸
        //用一个矩形框来包裹饼图
        Rect boundingRect = Rect.fromCircle(
            center: Offset(wheelSize, wheelSize), radius: wheelSize);
        //求出数组中所有数值的和
        _total = _list.reduce((value, element) => value + element);
        print("总份额是:$_total");
        //求出每一份所占的角度
        double radius = (2 * pi) / _total; //求出每一份的弧度
        print("总角度是${2 * pi},每份额角度是:$radius");
        //循环绘制每一份扇形
        for (int i = 0; i < _list.length; i++) {
          // 求出初始角度
          double startRadius;
          if (i == 0) {
            startRadius = 0;
          } else {
            startRadius =
                _list.sublist(0, i).reduce((value, element) => value + element) *
                    radius;
          }
          //求出滑过角度,即当前份额乘以每份所占角度
          double sweepRadius = radius * _list[i];
          print("起始角度:$startRadius,划过角度:$sweepRadius");

          /// 绘制扇形,第一个参数是绘制矩形所在的矩形,第二个参数是起始角度,第三个参数是矩形划过的角度
          /// 第三个参数代表扇形是否是实心,否则就只是绘制边框是空心的,最后一个参数是画笔
          canvas.drawArc(boundingRect, startRadius, sweepRadius, true,
              getPaintByColor(_listColor[i]));
        }
      }

      //根据不同的 color 来获取对应的画笔
      Paint getPaintByColor(Color color) {
        Paint paint = Paint();
        paint.color = color;
        return paint;
      }

      //判断是否需要重绘
      @override
      bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this;
    }

    Padding getCustomPaint() {
      return Padding(
          padding: EdgeInsets.all(10),
          child: CustomPaint(
            size: Size(200, 200),
            painter: WheelPainter(
                List.of([1.0, 2.0, 3.0, 4.0, 20]),
                List.of([
                  Colors.red,
                  Colors.blue,
                  Colors.green,
                  Colors.amber,
                  Colors.black54
                ])),
          ));
    }
    展开

    作者回复: 很厉害👍!

     3
     3
  • 吴小安
    2019-08-01
    大前端的界面不是提倡尽量减少图层的数量?这样一直嵌套下去图层似乎太多,这些布局的控件是不是不算图层?不参与渲染?

    作者回复: 1.大部分都是非可视的容器,并不参与绘制;对于非透明的视图叠加,Flutter在绘制完毕后会做图层合并的

    
     3
  • 獸丶
    2019-08-02
    老师,Flutter代码规范方面会讲吗,如果代码全写在一个Dart文件里,有点太冗杂了,还是说遵循SRP,一个类一个Dart文件?

    作者回复: 后面会捎带讲一点点

    
     2
  • davidzhou
    2019-08-01
    我的思路这样,先自定义一个statefulwidget,里面用过一个变量控制两个text,因为text是statelesswidget,无法动态去刷新,一个widget设置Maxlines=2,另一个不设置,more是一个floatbutton,点击事件里面实现setstate改变先前定义的变量就行了

    作者回复: 赞

    
     2
  • 大土豆
    2019-08-01
    一看到Canvas,就知道又把rn和weex给秒杀了,这两家伙没有画布。。。没法绘制
     1
     2
  • Neil 陈荣
    2019-12-11
    老师,我想绘制一个围棋游戏的棋盘,并在上面实现落子、提子等各种操作。大致估计了一下,如果用组合的方案,算上棋子,棋盘,各种线,至少会有接近400个 widget. 这种情况下性能会有问题吗?我想知道 widget 数量一般在多少以内采用组合不会出现性能问题,这个有没有一个指导性的最佳实践?如果一上来就用自绘的方案的话,担心各种操作的交互功能不容易实现。谢谢!

    作者回复: 没啥问题,组件比较多的情况下,唯一需要关注的是限制界面的刷新范围,可以参考37节分享,用重绘边界去提前做一些缓存。

     1
     1
  • 🌙
    2019-08-23
    如果说尽量使用stateless,但是只要需要交互都必须是stateful吧?怎么尽量来使用成stateless呢?

    作者回复: 把组件拆小

    
     1
  • wanggw
    2019-08-22
    功能算是差不多实现了,但是还存在一个核心的问题不知道应该解决,就是我怎么获取Text展示文本的行数,我需要行数才能控制 more 按钮的显示和隐藏,否则我默认超过2行显示 more 按钮,当文本只有1行的时候,more 按钮也显示了😂。暂时还没找到解决方案。这是我写的例子:https://github.com/wanggw911/flutter_hello/blob/master/lib/widget/Listview02.dart

    作者回复: 如果想简单点,可以预估一个文本长度(比如100),超过这个文本长度的两行文字,统一都展示“More”按钮;如果想精确点,算文本高度可以用TextPainter。具体用法可以参考auto_size_text控件:https://github.com/leisim/auto_size_text

     2
     1
  • Captain
    2019-11-18
    老师,pi是在哪里定义的?

    作者回复: math.dart

    
    
  • 毛哥来了
    2019-10-24
    我是用Builder(builder: (Buildcontext context){})来创建description那个Text组件,然后就可以通过context.size.height获取Text的高度,然后就能判断按钮何时展示了

    作者回复: 赞

    
    
  • leslee
    2019-10-21
    老师我把你的案例跑起来了, 但是我把 我把计数器那个案列的代码里面的 MaterialApp 的 themeData 的 primaryColor 的颜色改成你的 ligjtblue[800] 后他报错, 报 type color is not a subtype of type materialcolor 我看了文档确实颜色是分好几个类型, 可是为什么你的可以运行我的不可以运行........

    作者回复: 看一下是不是头文件没引

     1
    
  • 离尘不离人คิดถึ...
    2019-10-20
    功能都实现了,抽象了一个有状态的组件:https://github.com/lichenbuliren/flutter_study/blob/master/lib/components/appUpdateItemCard.dart;
    基本思路:
    1、用 Contaner 的 decoration 绘制一个圆角白色渐变的白底;
    2、抽取 UI 组件,内部维护一个 『showMore』 状态
    3、描述文本组件根据 『showMore』 来动态设置 『maxLines』属性值,并且设置 『overflow』为省略号
    唯一存在的小瑕疵就是我的 FlatButton 控件中的文本一直存在 padding;手动设置了 0 也不生效;因为我看该章节里面的 『more』文本应该是靠右对齐的,这里麻烦老师帮忙看下,我尝试了各种方案都没法实现
    展开

    作者回复: 你参考36节的布局调试分享,直接在Flutter Inspector里改布局参数

    
    
  • zzz
    2019-10-08
    请问下,再混合开发的场景下,module类型的对于root Widget,我们必须使用MaterialApp或者CupertinoApp二选一么?如果不使用这两个基础的widgetApp,除了不能享受封装好的Theme、封装好的Widget组件这些便利外,是否有无法实现的基础功能(比如在iOS中的右滑返回等等)? 同时想问下目前国内很多App在安卓上的表现都不是Material风格的,同时也不完全是Cupertino风格,所以在实际应用中,主流的做法是使用 MaterialApp/CupertinoApp/完全自定义 这三种的哪一种呢?以及在开发过程中的是否有什么弊端呢?

    作者回复: MaterialApp和CupertinoApp封装了一些基本的App功能,比如导航栈管理、屏幕管理,国际化,以及对应的脚手架等,自己实现没有必要也基本不可能。样式就是一个配置而已,你可以自己定义不同平台的配置规则(具体参考夜间模式这一节)。另外他俩对Android/iOS的关键设计差异(如导航栏样式、状态栏样式、弹窗样式等),在框架内就进行了区分实现,所以如果你不定制样式,也无需过多担心在iOS上长得太像Android。

    
    
  • 🌝
    2019-09-20
    我把描述信息这块提成了一个有状态的widget,这样性能应该会更好些

    class DescriptionModel extends StatefulWidget {
      String desc;

      DescriptionModel({Key key, this.desc}) : super(key: key);

      _DescriptionModelState createState() => _DescriptionModelState();
    }

    class _DescriptionModelState extends State<DescriptionModel> {

      bool flag = false;

      void changeFlag (){
        print(flag);
        setState(() {
          flag = !flag;
        });
      }

      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            Text(widget.desc, maxLines: flag ? null : 2,),
            Positioned(
              bottom: 0,
              right: -5,
              child: FlatButton(
                // color: Colors.white,
                highlightColor: Colors.transparent,
                splashColor: Colors.transparent,
                onPressed: changeFlag,
                child: Container(child: Text('More', style: TextStyle(color: Colors.blue),), padding: EdgeInsets.fromLTRB(5,0,5,0), color: Colors.white,)
              ),
            )
          ],
        );
      }
    }

    功能是实现了,但是这个按钮摆放的位置让我很头疼,而且 按钮的样式也不知道该怎么去改变,我想去改变按钮的宽高以便让按钮显示的更正常些。
    展开

    作者回复: 可以试试shape、width、height这几个属性

    
    
  • 🌝
    2019-09-20
    我把描述信息这一块提成了一个有状态的widget
    
    
  • 和小胖
    2019-09-04
    老师,没太明白第二道题的意思,传入的数组的值是弧度吗?那这样的话,传入的数组的所有元素加起来得够 2π 是吗?

    作者回复: 传入的数组是数值类型,数组有几个元素饼图就画几块,而饼图每一块的面积占比对应着该元素的数值大小

    
    
  • 浣熊特工队
    2019-09-03
    请问老师,more按钮那里的左右渐隐是怎么实现的啊,我用TextOverflow.fade是向下渐隐的啊

    作者回复: 可以看下这个issue:https://github.com/flutter/flutter/issues/13631
    另外这种效果可以考虑用Button遮挡来实现

     1
    
  • 楼外楼
    2019-08-10
    哪些算是非可视容器呢?

    作者回复: 不参与绘制,仅参与布局,或是仅提供数据的组件

    
    
  • 灰灰
    2019-08-05
    class UpdateItemWidget extends StatefulWidget {
      final model;
      final onPressed;

      UpdateItemWidget({Key key, this.model, this.onPressed}) : super(key: key);
      @override
      State<StatefulWidget> createState() {
        return _UpdateItemState();
      }
    }
    class _UpdateItemState extends State<UpdateItemWidget> {
      bool collapse = true;
      @override
      void initState() {
        super.initState();
      }
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            buildTopRow(context),
            buildBottomRow(context),
          ],
        );
      }
     ....
      Widget buildBottomRow(BuildContext context) {
        return Padding(
          padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Row(
                children: <Widget>[
                  Expanded(
                    child: Text(
                      widget.model.appDescription,
                      maxLines: collapse ? 2 : null,
                      overflow: collapse ? TextOverflow.ellipsis : null),
                  ),
                  Container(
                    width: !collapse ? 0 : null,
                    child: FlatButton(
                      onPressed: () {
                        setState(() {collapse = false;});
                        },
                      child: Text('More', style: TextStyle(color: Colors.blue),),
                    )
                  ),
                ],
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
                child: Text("${widget.model.appVersion} • ${widget.model.appSize} MB"),
              )
            ],
          ),
        );
      }
    }
    展开

    作者回复: 功能没问题,不过你的按钮位置把Text位置挤压了

     1
    
  • 许童童
    2019-08-01
    老师,用Positioned组件设置
    right: 0,
    bottom: 0,
    FlatButton组件总对齐不了最下边。

    作者回复: 你把FlatButton换成RaisedButton就明白了

    
    
我们在线,来聊聊吧