与将所有东西包装在脚手架中相比,Flutter快餐栏替代品还是更简单的方法?

时间:2019-04-07 01:16:01

标签: flutter notifications snackbar

我正在开发我的第一个Flutter应用程序(在我的Android手机上调试)。我有一个包含行项目的列表。长按该行时,它将内容复制到用户的剪贴板中。这很棒!

但是我需要让用户知道内容已被复制。

我尝试遵循许多教程,以使行被构建方法或在Scaffold中包围,但是我什么都无法工作。是否有另一种方法可以(简单地)通知用户“已复制!”之类的信息。发生了吗?

请注意下面的注释Scaffold.of(...。似乎除了将所有内容包装在脚手架中外,还必须有一种通知用户的简便方法。 (而且当我尝试时,它会破坏我的布局)。

import 'package:flutter/material.dart';
import 'package:my_app/Theme.dart' as MyTheme;
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/services.dart';

class RowRule extends StatelessWidget {
  final DocumentSnapshot ruleGroup;

  RowRule(this.ruleGroup);

  _buildChildren() {
    var builder = <Widget>[];
    if (!ruleGroup['label'].isEmpty) {
      builder.add(new Text(ruleGroup['label'],
          style: MyTheme.TextStyles.articleContentLabelTextStyle));
    }
    if (!ruleGroup['details'].isEmpty) {
      builder.add(new Text(ruleGroup['details'],
          style: MyTheme.TextStyles.articleContentTextStyle));
    }
    return builder;
  }


  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
        onLongPress: () {
          Clipboard.setData(new ClipboardData(text: ruleGroup['label'] + " "  + ruleGroup['details']));
//          Scaffold.of(context).showSnackBar(SnackBar
//            (content: Text('text copied')));
        },
        child: Container(
          margin: const EdgeInsets.symmetric(vertical: 3.0),
          child: new FlatButton(
            color: Colors.white,
            padding: EdgeInsets.symmetric(horizontal: 0.0),
            child: new Stack(
              children: <Widget>[
                new Container(
                  margin: const EdgeInsets.symmetric(
                    vertical: MyTheme.Dimens.ruleGroupListRowMarginVertical),
                  child: new Container(
                      child: Padding(
                        padding: EdgeInsets.symmetric(horizontal: 32.0, vertical: 8.0),
                        child: new Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: _buildChildren(),
                        ),
                    )),
              )
            ],
          ),
        ),
      ));
    }
  }

我的目标是要有一个这样的页面(请参见图片),并且可以工作并滚动...等等,但是我无法使其与脚手架一起使用,因此无法使用小吃吧。每个“行”(此文件用于该行)应在longPress上显示一个小吃栏。

enter image description here

6 个答案:

答案 0 :(得分:3)

您可以使用GlobalKey使它按您希望的方式工作。

enter image description here

