Альтернатива флаттеру в закусочной или более простой метод, чем завернуть все в эшафот? - PullRequest
3 голосов
/ 07 апреля 2019

Я работаю над своим первым приложением Flutter (отладка на моем телефоне Android).У меня есть список с элементами строки.Когда вы долго нажимаете на строку, она копирует содержимое в буфер обмена пользователя.Это прекрасно работает!

Но мне нужно сообщить пользователю, что контент был скопирован.

Я пытался следовать многим учебным пособиям при попытке окружить строку методом сборки.или внутри эшафот, но я не могу заставить кого-либо работать.Есть ли альтернативный способ уведомления пользователя (просто), что-то вроде «Скопировано!»имело место?

Обратите внимание на комментарий Scaffold.of(... ниже.Просто кажется, что должен быть более простой способ уведомления пользователя, чем завернуть все в Scaffold.(и когда я пытаюсь, это нарушает мой макет).

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 ]

3 голосов
/ 07 апреля 2019

Вы можете использовать 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 голос
/ 12 апреля 2019

Это простая замена плагина для Snackbar с именем "Flushbar".Вы можете получить плагин здесь - https://pub.dartlang.org/packages/flushbar Вам не нужно заботиться о переносе виджетов в скаффолд, а также вы получаете множество модификаций для вас, например, градиент фона, добавление форм и так далее в Snackbar и все,Внутри вашего onLongPressed в GestureDetectore вы можете сделать это.

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

Это покажет снэк-бар в вашем приложении, где вы хотели бы видеть его, а также вы можете получить множество модификаций, доступных для вас, чтобы вы могли сделатьэто выглядит согласно вашему приложению.

0 голосов
/ 25 июля 2019

Я сделал выпадающий баннер пакет на пабе, который позволяет легко уведомлять пользователей об ошибках или подтверждении успеха.Это работа в процессе, поскольку я продолжаю добавлять визуально богатые функции.

0 голосов
/ 12 апреля 2019

Я читаю ваши комментарии ко всем ответам и вот мое заключение:

Вам нужен ScaffoldState объект, который находится чуть выше виджета в дереве, чтобы показать Snackbar. Вы можете либо получить его через GlobalKey, как многие предложили. Довольно просто, если Scaffold создается внутри build виджета, но если он находится за пределами виджета (в вашем случае), тогда это становится сложным. Вам нужно передавать этот ключ везде, где он вам нужен, через аргументы конструктора дочерних виджетов.

Scaffold.of(context) - очень аккуратный способ сделать это. Так же, как InheritedWidget , Scaffold.of(BuildContext context) предоставляет вам доступ к ближайшему объекту ScaffoldState над деревом. Иначе это может быть кошмаром для получения этого экземпляра (передавая его в качестве аргумента конструктора), если ваше дерево было очень глубоким.

Извините, что разочаровал, но я не думаю, что есть лучший или более чистый метод, чем этот, если вы хотите получить ScaffoldState, который не встроен в сборку этого виджета. Вы можете вызвать его в любом виджете, который имеет Scaffold в качестве родителя.

0 голосов
/ 10 апреля 2019

Я не уверен, что ваш 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()),
    );
  }
}
0 голосов
/ 10 апреля 2019

Есть несколько вещей, которые вам нужно сделать, например, использовать onPressed свойство FlatButton, обязательно разрешать клики, обернуть GestureDetector в Scaffold.Далее я изменил код, чтобы он использовал GlobalKey, чтобы упростить вам задачу.

Вот окончательный код ( Твой путь )

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(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 Scaffold(
      key: globalKey,
      body: GestureDetector(
        onLongPress: () {
          Clipboard.setData(new ClipboardData(text: ruleGroup['label'] + " " + ruleGroup['details']));
          globalKey.currentState
            ..removeCurrentSnackBar()
            ..showSnackBar(SnackBar(content: Text('text copied')));
        },
        child: Container(
          margin: const EdgeInsets.symmetric(vertical: 3.0),
          child: new FlatButton(
            onPressed: () => print("Handle button press here"),
            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(),
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}
...