全屏浏览
缩小浏览
回到页首

flutter ui---->一些类QQ的实现

整理一下比较有意思的类QQ的UI实现。Nothing that has meaning is easy. Easy doesn’t enter into grown-up life.

darken the background image

很多场景下,我们需要背景图片上面显示文字。如果是白色字体的话,那么暗化图片是必须的,否则会影响文字的显示。可以设置Container的decoration里面的colorFilter属性

decoration: BoxDecoration(
  image: DecorationImage(
  colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.4), BlendMode.darken),
  image: AssetImage("assets/image/me_header_bg.jpg"),
  fit: BoxFit.fitWidth,
),

显示的效果如下:原背景图片是亮色的

image-20200703083652553

实现类QQ的卡片展示效果

image-20200703091513549

  • 最外层的Container设置背景浅灰色:
Container(
  color: Color.fromRGBO(245, 246, 249, 1),
  child: UserToolWidget(tools)
)
  • 主体部分是UserToolWidget
class UserToolWidget extends StatelessWidget {
  final List<ToolResp> tools;

  UserToolWidget(this.tools);

  @override
  Widget build(BuildContext context) {
    List<Widget> widgetList = tools.map((tool) => _buildToolItem(context, tool)).toList();
    if (tools.length % 3 == 1) {
      widgetList.addAll([Container(color: Colors.white), Container(color: Colors.white)]);
    }
    if (tools.length % 3 == 2) {
      widgetList.add(Container(color: Colors.white));
    }
    return Padding(
      padding: const EdgeInsets.all(16),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(16.0),
        child: GridView.count(
          crossAxisCount: 3,
          physics: ClampingScrollPhysics(),
          shrinkWrap: true,
          mainAxisSpacing: 1.5,
          crossAxisSpacing: 1.5,
          children: widgetList,
        ),
      ),
    );
  }

  Widget _buildToolItem(BuildContext context, ToolResp tool) {
    Color color = CommUtil.getColorFromRGBOString(tool.iconColor);
    return GestureDetector(
      onTap: () => toolHandler.handleToolJump(tool.type, context),
      child: Container(
        color: Colors.white,
        alignment: Alignment.center,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SvgUtil.withColor(tool.iconName, color),
            SizedBox(height: 10),
            Text(tool.label, style: TextStyle(color: color)),
          ],
        ),
      ),
    );
  }
}

实现头像嵌入的效果

image-20200703103910949

Stack(
  overflow: Overflow.visible,
  alignment: Alignment.topCenter,
  children: <Widget>[
    GestureDetector(
      onTap: () => CommUtil.toBeDev(),
      child: Card(
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
        child: Container(
          padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
          child: Column(
            children: <Widget>[
              Text(user.fullName, style: TextStyle(fontSize: 26, fontWeight: FontWeight.w500)),
              Text('手机:${user.phone}', style: TextStyle(fontSize: 16)),
              SizedBox(height: 6),
              QrImage(data: user.phone, version: QrVersions.auto, size: 250.0),
              SizedBox(height: 6),
              Text("点击卡片更换背景", style: TextStyle(color: Colors.grey))
            ],
          ),
        ),
      ),
    ),
    Positioned(
      top: -40,
      child: CircleImageWidget(filename: user.imageUrl, size: 80, borderWidth: 3.0),
    )
  ],
)

实现swipe卡片的功能

image-20200703092833192

  • Swipe的代码
class FirstDaySwipeScreen extends StatelessWidget {
  final int index;

  FirstDaySwipeScreen(this.index);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<FirstDayBloc, FirstDayState>(
      builder: (_, FirstDayState state) {
        return Center(
          child: Container(
            height: 370,
            child: Swiper(
              index: index,
              loop: false,
              fade: 0.7,
              itemBuilder: (_, int index) {
                FirstDay firstDay = (state as FirstDayLoadSuccess).firstDays[index];
                return FirstDayItemWidget(index, firstDay);
              },
              itemCount: (state as FirstDayLoadSuccess).firstDays.length,
              viewportFraction: 0.8,
              scale: 0.9,
            ),
          ),
        );
      },
    );
  }
}
  • 主体部分是卡片
class FirstDayItemWidget extends StatelessWidget {
  final int index;
  final FirstDay firstDay;

  FirstDayItemWidget(this.index, this.firstDay);

  @override
  Widget build(BuildContext context) {
    final textColor = CommUtil.getColorByIndex(index);
    return Material(
      borderRadius: BorderRadius.all(Radius.circular(10)),
      clipBehavior: Clip.antiAlias,
      child: Container(
        alignment: Alignment.topCenter,
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomLeft,
            colors: <Color>[Color.fromRGBO(255, 227, 243, 1), Colors.white],
          ),
        ),
        child: Column(
          children: <Widget>[
            Padding(
              child: SvgUtil.convertFromFile('first_love', textColor, 80),
              padding: const EdgeInsets.only(top: 45, bottom: 20),
            ),
            Padding(
              child: Text('第一次${firstDay.description}', style: TextStyle(fontSize: 16)),
              padding: const EdgeInsets.only(bottom: 20),
            ),
            Divider(),
            _buildFirstDialogDate(firstDay),
            Divider(),
            SizedBox(height: 50),
            _buildConfirmButton(context, firstDay),
          ],
        ),
      ),
    );
  }

  _buildFirstDialogDate(FirstDay firstDay) {
    firstDay.firstDateTime = firstDay.firstDateTime ?? DateTime.now();
    return StatefulBuilder(builder: (BuildContext buildContext, StateSetter setState) {
      return InkWell(
        onTap: () {},
        child: Container(
          alignment: Alignment.topLeft,
          padding: const EdgeInsets.only(top: 6, bottom: 6, left: 20, right: 10),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Text(
                DateTimeUtil.formatDateTime(firstDay.firstDateTime),
                style: TextStyle(fontSize: 16),
              ),
              IconTheme(child: Icon(Icons.keyboard_arrow_right), data: IconThemeData(color: Colors.grey)),
            ],
          ),
        ),
      );
    });
  }

  _buildConfirmButton(BuildContext context, FirstDay firstDay) {
    return StatefulBuilder(
      builder: (BuildContext buildContext, StateSetter setState) {
        return RaisedButton(
          child: Text(firstDay.open ? '取消点亮' : '点亮', style: TextStyle(fontSize: 18)),
          shape: StadiumBorder(),
          padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 10),
          onPressed: () {},
          textColor: Colors.white,
          color: Color.fromRGBO(253, 111, 193, 1),
        );
      },
    );
  }
}

posted @ 2020-07-03 09:36  huhx  阅读(609)  评论(0编辑  收藏  举报