由于我无权访问您的数据库资料,因此这就是我给您的一个想法。复制此代码并将其粘贴到您的班级中,并进行相应的更改。我也相信您的RowRule类中存在问题,您可以复制我给您的完整代码并运行吗?

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatelessWidget {
  final GlobalKey<ScaffoldState> _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFFFFFFFF).withOpacity(0.9),
      key: _key,
      body: Column(
        children: <Widget>[
          Container(
            color: Color.fromRGBO(52, 56, 245, 1),
            height: 150,
            alignment: Alignment.center,
            child: Container(width: 56, padding: EdgeInsets.only(top: 12), decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.yellow)),
          ),
          Expanded(
            child: ListView.builder(
              padding: EdgeInsets.zero,
              itemCount: 120,
              itemBuilder: (context, index) {
                return Container(
                  color: Colors.white,
                  margin: const EdgeInsets.all(4),
                  child: ListTile(
                    title: Text("Row #$index"),
                    onLongPress: () => _key.currentState
                      ..removeCurrentSnackBar()
                      ..showSnackBar(SnackBar(content: Text("Copied \"Row #$index\""))),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

答案 1 :(得分:1)

这些是Snackbar名为“ Flushbar”的简单插件替代。 您可以在此处获取插件-https://pub.dartlang.org/packages/flushbar 您不必照顾小部件到脚手架中的任何包裹,还可以为您做很多修改,例如背景渐变,在Snackbar中添加表格等。 在GestureDetectore的onLongPressed内部,您可以执行此操作。

onLongPressed:(){
Clipboard.setData(new ClipboardData(text: ruleGroup['label'] + " "  + ruleGroup['details']));
Flushbar(
             message:  "Copied !!",
             duration:  Duration(seconds: 3),              
          )..show(context);
}

这将在您想要查看的位置显示您的应用程序中的小吃店,您还可以进行很多修改,以便可以按照您的应用程序显示它。

答案 2 :(得分:0)

您需要做几件事,例如使用onPressed的{​​{1}}属性,必须允许点击,将FlatButton包装在GestureDetector中。我进一步修改了代码,以便它使用Scaffold来简化您的工作。

这是最终代码(您的方式

GlobalKey

答案 3 :(得分:0)

我不确定您的build()方法是否已完成或尚未更改,因为它包含许多多余的小部件。就像没有必要在Container中加入Container,并在Padding中再加上FlatButton,这将使整个屏幕都可点击。同时拥有Column也不是一个好主意,因为如果您有更多数据,屏幕可能会溢出。请改用ListView

因此,如果您接受我的建议,请使用此简单的代码即可为您提供真正的所需。 (请参见build()方法只有5行。

class RowRule extends StatelessWidget {
  final GlobalKey<ScaffoldState> globalKey = GlobalKey();

  final DocumentSnapshot ruleGroup;

  RowRule(this.ruleGroup);

  _buildChildren() {
    var builder = <Widget>[];
    if (!ruleGroup['label'].isEmpty) {
      builder.add(
        ListTile(
          title: Text(ruleGroup['label'], style: MyTheme.TextStyles.articleContentLabelTextStyle),
          onLongPress: () {
            globalKey.currentState
              ..removeCurrentSnackBar()
              ..showSnackBar(SnackBar(content: Text("Clicked")));
          },
        ),
      );
    }
    if (!ruleGroup['details'].isEmpty) {
      builder.add(
        ListTile(
          title: Text(ruleGroup['details'], style: MyTheme.TextStyles.articleContentTextStyle),
          onLongPress: () {
            globalKey.currentState
              ..removeCurrentSnackBar()
              ..showSnackBar(SnackBar(content: Text("Clicked")));
          },
        ),
      );
    }
    return builder;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: globalKey,
      body: ListView(children: _buildChildren()),
    );
  }
}

答案 4 :(得分:0)

我阅读了您对所有答案的评论,这是我的结论:

您需要ScaffoldState对象,它在树中的窗口小部件上方,才能显示Snackbar。正如许多人建议的那样,您可以通过GlobalKey获得它。如果Scaffold是在小部件的build内部创建的,则相当简单,但如果在小部件外部(以您的情况为准),则变得很复杂。您需要通过子窗口小部件的构造函数参数在任何需要的地方传递该密钥。

Scaffold.of(context)是一种非常简洁的方法。就像InheritedWidget一样,Scaffold.of(BuildContext context)使您可以访问树上方最近的ScaffoldState对象。否则,如果您的树很深,那么获取该实例(通过将其作为构造函数参数传递)可能是一场噩梦。

对不起,令人失望的是,但是如果您想获得不是在该小部件的内部版本中构建的ScaffoldState,那么我认为没有比这更好或更干净的方法了。您可以在具有Scaffold作为父级的任何小部件中调用它。

答案 5 :(得分:0)

我在酒吧上放置了一个下拉横幅package,可让您轻松地将错误或成功确认通知用户。随着我继续添加丰富的视觉功能,这项工作正在进行中。