import 'package:flutter/material.dart';
class Demo01Page extends StatelessWidget {
const Demo01Page({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
// pinned: false - 这是关键设置,当设为 false 时,SliverAppBar 会在滚动时完全隐藏
// floating: false - 设为 false,只有滚动到顶部时才显示 AppBar
// snap: false - 禁用快速动画,让 AppBar 只在到达顶部时显示
// SliverAppBar 作为导航栏
SliverAppBar(
title: const Text('分栏布局演示'),
expandedHeight: 200,
floating: false,
pinned: false,
snap: false,
// 添加滚动行为控制
forceElevated: false,
// 设置背景透明度变化
backgroundColor: Colors.blue.shade600.withOpacity(0.9),
flexibleSpace: FlexibleSpaceBar(
// 滚动时标题的显示方式
titlePadding: const EdgeInsets.only(left: 16, bottom: 16),
title: const Text('Web端响应式布局'),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Colors.blue.shade600,
Colors.purple.shade600,
],
),
),
),
),
),
// 主要内容区域
SliverToBoxAdapter(
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 1200) {
// 大屏幕:三栏布局
return _buildThreeColumnLayout();
} else if (constraints.maxWidth > 800) {
// 中等屏幕:两栏布局
return _buildTwoColumnLayout();
} else {
// 小屏幕:单栏布局
return _buildSingleColumnLayout();
}
},
),
),
],
),
);
}
// 三栏布局(左侧导航 + 主内容 + 右侧边栏)
Widget _buildThreeColumnLayout() {
return Container(
height: 1800,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 左侧导航栏
Container(
width: 250,
color: Colors.grey.shade100,
child: _buildSidebar('左侧导航', Icons.menu),
),
// 主内容区
Expanded(
flex: 2,
child: Container(
padding: const EdgeInsets.all(16),
child: _buildMainContent(),
),
),
// 右侧边栏
Container(
width: 300,
color: Colors.blue.shade50,
child: _buildSidebar('右侧边栏', Icons.info),
),
],
),
);
}
// 两栏布局(左侧导航 + 主内容)
Widget _buildTwoColumnLayout() {
return Container(
height: 1800,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 左侧导航栏
Container(
width: 250,
color: Colors.grey.shade100,
child: _buildSidebar('侧边导航', Icons.menu),
),
// 主内容区
Expanded(
child: Container(
padding: const EdgeInsets.all(16),
child: _buildMainContent(),
),
),
],
),
);
}
// 单栏布局(移动端)
Widget _buildSingleColumnLayout() {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// 移动端导航按钮
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
const Icon(Icons.menu),
const SizedBox(width: 8),
const Text('移动端菜单'),
],
),
),
// 主内容
_buildMainContent(),
],
),
);
}
// 侧边栏组件
Widget _buildSidebar(String title, IconData icon) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, color: Colors.blue.shade600),
const SizedBox(width: 8),
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 16),
_buildMenuItems(),
],
),
);
}
// 菜单项
Widget _buildMenuItems() {
final items = [
'首页',
'产品',
'服务',
'关于我们',
'联系方式',
'博客',
'帮助',
];
return Column(
children: items.map((item) => Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 8),
child: InkWell(
onTap: () {},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: Colors.white,
border: Border.all(color: Colors.grey.shade300),
),
child: Text(item),
),
),
)).toList(),
);
}
// 主内容区
Widget _buildMainContent() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题区域
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue.shade400, Colors.purple.shade400],
),
borderRadius: BorderRadius.circular(12),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'响应式分栏布局',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 8),
Text(
'使用 SliverAppBar 实现的 Web 端响应式布局',
style: TextStyle(
fontSize: 16,
color: Colors.white70,
),
),
],
),
),
const SizedBox(height: 24),
// 特性介绍
_buildFeatureCards(),
const SizedBox(height: 24),
// 内容区域
_buildContentSections(),
],
);
}
// 特性卡片
Widget _buildFeatureCards() {
return LayoutBuilder(
builder: (context, constraints) {
final isWide = constraints.maxWidth > 600;
return Wrap(
spacing: 16,
runSpacing: 16,
children: [
_buildFeatureCard(
'SliverAppBar',
'可伸缩的应用栏',
Icons.expand_less,
Colors.blue,
isWide ? constraints.maxWidth / 3 - 16 : constraints.maxWidth,
),
_buildFeatureCard(
'响应式布局',
'适配不同屏幕尺寸',
Icons.devices,
Colors.green,
isWide ? constraints.maxWidth / 3 - 16 : constraints.maxWidth,
),
_buildFeatureCard(
'分栏设计',
'左右或三栏布局',
Icons.view_column,
Colors.orange,
isWide ? constraints.maxWidth / 3 - 16 : constraints.maxWidth,
),
],
);
},
);
}
Widget _buildFeatureCard(String title, String description, IconData icon, Color color, double width) {
return Container(
width: width,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(50),
),
child: Icon(icon, color: color, size: 32),
),
const SizedBox(height: 16),
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
description,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
),
),
],
),
);
}
// 内容区域
Widget _buildContentSections() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'布局说明',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
_buildContentCard(
'大屏幕 (>1200px)',
'三栏布局:左侧导航 + 主内容 + 右侧边栏',
Icons.desktop_windows,
Colors.blue,
),
const SizedBox(height: 16),
_buildContentCard(
'中屏幕 (800-1200px)',
'两栏布局:左侧导航 + 主内容',
Icons.tablet_mac,
Colors.green,
),
const SizedBox(height: 16),
_buildContentCard(
'小屏幕 (<800px)',
'单栏布局:垂直堆叠,适合移动设备',
Icons.phone_android,
Colors.orange,
), const SizedBox(height: 16),
_buildContentCard(
'小屏幕 (<800px)',
'单栏布局:垂直堆叠,适合移动设备',
Icons.phone_android,
Colors.orange,
),
const SizedBox(height: 16),
_buildContentCard(
'小屏幕 (<800px)',
'单栏布局:垂直堆叠,适合移动设备',
Icons.phone_android,
Colors.orange,
),
const SizedBox(height: 16),
_buildContentCard(
'小屏幕 (<800px)',
'单栏布局:垂直堆叠,适合移动设备',
Icons.phone_android,
Colors.orange,
),
const SizedBox(height: 16),
_buildContentCard(
'小屏幕 (<800px)',
'单栏布局:垂直堆叠,适合移动设备',
Icons.phone_android,
Colors.orange,
),
const SizedBox(height: 16),
],
);
}
Widget _buildContentCard(String title, String description, IconData icon, Color color) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade200),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: color, size: 24),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
description,
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
),
),
],
),
),
],
),
);
}
}
SliverAppBar Demo
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 方式清单 (先将jar包导完后) 方式一思路将数据库连接有关的信息配置到db.properties里为了方便跟进程...
- 先看demo 写在最前面 从开始学RN到现在大概有2个星期天左右了,这里先记录一下,也算个小阶段总结。就目前感觉,...
- 在Leetop官网取得使用权限后,可以在设备端做如下测试。此人形姿态检测demo容器支持视频文件的输入。该容器中使...
- 自动驾驶乱局背后,demo是demo,产品是产品。Demo看的是你在最好条件下的表现,产品看的是你在最坏条件下的表...