You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何实现Dashboard中可点击跳转的Card卡片组件

Flutter Dashboard卡片点击跳转实现方案

Card组件本身没有自带点击事件回调,要实现点击跳转效果,只需要用可响应点击的组件包裹Card,在点击回调中触发路由跳转即可,优先推荐用InkWell包裹,自带Material Design规范的水波纹点击反馈,体验更好。

实现步骤

  • 先创建好每个功能卡片对应的目标页面,所有页面都是普通的Flutter页面组件,包含Scaffold根布局即可
  • 给每个Card外层套一层InkWell,设置和Card完全一致的圆角参数,避免水波纹效果溢出直角
  • 在InkWell的onTap回调中,调用Navigator.push方法传入对应目标页的实例,完成跳转

关键代码示例

单卡片修改写法:

// 功能介绍卡片
InkWell(
  borderRadius: BorderRadius.circular(8), // 和Card圆角保持一致
  onTap: () {
    // 点击执行路由跳转
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const DescriptionPage()),
    );
  },
  child: Card(
    shape:RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8)
    ),
    elevation: 4,
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        CircleAvatar(
            radius: 64,
            backgroundImage: NetworkImage(''),
        ),
        Text(
          'Description',
          style: cardTextStyle,
        )
      ],
    ),
  ),
)

目标页面最简示例(其余卡片对应页面都可以参照这个结构编写):

class DescriptionPage extends StatelessWidget {
  const DescriptionPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('功能介绍')),
      body: const Center(child: Text('这里放介绍页的业务内容')),
    );
  }
}

注意事项

  • 不要把InkWell写在Card的child属性里,否则点击热区只会覆盖卡片内部内容,无法响应整个卡片区域的点击
  • 如果不需要水波纹点击反馈,可以把InkWell替换为GestureDetector,onTap回调的写法完全一致,只是没有默认的材质交互效果
  • 路由跳转使用的context必须是位于MaterialApp子树中的上下文,否则会出现找不到路由的报错
  • 剩余的新闻、信息、报名等卡片,只需要复制上述InkWell包裹Card的结构,替换onTap中跳转的目标页面类即可,后续要扩充到6个功能卡片逻辑完全相同

修改后的完整可运行代码

import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;

    var cardTextStyle = TextStyle(
        fontFamily: "Open Sans",
        fontSize: 14,
        color: Color.fromRGBO(63, 63, 63, 1));

    return Scaffold(
      body: Stack(
        children: <Widget>[
          Container(
            height: size.height * .3,
            decoration: BoxDecoration(
              image: DecorationImage(
                  alignment: Alignment.topCenter,
                  image: AssetImage('')),
            ),
          ),
          SafeArea(
            child: Padding(
              padding: EdgeInsets.all(16.0),
              child: Column(
                children: <Widget>[
                  Container(
                    height: 64,
                    margin: EdgeInsets.only(bottom: 20),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        CircleAvatar(
                          radius: 32,
                          backgroundImage: NetworkImage(
                              'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Crystal_Clear_kdm_user_female.svg/2048px-Crystal_Clear_kdm_user_female.svg.png'),
                        ),
                        SizedBox(
                          width: 16,
                        ),
                        Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              'User',
                              style: TextStyle(
                                  fontFamily: "Open Sans",
                                  color: Colors.black,
                                  fontSize: 20),
                            ),
                            Text(
                              'ID:4101410141',
                              style: TextStyle(
                                  fontSize: 14,
                                  color: Colors.black,
                                  fontFamily: "Open Sans"),
                            )
                          ],
                        )
                      ],
                    ),
                  ),
                  Expanded(
                    child: GridView.count(
                      mainAxisSpacing: 10,
                      crossAxisSpacing: 10,
                      primary: false,
                      crossAxisCount: 2, // 6个功能推荐改成2列布局展示效果更好,可根据需求自行调整
                      children: <Widget>[
                        // 介绍卡片
                        InkWell(
                          borderRadius: BorderRadius.circular(8),
                          onTap: () {
                            Navigator.push(context, MaterialPageRoute(builder: (context) => const DescriptionPage()));
                          },
                          child: Card(
                            shape:RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(8)
                            ),
                            elevation: 4,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                CircleAvatar(
                                    radius: 32,
                                    backgroundImage: NetworkImage(''),
                                ),
                                SizedBox(height: 8),
                                Text(
                                  'Description',
                                  style: cardTextStyle,
                                )
                              ],
                            ),
                          ),
                        ),
                        // 新闻卡片
                        InkWell(
                          borderRadius: BorderRadius.circular(8),
                          onTap: () {
                            Navigator.push(context, MaterialPageRoute(builder: (context) => const NewsPage()));
                          },
                          child: Card(
                            shape:RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(8)
                            ),
                            elevation: 4,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                CircleAvatar(
                                  radius: 32,
                                  backgroundImage: NetworkImage(''),
                                ),
                                SizedBox(height: 8),
                                Text(
                                  'News',
                                  style: cardTextStyle,
                                )
                              ],
                            ),
                          ),
                        ),
                        // 信息卡片
                        InkWell(
                          borderRadius: BorderRadius.circular(8),
                          onTap: () {
                            Navigator.push(context, MaterialPageRoute(builder: (context) => const InformationPage()));
                          },
                          child: Card(
                            shape:RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(8)
                            ),
                            elevation: 4,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                CircleAvatar(
                                  radius: 32,
                                  backgroundImage: NetworkImage(
                                      'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Messagebox_info.svg/1200px-Messagebox_info.svg.png'),
                                ),
                                SizedBox(height: 8),
                                Text(
                                  'Information',
                                  style: cardTextStyle,
                                )
                              ],
                            ),
                          ),
                        ),
                        // 报名卡片
                        InkWell(
                          borderRadius: BorderRadius.circular(8),
                          onTap: () {
                            Navigator.push(context, MaterialPageRoute(builder: (context) => const RegistrationPage()));
                          },
                          child: Card(
                            shape:RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(8)
                            ),
                            elevation: 4,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                CircleAvatar(
                                  radius: 32,
                                  backgroundImage: NetworkImage(''),
                                ),
                                SizedBox(height: 8),
                                Text(
                                  'Registration',
                                  style: cardTextStyle,
                                )
                              ],
                            ),
                          ),
                        ),
                        // 剩下两个功能卡片照着上面的结构新增即可
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 以下是各个目标页的最简示例,实际业务内容可以自行替换
class DescriptionPage extends StatelessWidget {
  const DescriptionPage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('功能介绍')), body: const Center(child: Text('介绍页')));
  }
}
class NewsPage extends StatelessWidget {
  const NewsPage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('新闻资讯')), body: const Center(child: Text('新闻页')));
  }
}
class InformationPage extends StatelessWidget {
  const InformationPage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('通知信息')), body: const Center(child: Text('信息页')));
  }
}
class RegistrationPage extends StatelessWidget {
  const RegistrationPage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('报名登记')), body: const Center(child: Text('报名页')));
  }
}

内容的提问来源于stack exchange,提问作者NewUser556

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:36:23