Flutter Ui 实验室(十)Red Badget

有同学在QQ群里问动态Badget怎么实现?效果图如下


Flutter Ui 实验室(十)Red Badget_第1张图片
image.png

想了一下,可以用Stack和Positioned结合来实现,难点就是怎么获取到文字部分的坐标。

  1. 如果文字长度固定,那么可以使用LayoutBuilder来获取文字右上角的坐标
  2. 如果文字长度不固定,那么只能等build完成后,使用GlobalKey来获取文字的长度了。

考虑到动态徽章可以在页面build完成后再显示,那这里就采用第二种方法。

Stack(
                  overflow: Overflow.visible,
                  children: [
                    Text(
                      '你说啥?',
                      key: _key, //页面完成build后,使用这个_key来得到文字的长度
                      style: TextStyle(
                        fontSize: 16.0
                      ),
                    ),
                    Positioned(
                      left: _left,//动态徽章坐标
                      top: -6,
                      child: ClipRRect(
                        borderRadius: BorderRadius.all(
                          Radius.circular(4.0)
                        ),
                        child: Container(
                          color: Colors.redAccent, 
                          child: Padding(
                            padding: const EdgeInsets.only(
                              left: 3.0,
                              right: 3.0
                            ),
                            child: Text(_numStr),
                          )
                        ),
                      ),
                    )
                  ],
                )
// 获取到文字的长度
setState(() {
            _numStr = '99';
            _left = _key.currentContext.size.width; 
          });

点击浮动按钮后,获取到文字的长度,再显示动态徽章
效果图如下


Flutter Ui 实验室(十)Red Badget_第2张图片
image.png

当然这里只提供了思路,UI的细节只能根据要求慢慢调整了。
最后完整代码如下:

import 'package:flutter/material.dart';

class RedBadget extends StatefulWidget {
  @override
  _RedBadgetState createState() => _RedBadgetState();
}

class _RedBadgetState extends State {
  GlobalKey _key = GlobalKey();
  String _numStr = '99';
  double _left = -5000.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Red Badget'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _numStr = '99';
            _left = _key.currentContext.size.width;
          });
        },
        child: Icon(Icons.adjust),
      ),
      body: Container(
        child: Center(
          child: Container(
            // width: 100.0,
            color: Colors.blueAccent,
            child: LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints) {
                return Stack(
                  overflow: Overflow.visible,
                  children: [
                    Text(
                      '你说啥?',
                      key: _key,
                      style: TextStyle(
                        fontSize: 16.0
                      ),
                    ),
                    Positioned(
                      left: _left,
                      top: -6,
                      child: ClipRRect(
                        borderRadius: BorderRadius.all(
                          Radius.circular(4.0)
                        ),
                        child: Container(
                          color: Colors.redAccent, 
                          child: Padding(
                            padding: const EdgeInsets.only(
                              left: 3.0,
                              right: 3.0
                            ),
                            child: Text(_numStr),
                          )
                        ),
                      ),
                    )
                  ],
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

你可能感兴趣的:(Flutter Ui 实验室(十)Red Badget)