Futter3 仿抖音我的页面or用户详情页

效果图如下,就一个仿抖音个人主页的一串代码,如果大家有什么好的写法希望能分享一下,效果图如下。

dart 复制代码
import 'package:flutter/material.dart';
import 'package:theme/app_theme.dart';

class UserDetailPage extends StatefulWidget {
  const UserDetailPage({super.key});

  @override
  State<UserDetailPage> createState() => _UserDetailPageState();
}

class _UserDetailPageState extends State<UserDetailPage>
    with SingleTickerProviderStateMixin {
  //滑动监听
  final ScrollController _scrollController = ScrollController();
  // TabController (修改为3个标签页,可根据需要调整)
  late TabController _tabController;
  // 封面高度
  static const double coverHeight = 140.0;
  // appbar 透明度
  double appBarOpacity = 0.0;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
    // 初始化TabController,length对应标签数量
    _tabController = TabController(length: 3, vsync: this);
  }

  void _onScroll() {
    setState(() {
      double offset = _scrollController.offset;
      if (offset < 0) {
        appBarOpacity = 0.0;
      } else if (offset < coverHeight) {
        appBarOpacity = offset / coverHeight;
      } else {
        appBarOpacity = 1.0;
      }
    });
  }

  @override
  void dispose() {
    _scrollController.removeListener(_onScroll);
    _scrollController.dispose();
    _tabController.dispose(); // 释放TabController
    super.dispose();
  }

  // 构建每个Tab对应的内容页面
  Widget _buildTabViewContent(String tabName) {
    return Container(
      decoration: BoxDecoration(color: Colors.grey[200]),
      padding: const EdgeInsets.all(20.0),
      child: Text(
        tabName,
        style: const TextStyle(
          fontSize: 24.0,
          fontWeight: FontWeight.bold,
          color: Colors.black,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        backgroundColor: Colors.white.withOpacity(appBarOpacity),
        elevation: appBarOpacity > 0.1 ? 4.0 : 0.0,
        leading: IconButton(
          icon: Icon(
            Icons.arrow_back,
            color: appBarOpacity > 0.5 ? Colors.black : Colors.white,
          ),
          onPressed: () => Navigator.pop(context),
        ),
      ),
      body: CustomScrollView(
        controller: _scrollController,
        physics: const BouncingScrollPhysics(),
        slivers: [
          SliverAppBar(
            expandedHeight: coverHeight,
            snap: false,
            // 滚动时固定在顶部
            pinned: false,
            floating: false,
            // 下滑超过范围时拉伸(实现放大效果)
            stretch: true,
            // 拉伸时的回调(可选,用于自定义放大逻辑)
            onStretchTrigger: () async {},
            collapsedHeight: coverHeight,
            // 背景透明度和阴影随滚动变化
            flexibleSpace: FlexibleSpaceBar(
              collapseMode: CollapseMode.none, // 关键:关闭渐隐
              // 拉伸模式:向下滑动时图片从中心放大
              stretchModes: const [StretchMode.zoomBackground],
              // 背景图片
              background: Stack(
                fit: StackFit.expand,
                children: [
                  // 背景图片(自动跟随StretchMode放大)
                  Image.network(
                    // 替换成你的图片地址
                    'https://picsum.photos/800/400',
                    fit: BoxFit.cover,
                    width: MediaQuery.of(context).size.width,
                  ),
                  // 可选:添加渐变遮罩,让文字更清晰
                  const DecoratedBox(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [Colors.transparent, Colors.black],
                      ),
                    ),
                  ),
                  // 头像 白色边框
                  Positioned(
                    left: 20,
                    bottom: 45,
                    child: SafeArea(
                      child: Row(
                        children: [
                          //头像增加白色边框2
                          Container(
                            decoration: BoxDecoration(
                              border: Border.all(color: Colors.white, width: 2),
                              shape: BoxShape.circle,
                            ),
                            child: CircleAvatar(
                              radius: 40,
                              backgroundColor: Colors.white,
                              backgroundImage: NetworkImage(
                                "https://picsum.photos/200/200",
                              ),
                            ),
                          ),
                          const SizedBox(width: 15),
                          Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                "用户昵称",
                                style: TextStyle(
                                  color: Colors.white,
                                  fontSize: 18,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              Text(
                                "用户简介",
                                style: TextStyle(
                                  color: Colors.grey[400],
                                  fontSize: 13,
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
            backgroundColor: const Color.fromARGB(255, 255, 255, 255),
            bottom: PreferredSize(
              preferredSize: const Size.fromHeight(1),
              child: Container(
                height: 20,
                width: MediaQuery.of(context).size.width,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(16),
                    topRight: Radius.circular(16),
                  ),
                ),
              ),
            ),
          ),
          SliverToBoxAdapter(
            child: Container(
              width: MediaQuery.of(context).size.width,
              color: Colors.white,
              padding: const EdgeInsets.symmetric(
                horizontal: 16.0,
                vertical: 0,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // 获赞、关注、粉丝数据
                  const Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: [
                      Text(
                        '205.6万',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: Colors.black,
                        ),
                      ),
                      Text(
                        ' 获赞',
                        style: TextStyle(fontSize: 14, color: Colors.black),
                      ),
                      SizedBox(width: 24),
                      Text(
                        '443',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: Colors.black,
                        ),
                      ),
                      Text(
                        ' 关注',
                        style: TextStyle(fontSize: 14, color: Colors.black),
                      ),
                      SizedBox(width: 24),
                      Text(
                        '42.0万',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: Colors.black,
                        ),
                      ),
                      Text(
                        ' 粉丝',
                        style: TextStyle(fontSize: 14, color: Colors.black),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16), // IP地址和性别标签
                  Row(
                    children: [
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 8,
                          vertical: 2,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.grey[200],
                          borderRadius: BorderRadius.circular(4),
                        ),
                        child: Text(
                          'IP: 河北',
                          style: TextStyle(
                            fontSize: 12,
                            color: Colors.grey[600],
                          ),
                        ),
                      ),
                      const SizedBox(width: 12),
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 8,
                          vertical: 2,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.grey[200],
                          borderRadius: BorderRadius.circular(4),
                        ),
                        child: Text(
                          '男',
                          style: TextStyle(
                            fontSize: 12,
                            color: Colors.grey[600],
                          ),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 20),

                  // 关注按钮和分享按钮
                  Row(
                    children: [
                      Expanded(
                        child: Container(
                          height: 48,
                          decoration: BoxDecoration(
                            color: Colors.red,
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: const Center(
                            child: Text(
                              '+ 关注',
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 16,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                        ),
                      ),
                      const SizedBox(width: 12),
                      Container(
                        width: 48,
                        height: 48,
                        decoration: BoxDecoration(
                          border: Border.all(
                            color: Colors.grey[300]!,
                            width: 1,
                          ),
                          borderRadius: BorderRadius.circular(8),
                        ),
                        child: Icon(
                          Icons.share_outlined,
                          size: 20,
                          color: Colors.grey[600],
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 20), // 增加间距
                  // ========== 新增:TabBar ==========
                  TabBar(
                    controller: _tabController,
                    isScrollable: true,
                    tabAlignment: TabAlignment.start,
                    dividerColor: Colors.transparent,
                    // 怎么设置第一个标签左边的间距
                    labelPadding: const EdgeInsets.only(left: 0.0, right: 20.0),

                    tabs: const [
                      Tab(text: '作品'),
                      Tab(text: '动态'),
                      Tab(text: '收藏'),
                    ],
                  ),
                ],
              ),
            ),
          ),

          // ========== 新增:TabBarView 内容区域 ==========
          SliverFillRemaining(
            child: TabBarView(
              controller: _tabController,
              // 三个Tab对应的内容
              children: [
                _buildTabViewContent('作品'),
                _buildTabViewContent('动态'),
                _buildTabViewContent('收藏'),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

还有就是这种头像溢出效果怎么实现啊,sliverAppbar感觉就没有办法实现,他必须要固定高度,而且背景图还是铺开的.

相关推荐
Haha_bj2 小时前
Flutter ——device_info_plus详解
android·flutter·ios
前端小伙计2 小时前
Android/Flutter 项目统一构建配置最佳实践
android·flutter
微祎_3 小时前
Flutter for OpenHarmony:形状拼图游戏开发全指南 - 基于Flutter CustomPaint的可拖拽矢量拼图实现与设计理念
flutter
不爱吃糖的程序媛3 小时前
解锁Flutter鸿蒙开发新姿势——flutter_ohfeatures插件集实战指南
flutter
一只大侠的侠4 小时前
React Native开源鸿蒙跨平台训练营 Day16自定义 useForm 高性能验证
flutter·开源·harmonyos
子春一4 小时前
Flutter for OpenHarmony:绿氧 - 基于Flutter的呼吸训练应用开发实践与身心交互设计
flutter·交互
ujainu4 小时前
告别杂乱!Flutter + OpenHarmony 鸿蒙记事本的标签与分类管理(三)
android·flutter·openharmony
ZH15455891315 小时前
Flutter for OpenHarmony Python学习助手实战:API接口开发的实现
python·学习·flutter
一只大侠的侠5 小时前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos