简体   繁体   English

Flutter:如何将快照传递给浮动操作按钮?

[英]Flutter: How to pass snapshot to floating action button?

I want to pass this documentSnapshot to my FloatingActionButton so that I can use it on another page, but how?我想将此documentSnapshot传递到我的FloatingActionButton以便我可以在另一个页面上使用它,但是如何呢? I want to pass the documentSnapshot data to my AddTaskPage .我想将documentSnapshot数据传递给我的AddTaskPage

My documentSnapshot is under StreamBuilder .我的documentSnapshotStreamBuilder下。

This is my code:这是我的代码:

final DocumentSnapshot documentSnapshot = snapshot.data!.docs[index];

This is my FloatingActionButton :这是我的FloatingActionButton

floatingActionButton: FadeInRight(
  delay: const Duration(milliseconds: 200),
  duration: const Duration(milliseconds: 500),
  child: FloatingActionButton.extended(
  label: const Text(
    'Add Timeline',
    style: TextStyle(
      color: Colors.white,
      fontFamily: 'poppins',
      fontWeight: FontWeight.w400,
      fontSize: 15,
      letterSpacing: 1,
    ),
  ),
  backgroundColor: Colors.black,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(6),
  ),
  onPressed: () {
    showModalBottomSheet(
      // isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
        context: context,
        builder: (context) => const AddTaskPage(),
      );
    },
  ),
),

This is my AddTaskPage() code:这是我的 AddTaskPage() 代码:

    import 'package:animate_do/animate_do.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:todoapp/authentication/auth.provider.dart';
import 'package:todoapp/models/timeline.model.dart';
import 'package:todoapp/services/notifications_service.dart';

class AddTaskPage extends StatefulWidget {
  const AddTaskPage({
    super.key,
  });
  @override
  State<AddTaskPage> createState() => _AddTaskPageState();
}

class _AddTaskPageState extends State<AddTaskPage> {
  final dateController = TextEditingController();
  final timeController = TextEditingController();
  final topicController = TextEditingController();

  final _formKey = GlobalKey<FormState>();

  final db = FirebaseFirestore.instance;

  final notifyHelper = NotifyHelper();

  DocumentReference uidRef = FirebaseFirestore.instance
      .collection('timeline')
      .doc(FirebaseAuth.instance.currentUser!.uid);

  void dateOnTap() async {
    TimeOfDay? pickTime = await showTimePicker(
        context: context,
        initialEntryMode: TimePickerEntryMode.input,
        initialTime: TimeOfDay.now());
    if (pickTime != null) {
      DateTime parsedTime =
          DateFormat.jm().parse(pickTime.format(context).toString());
      //converting to DateTime so that we can further format on different pattern.
      String formattedTime = DateFormat().add_jm().format(parsedTime);
      setState(() {
        timeController.text = formattedTime;
//  DateFormat.yMMMMd().format(pickTime);
      });
    }
  }

  // String uidFunction(String uid) {
  //   // dart unique string generator
  //   String _randomString = uid.toString() +
  //       math.Random().nextInt(9999).toString() +
  //       math.Random().nextInt(9999).toString() +
  //       math.Random().nextInt(9999).toString();
  //   return _randomString;
  // }

  void addFunction() async {
    final uid =
        await Provider.of<AuthProvider>(context, listen: false).getCurrentUID();
    DocumentReference ref =
        db.collection('users').doc(uid).collection('time-line').doc();
    if (dateController.text.trim().isNotEmpty &&
        timeController.text.trim().isNotEmpty &&
        topicController.text.trim().isNotEmpty) {
      await db
          .collection('users')
          .doc(uid)
          .collection('time-line')
          .add(Timeline(
                  id: ref.id, // auto generated id
                  date: dateController.text.trim(),
                  time: timeController.text.trim(),
                  topic: topicController.text.trim(),
                  isDone: false)
              .toJson());

      // DateTime date = DateFormat.jm().parse(timeController.text.toString());
      // var myTime = DateFormat('HH:mm').format(date);
      // var hour = int.parse(formattedTime.toString().split(':')[0]);
      // var min = int.parse(formattedTime.toString().split(':')[1]);

      notifyHelper.displayNotification(
          title: topicController.text.trim(), body: 'Don\'t forget your task!');

      // notifyHelper.scheduledNotification(hour, min, timeline);
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
          content: Text(
        'All fields required!',
        style: TextStyle(fontFamily: 'poppins', fontWeight: FontWeight.w400),
      )));
    }
    Navigator.of(context).pop();
  }

  void cancelAddFunction() {
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15),
      child: Column(
        children: [
          Container(
            width: 60,
            height: 5,
            decoration: BoxDecoration(
                color: Colors.grey.shade300,
                borderRadius: BorderRadius.circular(10)),
          ),
          const SizedBox(
            height: 20,
          ),
          const Align(
            alignment: Alignment.topLeft,
            child: Text(
              'Add timeline 🗓️',
              style: TextStyle(
                  color: Colors.black,
                  fontFamily: 'poppins',
                  fontWeight: FontWeight.w500,
                  fontSize: 20,
                  letterSpacing: 1),
            ),
          ),
          const SizedBox(
            height: 30,
          ),
          Form(
            key: _formKey,
            child: Column(
              children: [
                textFieldDate(
                    dateController, 'Date', Icons.date_range_outlined),
                const SizedBox(
                  height: 20,
                ),
                textFieldTime(
                    timeController,
                    DateFormat.jm().format(DateTime.now()),
                    const Icon(
                      Icons.calendar_month_outlined,
                      color: Colors.black,
                    ),
                    dateOnTap),
                const SizedBox(
                  height: 20,
                ),
                textFieldTopic(
                    topicController,
                    'Topic',
                    const Icon(
                      Icons.topic_outlined,
                      color: Colors.black,
                    )),
              ],
            ),
          ),
          Expanded(child: Container()),
          btnSection()
        ],
      ),
    );
  }

  Widget textFieldDate(
    controller,
    hintText,
    icon,
  ) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        readOnly: true,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        onTap: (() async {
          DateTime? pickDate = await showDatePicker(
              context: context,
              initialDate: DateTime.now(),
              firstDate: DateTime(2000),
              lastDate: DateTime(3000));
          if (pickDate != null) {
            setState(() {
              controller.text = DateFormat.yMMMMd().format(pickDate);
            });
          }
        }),
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: Icon(
              icon,
              color: Colors.black,
            ),
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget textFieldTime(controller, hintText, icon, dateOnTap) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        readOnly: true,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        onTap: dateOnTap,
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: icon,
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget textFieldTopic(controller, hintText, icon) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        minLines: 1,
        maxLines: 3,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: icon,
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget btnAddTimeline(addFunction, text) {
    return FadeInUp(
      duration: const Duration(milliseconds: 500),
      delay: const Duration(milliseconds: 200),
      child: ElevatedButton(
          onPressed: addFunction,
          style: ButtonStyle(
              elevation: MaterialStateProperty.all(0),
              backgroundColor: MaterialStateProperty.all(Colors.black),
              fixedSize: MaterialStateProperty.all(const Size(0, 54)),
              shape: MaterialStateProperty.all(RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)))),
          child: Text(
            text,
            style: const TextStyle(
                color: Colors.white,
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 17,
                letterSpacing: 1),
          )),
    );
  }

  Widget btnCancelAddTimeline(cancelAddFunction, icon) {
    return FadeInLeft(
      duration: const Duration(milliseconds: 500),
      delay: const Duration(milliseconds: 200),
      child: ElevatedButton(
          onPressed: cancelAddFunction,
          style: ButtonStyle(
              side: MaterialStateProperty.all(
                  const BorderSide(color: Colors.black)),
              elevation: MaterialStateProperty.all(0),
              backgroundColor: MaterialStateProperty.all(Colors.white),
              fixedSize: MaterialStateProperty.all(const Size(0, 54)),
              shape: MaterialStateProperty.all(RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)))),
          child: Icon(
            icon,
            color: Colors.black,
          )),
    );
  }

  Widget btnSection() {
    return Row(
      children: [
        Expanded(
            flex: 1,
            child: btnCancelAddTimeline(cancelAddFunction, Icons.clear)),
        const SizedBox(
          width: 10,
        ),
        Expanded(
            flex: 4, child: btnAddTimeline(addFunction, 'Add New Timeline'))
      ],
    );
  }
}

