简体   繁体   English

Flutter - 在同一屏幕上的小部件之间传递数据

[英]Flutter - Passing data between widgets on same screen

I have one screen split into 2 halves.我将一个屏幕分成两半。 Top half has a listview and the bottom will display the details based on the onTap: from the listTile within the listview above.上半部分有一个列表视图,底部将显示基于onTap 的详细信息:来自上面列表视图中的 listTile。

My code looks something like this, after removing all irrelevant pieces:在删除所有不相关的部分后,我的代码看起来像这样:

return Scaffold(
  appBar: AppBar(
    ...
    // app bar details
      ...
    ), // AppBar

body: SingleChildScrollView (
        child: Column(
            children: <Widget>[ 
             ...
             Container(
                ...
                child: populatelistview();
                ), 

             SizedBox(height: ...),
              ...
              ...
             Container(
                ...
                child: detailsView();
                ),
             ... 
            ],
          ), // Column
     ) // SingleChildScrollView

So, in order to get the detailsView populated with data based on onTap() from listview, I will have to pass some variable (or some id), from the listview to detailsView.因此,为了从 listview 中获取使用基于 onTap() 的数据填充的 detailsView,我必须将一些变量(或一些 id)从 listview 传递到 detailsView。

I have used Navigator.push before (refer: https://flutter.dev/docs/cookbook/navigation/passing-data ), but that would work only when moving from one screen to another.我以前使用过 Navigator.push (请参阅: https://flutter.dev/docs/cookbook/navigation/passing-data ),但这仅在从一个屏幕移动到另一个屏幕时才有效。 I am having trouble sending data from listview to detailsView, on the same screen.我无法在同一屏幕上将数据从 listview 发送到 detailsView。

Maybe I am looking at it differently or just unable to search properly.也许我对它的看法不同,或者只是无法正确搜索。

Would appreciate if someone could point me in the right direction.如果有人能指出我正确的方向,将不胜感激。

If this question is already answered before, then I apologize for the same - please do mark it as duplicate and point me to the correct discussion.如果这个问题之前已经回答过,那么我对此表示歉意 - 请务必将其标记为重复并指出正确的讨论。

Thanks in advance.提前致谢。

Stay Safe!!注意安全!!

I would suggest you to use provider state management this will be easy to implement, your both view will have the some ChangeNotifier,Here some snippest that may helps you:我建议您使用提供商 state 管理,这将很容易实现,您的两个视图都会有一些 ChangeNotifier,这里有一些可能对您有帮助的片段:


populatelistview: 填充列表视图:

 GestureDetector( onTap: (){ notifier.setId(id); }, child:// your child


detailsView: 详情查看:

class Notifier extends ChangeNotifier {

int id;

void setId(int id){
  this.id = id;
  notifyListeners();// Here the magic happens
}


Change notifier 更改通知程序

class Notifier extends ChangeNotifier { int id; void setId(int id){ this.id = id; notifyListeners();// Here the magic happens }

You can pass information like this.你可以像这样传递信息。 Use a variable within your class to store the information of the clicked item.使用 class 中的变量来存储单击项目的信息。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: MyWidget(),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  int _item;

  @override
  void initState() {
    super.initState();
    _item = null;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Expanded(
            child: ListView.builder(
                itemCount: 100,
                itemBuilder: (context, i) {
                  return ListTile(
                    title: Text('Item $i'),
                    onTap: () => setState(() => _item = i),
                  );
                }),
          ),
          Container(height: 2, color: Colors.grey),
          Expanded(
            child: Container(
              color: Colors.grey[100],
              child: Center(
                child: Text(_item == null
                    ? 'Select an item'
                    : 'Item $_item was selected',),
              ),
            ),
          ),
        ]);
  }
}

结果

Hope this helps!希望这可以帮助!

If this is a stateful widget, then try using setState()如果这是一个stateful的小部件,请尝试使用setState()

See sample code below:请参阅下面的示例代码:

class Test extends State<StatusPage> {
String text = 'Hello';

  @override
  Widget build(BuildContext context) {

    Widget details = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Text(text),
      ],
    );

    return Scaffold(
      appBar: AppBar(),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            ListView.builder(
              itemCount: 4,
              shrinkWrap: true,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text('Item #$index'),
                  onTap: () {
                    setState(() {
                      text == 'Hello' ? text = 'Test' : text = 'Hello';
                    });
                  },
                );
              },
            ),
            SizedBox(height: 54),
            details,
          ],
        ), // Column
      ),
    );
  }


}

Thanks to everyone who tried helping me out.感谢所有试图帮助我的人。 However, I have now resolved this issue by using Inherited Widget.但是,我现在已经通过使用 Inherited Widget 解决了这个问题。

Inherited Widget was more suitable for my situation where I needed data to flow from one widget to another without change of screen. Inherited Widget 更适合我需要数据从一个小部件流向另一个小部件而不改变屏幕的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM