Flutter,交错 flutter_staggered_grid_view 使每个图 block 可点击而不破坏布局

标签 flutter dart flutter-dependencies flutter-animation flutter-gridview

这里是新开发人员,需要一些专业知识。我正在尝试创建一个自定义的交错 GridView ,该 View 还允许每个图 block 可点击并进入不同的页面。

我尝试过使用墨水池,但我似乎无法对每个单独的瓷砖都这样做。然后就进入了手势检测器。我可以使用手势检测器将整个 GridView 包装为可点击,但这使得整个网格可点击,并且所有内容都进入一个页面。

知道如何使每个单独的图 block 可点击,然后将其链接到另一个页面吗?当我尝试为每个人做这件事时,它完全破坏了布局。使每个图 block 大小相同。然后我尝试使每个图 block 尺寸可定制,但这不起作用。我尝试使用 chatGPT 使其全部可定制,但它无法完全实现这一目标。忽略顶部图像资源。

感谢任何和所有帮助。即使我需要使用其他东西来构建我想做的事情。查看其当前状态的示例图像。

actual state of app now, screenshot of phone

在 Windows 上使用 Visual Studio

依赖项: flutter : sdk: flutter

cupertino_icons:^1.0.2 谷歌字体:^5.1.0 flutter_staggered_grid_view:^0.7.0

我尝试过使用聊天 GPT 来要求它确实使每个图 block 可点击,保持原始图 block 大小,每个图 block 指向不同的页面,但我不断地浏览网络和更长的代码库,它最终无法获得什么我需要它来做。

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  google_fonts: ^5.1.0
  flutter_staggered_grid_view: ^0.7.0

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:google_fonts/google_fonts.dart';

