flutter 同时使用go_router和Listview.builder的问题

6tqwzwtp  于 2023-10-22  发布在  Flutter
关注(0)|答案(2)|浏览(171)

我正在开发一个字典应用程序。我的主页,这是从主文件返回,应该有这样的话。我想在主屏幕上实现Go路由器,这是所谓的DictionaryScreenEnglish,并通过点击我想去路由器推到入口页面的话。我无法实现的onTap功能时,这些话是轻敲。下面是我的DictionaryScreenEnglish的代码

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:zeetionary/dictionary/english_dictionary/alphabet/letter_a/letters_ab/en_entry_aback.dart'; // a page that contains the entry for the word "aback"

final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/dictionaryenglish',
      builder: (BuildContext context, GoRouterState state) {
        return const DictionaryScreenEnglish();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'english/:aback',
          builder: (BuildContext context, GoRouterState state) {
            return EnglishEntryAback();
          },
        ),
      ],
    ),
  ],
);

class DictionaryScreenEnglish extends StatefulWidget {
  const DictionaryScreenEnglish({Key? key}) : super(key: key);

  @override
  State<DictionaryScreenEnglish> createState() =>
      _DictionaryScreenEnglishState();
}

class _DictionaryScreenEnglishState extends State<DictionaryScreenEnglish> {
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  final List<String> allWordsEnglish = [
    "aback",
    "abacus",
  ];
  List<String> filteredWords = [];
  final TextEditingController _searchController = TextEditingController();

  @override
  void initState() {
    super.initState();
    filteredWords = List.from(allWordsEnglish);
  }

  void filterWords(String query) {
    setState(() {
      filteredWords = allWordsEnglish
          .where((word) => word.toLowerCase().contains(query.toLowerCase()))
          .toList();
    });
  }

  void clearSearch() {
    _searchController.clear();
    filterWords('');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Directionality(
            textDirection: TextDirection.ltr,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: SizedBox(
                height: 60,
                child: TextField(
                  controller: _searchController,
                  onChanged: filterWords,
                  decoration: InputDecoration(
                    labelText: 'Search here',
                    prefixIcon: const Icon(Icons.search),
                    suffixIcon: IconButton(
                      icon: const Icon(Icons.clear),
                      onPressed: clearSearch,
                    ),
                    border: const OutlineInputBorder(),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            child: Directionality(
              textDirection: TextDirection.ltr,
              child: EnglishDictionary(
                words: filteredWords,
                onTapWord: (wordsEnglish) {
                  if (wordsEnglish == "aback") {
                    context.go('english/:aback');
                  }
                },
              ),
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }
}

class EnglishDictionary extends StatelessWidget {
  final List<String> words;
  final Function(String) onTapWord;

  const EnglishDictionary({
    Key? key,
    required this.words,
    required this.onTapWord,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: words.length,
      itemBuilder: (BuildContext context, int index) {
        return ListTileEnglish(
          wordsEnglish: words[index],
          onTap: () {
            onTapWord(words[index]);
          },
        );
      },
    );
  }
}

class ListTileEnglish extends StatelessWidget {
  final String wordsEnglish;
  final VoidCallback? onTap;

  const ListTileEnglish({
    Key? key,
    required this.wordsEnglish,
    this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: ListTile(
        key: key,
        title: Text(wordsEnglish),
        trailing: const Icon(Icons.arrow_forward),
      ),
    );
  }
}

class CardButton extends StatelessWidget {
  final String label;
  final VoidCallback? onPressed;

  const CardButton({
    Key? key,
    required this.label,
    this.onPressed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 50,
      child: Card(
        child: InkWell(
          onTap: onPressed,
          child: Center(
            child: Text(
              label,
              style: const TextStyle(fontSize: 16),
            ),
          ),
        ),
      ),
    );
  }
}
iq0todco

iq0todco1#

一个可能的问题是您尚未配置MaterialApp.router()。

void main() {
  runApp(MaterialApp.router(
    routerConfig: _router
  ));
}

另一个问题是你有一个嵌套的导航,你想导航到english/:aback,这不是你goRouter中的路径。如果你想用go()导航到正确的路径,你需要像这样指定整个路径:

onTapWord: (wordEnglish) {
   if (wordEnglish == "aback") {
      context.go('/dictionaryenglish/english/$wordEnglish');
   }
},

更改GoRouter以接受pathParameter:

GoRoute(
      path: 'english/:aback',
      builder: (BuildContext context, GoRouterState state) {
        final word = state.pathParameters['aback'] as String;
        if (word == 'aback') {
          // return your widget
        }
      },
    ),
qojgxg4l

qojgxg4l2#

我想也许onTap没有被触发到开始。尝试将ListTileEnglishCarButton的onTap`处理程序调用更新为如下内容:

class ListTileEnglish extends StatelessWidget {
...

  @override
  Widget build(BuildContext context) {
    return InkWell(
      ----> onTap: () => onTap(), <----
      child: ListTile(
        key: key,
        title: Text(wordsEnglish),
        trailing: const Icon(Icons.arrow_forward),
      ),
    );
  }

相关问题