整理一下比较有意思的类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,
),

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

实现类QQ的卡片展示效果

  • 最外层的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)),
],
),
),
);
}
}

实现头像嵌入的效果

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卡片的功能

  • 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),
);
},
);
}
}

flutter ui---->一些类QQ的实现的更多相关文章

  1. Android代码优化----Application节点的模板写法及UI工具类

    一. MyApplication类的编写: 新建一个类MyApplication,继承自Application.代码如下: MyApplication.java: package com.smyhva ...

  2. iOS开发——项目实战OC篇&类QQ黏性按钮(封装)

    类QQ粘性按钮(封装) 那个,先来说说原理吧: 这里原理就是,在界面设置两个控件一个按钮在上面,一个View在下面(同样大小),当我们拖动按钮的时候显示下面的View,view不移动,但是会根据按钮中 ...

  3. Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  4. CSS 伪类(下)结构性伪类\UI伪类\动态伪类和其他伪类 valid check enable child required link visit

      伪类选择器汇总伪类选择器有4种, 结构性伪类\UI伪类\动态伪类和其他伪类. 具体如下 结构性伪类选择器结构性伪类选择器它能够根据元素在文档中的位置选择元素, 这类元素都有个前缀":&q ...

  5. CSS链接四种状态注意顺序、UI伪类选择器的顺序

    css定义超链接是要有先后顺序的.否则,可能会出现某个或某几个样式不起作用的bug.例如:visited与hover顺序颠倒了,则不能显示hover和active的样式了. 正确的顺序: a:link ...

  6. [cocos2dx笔记012]一定简易的UI配置类

    使用cocostudio能够装载编辑好的UI,可是过于复杂.特别是在加截UI后,发现触屏事件有些问题. 假设直接使用程序写死载入UI又过于麻烦.花点时间,添加了一个基于ini的UI配置类,眼下仅仅实现 ...

  7. Flutter UI系统

    我们可以看到,无论是Android SDK还是iOS的UIKit 的职责都是相同的,它们只是语言载体和底层的系统不同而已.那么可不可以实现这么一个UI系统:可以使用同一种编程语言开发,然后针对不同操作 ...

  8. Flutter & UI system & GUI & API & SDK

    Flutter & UI system & GUI & API & SDK https://book.flutterchina.club/chapter14/flutt ...

  9. 全网最详细的一篇Flutter 尺寸限制类容器总结

    Flutter中尺寸限制类容器组件包括ConstrainedBox.UnconstrainedBox.SizedBox.AspectRatio.FractionallySizedBox.Limited ...

  10. Flutter 容器Container类和布局Layout类

    1.布局和容器 [布局]是把[容器]按照不同的方式排列起来. Scaffold包含的主要部门:appBar,body,bottomNavigator 其中body可以是一个布局组件,也可以是一个容器组 ...

随机推荐

  1. WebStore 破解

    前提 你需要首先安装该软件,并下载补丁,不过这些已经为你打包好了. WebStore 2020.1 , jetbrains-agent.jar , resources_zh_CN_WebStorm_2 ...

  2. Java下 BigDecimal类型数值的计算(转)

    BigDecimal bignum1 = new BigDecimal("40"); BigDecimal bignum2 = new BigDecimal("7&quo ...

  3. Ext中数据表格序号超过3位数时显示省略号

    问题 在老项目上优化时,遇到了Ext中ColumnModel序号超过3位数时,自动显示了省略号,不友好 修改方法 给RowNumberer添加样式 new Ext.grid.RowNumberer({ ...

  4. vue+高德地图配置及添加marker

    1.首先在index.html中引入高德地图 <script type="text/javascript" src="https://webapi.amap.com ...

  5. C++ PTA 小于m的最大的10个素数

    7-5 小于m的最大的10个素数 (15分) 给定一个整数m(50<m<20000),找出小于m的最大的10个素数. 输入格式: 输入在一行中给出一个正整数m(50<m<200 ...

  6. FCC 高级算法题 库存更新

    Inventory Update 依照一个存着新进货物的二维数组,更新存着现有库存(在 arr1 中)的二维数组. 如果货物已存在则更新数量 . 如果没有对应货物则把其加入到数组中,更新最新的数量. ...

  7. C语言转义序列

    转义序列 含义 \a 报警(ANSIC) \b 退格 \f 换页 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \\ 反斜杆\ \' 单引号 \" 双引号 \? 问号 \0oo ...

  8. 转载:谷歌浏览器一些https打不开点击高级不行的解决办法

    转载:https://blog.51cto.com/u_15275035/2925642 关于谷歌浏览器一些https网站打不开点击高级不行的解决办法有些url,在谷歌浏览器上打不开,点击高级也没有继 ...

  9. svn备份迁移

    参考链接: SVN版本库的迁移 dump的详细使用 https://www.iteye.com/blog/tdcq-1684344 svn备份与还原_脚本_(dump命令)

  10. PostgreSQL 数组类型使用详解

    PostgreSQL 数组类型使用详解 PostgreSQL 数组类型使用详解 可能大家对 PostgreSQL 这个关系型数据库不太熟悉,因为大部分人最熟悉的,公司用的最多的是 MySQL 我们先对 ...