flutter ui---->一些类QQ的实现
2023-09-27 14:20:11 时间
整理一下比较有意思的类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),
);
},
);
}
}
相关文章
- 病毒木马查杀实战第009篇:QQ盗号木马之手动查杀
- QQ拼音输入法 禁用模糊音
- 【BZOJ3555】[Ctsc2014]企鹅QQ hash
- vue 仿QQ 开发流程
- Vue - 最新网页 H5 分享到微信朋友圈 / 转发分享给朋友好友 / 分享到手机 QQ / 分享到 QQ 空间,Vue.js Nuxt.js 通用公众号页面解决方案(超级详细教程)
- prometheus-operator告警模块alertmanager注意事项(QQ邮箱发送告警)--大大坑
- Java实现QQ邮件发送
- Android 接收微信、QQ其他应用打开,第三方分享
- iptables禁止QQ端口
- Linux_屏蔽360、scanv、QQ管家等IP扫描
- Flutter 插件url_launcher简介及使用,打开外部浏览器,拨打电话,发送短信,打开微信,支付宝,qq等
- Android自己定义对话框实现QQ退出界面
- Sql server用QQ邮箱发送邮件
- 通过 点击链接打开QQ或者TIM
- 新浪微博、腾讯微博、QQ空间、人人网、豆瓣 一键分享API
- [Android Studio]Android 数据存储-文件存储学习笔记-结合保存QQ账户与密码存储到指定文件中的演练
- 超简单一行代码实现应用双开,仿照微信双开、QQ双开等实现app应用双开,即采用Android插件化开发在免安装情况下加载使用原生app