路由到另一页面时,我得到“子树中有多个共享相同标签的英雄”

时间:2020-10-11 15:41:31

标签: flutter dart

我正在尝试通过路线从一个屏幕导航到另一个屏幕。当我点击页面上的按钮以移动到提供的路线时,我得到了错误:

I/flutter ( 8790): Another exception was thrown: There are multiple heroes that share the same tag within a subtree.

与您共享源代码:

import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_counter/flutter_counter.dart';
import 'package:gender_selection/gender_selection.dart';
import 'package:group_chats/addContactUI.dart';
import 'package:group_chats/addPhone.dart';
import 'package:group_chats/letGoUI.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'Animation/FadeAnimation.dart';
import 'Model/insertUserModel.dart';

class AddProfileUI extends StatefulWidget {
  final List<String> listFriends;
  final String phone;
  AddProfileUI(this.listFriends, this.phone);
  @override
  _AddProfileUIState createState() => _AddProfileUIState();
}

class _AddProfileUIState extends State<AddProfileUI> {
  File _image;
  final picker = ImagePicker();
  final _formKey = GlobalKey<FormState>();
  String name = "";
  String city = "";
  TextEditingController dobController = TextEditingController();
  bool single = false;
  Gender gender;
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  int defaultValue = 18;
  List<String> selectedContact;
  SharedPreferences prefs;

  bool _loading = true;

  Future initPrefs() async {
    prefs = await SharedPreferences.getInstance();
  }

  uploadImage(String userId) async {
    try {
      FormData formData = new FormData.fromMap({
        "file":
            await MultipartFile.fromFile(_image.path, filename: "$userId.jpg"),
      });
      var response = await Dio().post(
          "https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/upload_profile/$userId",
          data: formData);
      if (response.statusCode == 200)
        return response.data;
      else
        return null;
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  Future<InsertUserModel> insertData() async {
    try {
      for (int i = 0; i < selectedContact.length; i++) {
        if (selectedContact[i][0] == "0") {
          selectedContact[i] = selectedContact[i].replaceRange(0, 1, "+972");
        }
      }
      var body = jsonEncode({
        "gender": gender.index == 0 ? "male" : "female",
        "city": city,
        "last_login": {},
        "friends": selectedContact ?? [],
        "single": single,
        "name": name,
        "phone_number": widget.phone,
        "age": defaultValue
      });
      final String apiUrl =
          "https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/${AddPhoneUI.uid}";
      final response = await http.post(apiUrl,
          headers: {"content-type": "application/json"}, body: body);
      if (response.statusCode == 200) {
        final responseString = response.body;

        return insertUserModelFromJson(responseString);
      }
    } catch (e) {
      setState(() {
        _loading = false;
      });
    }
  }

  getUserData() async {
    try {
      final String apiUrl =
          "https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/";
      final response = await http.get(apiUrl);
      if (response.statusCode == 200) {
        final responseString = response.body;
        return insertUserModelFromJson(responseString);
      }
    } catch (e) {
      setState(() {
        _loading = false;
      });
      Scaffold.of(context).showSnackBar(SnackBar(
        backgroundColor: Colors.red,
        content: Text('Error: ${e.toString()}'),
        duration: Duration(milliseconds: 2500),
      ));
    }
  }

  Future<void> _selectStartingDate(BuildContext context) async {
    DateTime selectedDate = DateTime.now();
    final DateTime picked = await showDatePicker(
      context: context,
      initialDate: selectedDate,
      firstDate: DateTime(1950),
      lastDate: DateTime(
          DateTime.now().year, DateTime.now().month, DateTime.now().day),
    );
    if (picked != null && picked != selectedDate)
      setState(() {
        selectedDate = picked;
        dobController.text = selectedDate.year.toString() +
            "-" +
            selectedDate.month.toString() +
            "-" +
            selectedDate.day.toString();
      });
  }

  Future getImage() async {
    final pickedFile = await picker.getImage(source: ImageSource.gallery);

    setState(() {
      _image = File(pickedFile.path);
    });
  }

  showPopUp(BuildContext context) {
    showDialog(
        context: context,
        builder: (context) => AlertDialog(
              shape:
                  OutlineInputBorder(borderRadius: BorderRadius.circular(14.0)),
              content: Container(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    SizedBox(
                      height: 20.0,
                    ),
                    Text(
                      "My Profile",
                      style: TextStyle(
                          fontSize: 27.0, fontWeight: FontWeight.w600),
                    ),
                    SizedBox(
                      height: 30.0,
                    ),
                    RichText(
                        text: TextSpan(
                      text: "Your friends will be able to\nsee ",
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 18.0,
                      ),
                      children: <TextSpan>[
                        TextSpan(
                            text: 'only',
                            style: TextStyle(
                                color: Colors.blue,
                                fontWeight: FontWeight.w500)),
                        TextSpan(text: 'your picture and\name.'),
                      ],
                    )),
                    SizedBox(
                      height: 10.0,
                    ),
                    RichText(
                        text: TextSpan(
                      text: "Other fields are used for\n",
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 18.0,
                      ),
                      children: <TextSpan>[
                        TextSpan(
                            text: 'research issues',
                            style: TextStyle(
                                color: Colors.blue,
                                fontWeight: FontWeight.w500)),
                        TextSpan(text: "only."),
                      ],
                    )),
                    SizedBox(
                      height: 10.0,
                    ),
                    RichText(
                        text: TextSpan(
                      text: "Please fill all the fields.",
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 18.0,
                      ),
                    )),
                    SizedBox(
                      height: 80.0,
                    ),
                    MaterialButton(
                      shape: OutlineInputBorder(
                          borderSide: BorderSide(width: 1.0)),
                      color: Colors.white38,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(
                            vertical: 10.0, horizontal: 20.0),
                        child: Text(
                          "Ok, got it",
                          style: TextStyle(fontSize: 18.0),
                        ),
                      ),
                      onPressed: () {
                        Navigator.pop(context);
                      },
                    ),
                  ],
                ),
              ),
            ));
  }

  @override
  void initState() {
    super.initState();
    selectedContact = widget.listFriends;
    initPrefs();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.only(right: 10.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    IconButton(
                      icon: Icon(Icons.arrow_back),
                      onPressed: () {},
                    ),
                    GestureDetector(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => AddContactUI(),
                            )).then((value) {
                          setState(() {
                            selectedContact = value;
                          });
                        });
                      },
                      child: Column(
                        children: [
                          Icon(
                            Icons.supervisor_account,
                            size: 40.0,
                          ),
                          Text("Add Friends"),
                        ],
                      ),
                    )
                  ],
                ),
              ),
              Container(
                child: GestureDetector(
                  onTap: () async {
                    await getImage();
                  },
                  child: CircleAvatar(
                    radius: 60.0,
                    backgroundImage: _image != null
                        ? Image.file(_image).image
                        : Image.asset("assets/empty.png").image,
                    backgroundColor: Colors.transparent,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: FadeAnimation(
                  1.7,
                  Form(
                    key: _formKey,
                    child: Container(
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.white,
                          boxShadow: [
                            BoxShadow(
                              color: Color(0xff5E17EB).withOpacity(0.3),
                              blurRadius: 20,
                              offset: Offset(0, 10),
                            )
                          ]),
                      child: Column(
                        children: <Widget>[
                          Container(
                            padding: EdgeInsets.all(10),
                            decoration: BoxDecoration(
                                border: Border(
                                    bottom:
                                        BorderSide(color: Colors.grey[200]))),
                            child: TextFormField(
                              textInputAction: TextInputAction.next,
                              onFieldSubmitted: (_) =>
                                  FocusScope.of(context).nextFocus(),
                              onChanged: (val) {
                                setState(() {
                                  name = val;
                                });
                              },
                              validator: (val) =>
                                  val.isEmpty ? "Enter Name" : null,
                              decoration: InputDecoration(
                                  border: InputBorder.none,
                                  hintText: "Name",
                                  hintStyle: TextStyle(color: Colors.grey)),
                            ),
                          ),
                          Container(
                            decoration: BoxDecoration(
                                border: Border(
                                    bottom:
                                        BorderSide(color: Colors.grey[200]))),
                            padding: EdgeInsets.all(10),
                            child: TextFormField(
                              textInputAction: TextInputAction.next,
                              keyboardType: TextInputType.text,
                              onChanged: (val) {
                                setState(() {
                                  city = val;
                                });
                              },
                              validator: (val) {
                                if (val.isEmpty) return "Enter City";
//                                      if (val.length < 6)
//                                        return "Password should be at least 6 characters";
                                return null;
                              },
                              decoration: InputDecoration(
                                  border: InputBorder.none,
                                  hintText: "City",
                                  hintStyle: TextStyle(color: Colors.grey)),
                            ),
                          ),
                          Container(
                            height: 140.0,
                            padding: EdgeInsets.all(10),
                            child: GenderSelection(
                              selectedGender: gender,
                              maleText: "", //default Male
                              femaleText: "", //default Female
                              linearGradient: LinearGradient(colors: [
                                Colors.indigo,
                                Colors.black
                              ]), //List: [Colors.indigo, Colors.black]
                              selectedGenderIconBackgroundColor:
                                  Colors.indigo, // default red
                              checkIconAlignment:
                                  Alignment.centerRight, // default bottomRight
                              selectedGenderCheckIcon:
                                  null, // default Icons.check
                              onChanged: (Gender gender) {
                                this.gender = gender;
                                print(this.gender);
                              },
                              equallyAligned: true,
                              animationDuration: Duration(milliseconds: 400),
                              isCircular: true, // default : true,
                              isSelectedGenderIconCircular: true,
                              opacityOfGradient: 0.6,
                              padding: const EdgeInsets.all(3),
                              size: 120, //default : 120
                            ),
                          ),
                          SizedBox(
                            height: 10.0,
                          ),
                          Row(
                            children: [
                              Checkbox(
                                value: single,
                                onChanged: (value) {
                                  setState(() {
                                    single = !single;
                                  });
                                },
                              ),
                              Text(
                                "Are you Single?",
                                style: TextStyle(fontSize: 16.0),
                              )
                            ],
                          ),
                          Padding(
                            padding: const EdgeInsets.all(14.0),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: [
                                Text(
                                  "Age:",
                                  style: TextStyle(fontSize: 18.0),
                                ),
                                Counter(
                                  initialValue: defaultValue,
                                  buttonSize: 35.0,
                                  textStyle: TextStyle(fontSize: 25.0),
                                  minValue: 0,
                                  color: Colors.black,
                                  maxValue: 80,
                                  step: 1,
                                  decimalPlaces: 0,
                                  onChanged: (value) {
                                    // get the latest value from here
                                    setState(() {
                                      defaultValue = value;
                                    });
                                  },
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              FadeAnimation(
                1.9,
                MaterialButton(
                  shape: OutlineInputBorder(borderSide: BorderSide(width: 1.0)),
                  color: Colors.black,
                  child: Padding(
                    padding: const EdgeInsets.symmetric(
                        vertical: 10.0, horizontal: 20.0),
                    child: Text(
                      "Next",
                      style: TextStyle(
                        fontSize: 18.0,
                        color: Colors.white,
                      ),
                    ),
                  ),
                  onPressed: () async {
                    if (_formKey.currentState.validate()) {
                      InsertUserModel result = await insertData();
                      // var imageResult = await uploadImage(result.id);
                      print(result.data[0].id);
                      if (_image != null) {
                        await uploadImage(result.data[0].id);
                      }
                      setState(() {
                        _loading = false;
                      });
                      if (result != null) {
                        await prefs.setString("userID", result.data[0].id);
                        final snackBar = SnackBar(
                          content: Text(
                            result.message,
                            style: TextStyle(color: Colors.white),
                          ),
                          backgroundColor: Colors.green,
                          duration: Duration(milliseconds: 2000),
                        );

                        _scaffoldKey.currentState.showSnackBar(snackBar);
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => LetGoUI(result.data[0].id),
                            ));
                      } else {
                        final snackBar = SnackBar(
                          content: Text(
                            "Here is some error, please try again later!",
                            style: TextStyle(color: Colors.white),
                          ),
                          backgroundColor: Colors.red,
                          duration: Duration(milliseconds: 2000),
                        );

                        _scaffoldKey.currentState.showSnackBar(snackBar);
                      }
                    }
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

我真的不明白问题出在哪里,因为我没有使用任何英雄,也没有双FloatingActionButton

我该如何解决? 谢谢

1 个答案:

答案 0 :(得分:0)

导航时显示小吃栏可能存在问题。您应该在导航之前通过调用以下方法来解决该问题。

void removeSnackBarCallsBeforeNavigation() {
    ScaffoldMessenger.of(context).removeCurrentSnackBar();
  }