news 2026/7/14 17:22:10

Flutter---CustomScrollView的UI项目(1)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter---CustomScrollView的UI项目(1)

效果图

详细介绍:整体分为3个部分,一个是顶部固定的信息栏,一个是滑动的列表,还有一个是底部固定的播放栏。

重点内容

// 理解基础布局组件 Stack( // 层叠布局:背景+内容+底部栏 children: [ Container(), // 背景层 CustomScrollView(), // 内容滚动层 Positioned() // 底部固定层 ], ) // 理解滚动布局 CustomScrollView( slivers: [ SliverAppBar(), // 固定头部 SliverToBoxAdapter(), // 列表内容 ], ) // 理解组件封装 Widget buildItem({ // 参数化组件 required String title, required String icon, VoidCallback? callback }) { return Container(...); } // 理解状态管理 class SleepPage extends StatefulWidget { @override State<StatefulWidget> createState() => _SleepPage(); }

实现步骤

1.背景渐变

Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white, Colors.purple.withOpacity(0.7), ], ), ), ),

2.可滚动的内容

CustomScrollView( slivers: [ // 顶部信息固定区域 SliverAppBar( expandedHeight: 270, //展开高度 collapsedHeight: 270, //收起高度(与展开相同=固定高度) pinned: true, //固定在顶部,不让滑动 snap: false, floating: false, automaticallyImplyLeading: false, backgroundColor: Colors.transparent, elevation: 0, flexibleSpace: Stack( //实际内容区 children: [ //背景容器 Positioned.fill( child: Image.asset( "assets/images/start.png", fit: BoxFit.cover, ), ), // 标题行 Positioned( top:50, left: 10, right: 0, child: Row( children: [ SizedBox(width: 20), GestureDetector( onTap: () => Navigator.pop(context), child: Image.asset("assets/images/back_white.png",width: 20,height: 20,), ), Spacer(), Text( "标题栏", style: TextStyle(color: Colors.white, fontSize: 24), ), Spacer(), SizedBox(width: 20), ], ), ), // 耳机图 Positioned( top: 109, left: 0, right: 0, child: Container( height: 141, child: Image.asset( "assets/images/earphone.png", fit: BoxFit.contain, ), ), ), ], ), ), // 内容列表 SliverToBoxAdapter( child: Column( children: [ buildItem( title: "列表1", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表2", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表3", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表4", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表5", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表6", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表7", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表8", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表9", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), // 添加底部间距,为固定播放栏留出空间 const SizedBox(height: 80), // 播放栏高度 + 边距 ], ), ), ], ),

3.固定在底部的播放栏

Positioned( left: 10, right: 15, bottom: 15, // 距离底部的距离 child: Container( height: 60, padding: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( color: const Color(0xFF2C2C2E), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ Image.asset("assets/images/cherry.png",), const SizedBox(width: 10), const Text( "Rain", style: TextStyle(color: Colors.white), ), const Spacer(), Image.asset("assets/images/mango.png",), const SizedBox(width: 10), Image.asset("assets/images/banana.png"), ], ), ), ),

4.小卡片的通用组件

Widget buildItem({ required String title, required String icon, required String rightIcon, VoidCallback? callback }) { return Container( padding: EdgeInsets.symmetric(horizontal: 20), margin: EdgeInsets.only(left: 15,right: 20), height: 52, width: double.infinity, decoration:BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Material( color: Colors.transparent, child: Ink( child: InkWell( onTap: callback, child: Row( children: [ Image.asset(icon), SizedBox(width: 15,), Text(title,style: const TextStyle(color: Colors.white,fontSize: 18),), const Expanded(child: SizedBox()), Image.asset(rightIcon), ], ) ), ), ) ); }

代码实例

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class SleepPage extends StatefulWidget { const SleepPage({super.key}); @override State<StatefulWidget> createState() => _SleepPage(); } class _SleepPage extends State<SleepPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.transparent, body: Stack( children: [ //1.背景渐变 Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white, Colors.purple.withOpacity(0.7), ], ), ), ), // 2. 可滚动内容 CustomScrollView( slivers: [ // 顶部信息固定区域 SliverAppBar( expandedHeight: 270, //展开高度 collapsedHeight: 270, //收起高度(与展开相同=固定高度) pinned: true, //固定在顶部,不让滑动 snap: false, floating: false, automaticallyImplyLeading: false, backgroundColor: Colors.transparent, elevation: 0, flexibleSpace: Stack( //实际内容区 children: [ //背景容器 Positioned.fill( child: Image.asset( "assets/images/start.png", fit: BoxFit.cover, ), ), // 标题行 Positioned( top:50, left: 10, right: 0, child: Row( children: [ SizedBox(width: 20), GestureDetector( onTap: () => Navigator.pop(context), child: Image.asset("assets/images/back_white.png",width: 20,height: 20,), ), Spacer(), Text( "标题栏", style: TextStyle(color: Colors.white, fontSize: 24), ), Spacer(), SizedBox(width: 20), ], ), ), // 耳机图 Positioned( top: 109, left: 0, right: 0, child: Container( height: 141, child: Image.asset( "assets/images/earphone.png", fit: BoxFit.contain, ), ), ), ], ), ), // 内容列表 SliverToBoxAdapter( child: Column( children: [ buildItem( title: "列表1", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表2", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表3", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表4", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表5", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表6", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表7", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表8", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), buildItem( title: "列表9", icon: "assets/images/apple.png", rightIcon: "assets/images/apple.png", ), const SizedBox(height: 8), // 添加底部间距,为固定播放栏留出空间 const SizedBox(height: 80), // 播放栏高度 + 边距 ], ), ), ], ), // 3. 固定在底部的播放栏 Positioned( left: 10, right: 15, bottom: 15, // 距离底部的距离 child: Container( height: 60, padding: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( color: const Color(0xFF2C2C2E), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ Image.asset("assets/images/cherry.png",), const SizedBox(width: 10), const Text( "Rain", style: TextStyle(color: Colors.white), ), const Spacer(), Image.asset("assets/images/mango.png",), const SizedBox(width: 10), Image.asset("assets/images/banana.png"), ], ), ), ), ], ), ); } //功能小卡片 Widget buildItem({ required String title, required String icon, required String rightIcon, VoidCallback? callback }) { return Container( padding: EdgeInsets.symmetric(horizontal: 20), margin: EdgeInsets.only(left: 15,right: 20), height: 52, width: double.infinity, decoration:BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Material( color: Colors.transparent, child: Ink( child: InkWell( onTap: callback, child: Row( children: [ Image.asset(icon), SizedBox(width: 15,), Text(title,style: const TextStyle(color: Colors.white,fontSize: 18),), const Expanded(child: SizedBox()), Image.asset(rightIcon), ], ) ), ), ) ); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 17:19:03

MP8859与PIC18F46K20的DC-DC降压转换系统设计

1. 项目背景与硬件选型解析在嵌入式电源设计中&#xff0c;DC-DC降压转换是一个基础但至关重要的环节。171010550&#xff08;经查证为MP8859芯片的型号代码&#xff09;与PIC18F46K20的组合&#xff0c;为构建智能可调的降压电源系统提供了理想的硬件平台。MP8859作为MPS公司推…

作者头像 李华
网站建设 2026/7/14 17:16:31

kupl-sample并行for循环详解:1D到3D并行化完整指南

kupl-sample并行for循环详解&#xff1a;1D到3D并行化完整指南 【免费下载链接】kupl-sample kupl-sample provides a set of cases using the kupl library . 项目地址: https://gitcode.com/openeuler/kupl-sample 前往项目官网免费下载&#xff1a;https://ar.openeu…

作者头像 李华
网站建设 2026/7/14 17:13:41

三步轻松获取国家中小学智慧教育平台电子课本PDF文件

三步轻松获取国家中小学智慧教育平台电子课本PDF文件 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具&#xff0c;帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载&#xff0c;让您更方便地获取课本内容。 项目地址: https://gi…

作者头像 李华
网站建设 2026/7/14 17:13:20

Unity外发光Shader避坑指南:从边缘发黑到闪烁的深度优化

1. 项目概述&#xff1a;从“能用”到“好用”的外发光Shader之路在Unity项目里给角色、UI或者场景物件加个外发光&#xff0c;听起来是个挺基础的需求&#xff0c;网上随便一搜就能找到一堆现成的Shader代码。但真当你把代码复制粘贴到项目里&#xff0c;兴奋地拖到材质球上时…

作者头像 李华
网站建设 2026/7/14 17:13:05

A3908与PIC18F45K22的直流电机精密控制方案

1. 项目背景与核心器件选型在精密运动控制领域&#xff0c;直流电机的驱动方案选择直接影响系统性能。A3908作为Allegro MicroSystems推出的低压恒压驱动器&#xff0c;与Microchip的PIC18F45K22微控制器组合&#xff0c;构成了一个兼顾精度与灵活性的解决方案。这套组合特别适…

作者头像 李华