zoukankan      html  css  js  c++  java
  • 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),
            );
          },
        );
      }
    }
    

  • 相关阅读:
    【2017-4-26】Winform 公共控件 菜单和工具栏
    【2017-4-24】Winform 简单了解 窗口属性
    【2017-4-21】ADO.NET 数据库操作类
    【2017-4-21】ADO.NET 防止字符串注入攻击
    【2017-4-19】ADO.NET 数据库链接,基础增删改
    Vue#条件渲染
    Vue#Class 与 Style 绑定
    Vue#计算属性
    Vue入门笔记#数据绑定语法
    Vue入门笔记#过渡
  • 原文地址:https://www.cnblogs.com/huhx/p/13228534.html
Copyright © 2011-2022 走看看