class FantasyHome extends StatelessWidget {
  const FantasyHome({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('new app'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          Image.asset(
            'assets/images/bannerbig.png',
            fit: BoxFit.cover,
            width: double.infinity,
          ),
          Expanded(
            child: SingleChildScrollView(
              child: GestureDetector(
                // Wraped the StaggeredGrid with GestureDetector
                onTap: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => PointsPage(),
                    ),
                  );
                },
                child: StaggeredGrid.count(
                  crossAxisCount: 4,
                  mainAxisSpacing: 4,
                  crossAxisSpacing: 4,
                  children: const [
                    StaggeredGridTile.count(
                      crossAxisCellCount: 2,
                      mainAxisCellCount: 2,
                      child: Tile(
                        index: 0,
                        color: Color.fromARGB(255, 255, 255, 255),
                        customText: '50\npoints',
                        fontSize: 30,
                      ),
                    ),
                    StaggeredGridTile.count(
                      crossAxisCellCount: 2,
                      mainAxisCellCount: 1,
                      child: Tile(
                        index: 1,
                        color: Color.fromARGB(255, 129, 173, 180),
                        customText: 'Leagues',
                      ),
                    ),
                    StaggeredGridTile.count(
                      crossAxisCellCount: 1,
                      mainAxisCellCount: 1,
                      child: Tile(
                        index: 2,
                        color: Colors.green,
                        customText: 'Stats',
                      ),
                    ),
                    StaggeredGridTile.count(
                      crossAxisCellCount: 1,
                      mainAxisCellCount: 1,
                      child: Tile(
                        index: 3,
                        color: Colors.red,
                        customText: 'Custom Text for Tile 3',
                      ),
                    ),
                    StaggeredGridTile.count(
                      crossAxisCellCount: 4,
                      mainAxisCellCount: 2,
                      child: Tile(
                        index: 4,
                        color: Colors.purple,
                        customText: 'Custom Text for Tile 4',
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class Tile extends StatelessWidget {
  final int index;
  final Color color;
  final double fontSize;
  final String? customText;

  const Tile({
    required this.index,
    required this.color,
    this.fontSize = 15, // Provide a default value for fontSize.
    this.customText,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      color: color,
      child: Center(
        child: Text(
          customText ?? 'Tile $index',
          style: GoogleFonts.openSans(
            fontSize: fontSize,
            color: const Color.fromARGB(255, 0, 0, 0),
          ),
        ),
      ),
    );
  }
}

// Placeholder page for demonstration purposes.
class PointsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Points Page')),
      body: Center(child: Text('Points Page Content')),
    );
  }
}

from the comment I tried this: 

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:google_fonts/google_fonts.dart';

class FantasyHome extends StatelessWidget {
  const FantasyHome({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('new app'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          Image.asset(
            'assets/images/bannerbig.png',
            fit: BoxFit.cover,
            width: double.infinity,
          ),
          Expanded(
            child: SingleChildScrollView(
              child: GestureDetector(
                // Wrap the StaggeredGrid with GestureDetector
                onTap: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => PointsPage(),
                    ),
                  );
                },
                child: StaggeredGridView.countBuilder(
                  crossAxisCount: 4,
                  itemCount: 4,
                  mainAxisSpacing: 4,
                  crossAxisSpacing: 4,
                  staggeredTileBuilder: (index) => StaggeredTile.fit(2),
                  itemBuilder: (context, index) {
                    return GestureDetector(
                      onTap: () {
                        switch (index) {
                          case 0:
                            Navigator.pushNamed(context, '/tile1');
                            break;
                          case 1:
                            Navigator.pushNamed(context, '/tile2');
                            break;
                          case 2:
                            Navigator.pushNamed(context, '/tile3');
                            break;
                          case 3:
                            Navigator.pushNamed(context, '/tile4');
                            break;
                        }
                      },
                      child: Tile(
                        index: index,
                        color: index == 0
                            ? Color.fromARGB(255, 255, 255, 255)
                            : index == 1
                                ? Color.fromARGB(255, 129, 173, 180)
                                : index == 2
                                    ? Colors.green
                                    : Colors.red,
                        customText: index == 0 ? '50\npoints' : 'Custom Text for Tile $index',
                        fontSize: index == 0 ? 30 : 15,
                      ),
                    );
                  },
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class Tile extends StatelessWidget {
  final int index;
  final Color color;
  final double fontSize;
  final String? customText;

  const Tile({
    required this.index,
    required this.color,
    this.fontSize = 15, // Provide a default value for fontSize.
    this.customText,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      color: color,
      child: Center(
        child: Text(
          customText ?? 'Tile $index',
          style: GoogleFonts.openSans(
            fontSize: fontSize,
            color: const Color.fromARGB(255, 0, 0, 0),
          ),
        ),
      ),
    );
  }
}

// Placeholder page for demonstration purposes.
class PointsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Points Page')),
      body: Center(child: Text('Points Page Content')),
    );
  }
}

void main() {
  runApp(MaterialApp(
    home: FantasyHome(),
    routes: {
      // Define routes for individual pages
      '/tile1': (context) => TilePage(tile: tiles[0]),
      '/tile2': (context) => TilePage(tile: tiles[1]),
      '/tile3': (context) => TilePage(tile: tiles[2]),
      '/tile4': (context) => TilePage(tile: tiles[3]),
    },
  ));
}

// Sample data for the tiles
final List<TileModel> tiles = [
  TileModel(title: 'Tile 1', description: 'Description for Tile 1'),
  TileModel(title: 'Tile 2', description: 'Description for Tile 2'),
  TileModel(title: 'Tile 3', description: 'Description for Tile 3'),
  TileModel(title: 'Tile 4', description: 'Description for Tile 4'),
];

class TileModel {
  final String title;
  final String description;

  TileModel({required this.title, required this.description});
}

class TilePage extends StatelessWidget {
  final TileModel tile;

  TilePage({required this.tile});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(tile.title)),
      body: Center(
        child: Text(tile.description),
      ),
    );
  }
}


但这使得这一切发生: enter image description here

最佳答案

在您的 Tile 小部件中,使用 GestureDetectorInkWell 包裹卡片,并设置 onTap 处理程序以在点击时执行您想要的操作。

GestureDetectorInkWell 都是“隐形”小部件,不会更改应用的布局或外观。如果您希望点击时 Material 出现颜色飞溅,请使用 InkWell,否则请使用 GestureDetector。

关于Flutter,交错 flutter_staggered_grid_view 使每个图 block 可点击而不破坏布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76799432/

相关文章:

flutter - 错误 : Cannot invoke a non -'const' constructor where a const expression is expected

flutter - WebRTC : not working on WIFI/works on Mobile Data

dart - 在点击图标时呈现屏幕

flutter - 在 Flutter 中初始化时带有错误表情符号的文本小部件

android - 类型 'List<dynamic>' 不是类型“Uint8List”的子类型

flutter - Flutter:我想访问setstate的更改后的值,访问它时未显示新的状态值

flutter - 在 IDE 中打开 Flutter 应用时,scrcpy 不会运行

binding - 如何查询 dom-repeat 中的元素

android - Razorpay 在支付页面崩溃,在 flutter 中找不到类 "com.razorpay.d__1_"

android - Play 商店删除应用后,新版本卡在 "Ready to send for review"