Depend a lot of what you want to do with these data and where you define your document snapshot.很大程度上取决于您要对这些数据执行的操作以及定义文档快照的位置。

But reading your question, i guess your FAB is defined in a Scaffold and your StreamBuilder inside the Scaffold body?但是阅读您的问题,我猜您的 FAB 是在脚手架中定义的,而您的 StreamBuilder 是在脚手架体内定义的吗?

If so you can invert these and access documentSnapshot.data() in all of your Scaffold children (FAB included).如果是这样,您可以反转这些并在所有脚手架子项(包括 FAB)中访问documentSnapshot.data() )。 Something like that:像这样的东西:

StreamBuilder(
  stream: getUsersTimelineSnapshots(context)
    .map((snapshot) => snapshot.docs.toList()),
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      return Scaffold(
        body: Text('Error: ${snapshot.error}'),
      );
    }

    if (!snapshot.hasData) {
      return Scaffold(
        body: Text('Loading...'),
      );
    }

    return Scaffold(
      //Your FAB
      floatingActionButton: FadeInRight(
        delay: const Duration(milliseconds: 200),
        duration: const Duration(milliseconds: 500),
        child: FloatingActionButton.extended(
          label: const Text(
            'Add Timeline',
            style: TextStyle(
                color: Colors.white,
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                letterSpacing: 1),
          ),
          backgroundColor: Colors.black,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(6)),
          onPressed: () {
            showModalBottomSheet(
                // isScrollControlled: true,
                shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(10),
                        topRight: Radius.circular(10))),
                context: context,
                builder: (context) => const AddTaskPage(snapshot.data));//Here you will get a List<DocumentSnapshot>
          },
        ),
      ),
      //Rest of your old scaffold here
    );
  },
);

But again, without more infos about your code, it will be difficult to provide a more accurate answer.但是同样,如果没有关于您的代码的更多信息,将很难提供更准确的答案。

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

相关问题 Flutter:如果快照没有数据如何显示消息 - Flutter: How to show a message if snapshot has no data 如何获取数组中的所有快照 flutter firebase 云 - how to get snapshot all in an array flutter firebase cloud 如果用户在 flutter 中使用 email 或 gmail 登录,如何获取快照 - How to get snapShot if user have sign in with email or gmail in flutter 如何在 flutter 中禁用带有页面视图的滑动操作 - How to disable swipe action with page view in flutter Flutter Awesome Notification 无法将方法绑定到操作按钮 - Flutter Awesome Notification couldn't bind a method to action button Flutter:更新 Firebase 快照数据 - Flutter: update Firebase snapshot data 如何在 DropdownButton flutter 中的数组中放置 String 的 snapShot 列表 - How can I put a list of snapShot of String in array inside the DropdownButton flutter 如何使用 object snapshot.data 在简单的 flutter-dart 代码中实现空安全? - How to implement null-safety in simple flutter-dart code with object snapshot.data? 来自 Cloud Firestore 的 flutter Stream:如何将数据从快照复制到 class 并打印 - flutter Stream from Cloud Firestore : how to copy data from snapshot to class and print Flutter - 来自子集合的快照 - Flutter - Snapshot from Sub-collection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM