【问题标题】:flutter return multiple fields from custom widget颤动从自定义小部件返回多个字段
【发布时间】:2019-01-12 09:33:09
【问题描述】:

我得到了下面的geolocation.dart 文件,它可以完美地作为独立的小部件工作:

import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:flutter/services.dart';
import 'package:simple_permissions/simple_permissions.dart';

class LocationField extends StatefulWidget {
  const LocationField({
    this.fieldKey,
    this.onSaved,
  });

  final Key fieldKey;
  final FormFieldSetter<String> onSaved;

  @override
  _LocationFieldState createState() => _LocationFieldState();
}

class _LocationFieldState extends State<LocationField> {
  Location _location = new Location();

  final lat = TextEditingController();
  final lon = TextEditingController();


  // @override
  // void initState() {
  //   super.initState();
  //  lat.addListener(_addLatValue);
  //  lon.addListener(_addLonValue);
  //}

  @override
  Widget build(BuildContext context) {
    return Row(
      textDirection: TextDirection.rtl,
      children: <Widget>[
        FlatButton(
          child: const Icon(Icons.my_location),
          onPressed: () => _getLocation(),
        ),
        Expanded(child: Column(
            textDirection: TextDirection.ltr,
            children: <Widget>[
                TextFormField(
                  controller: lat,
                  decoration: InputDecoration(
                      prefixIcon: Text("Latittude:     ")
                  ),
                ),
                TextFormField(
                    controller: lon,
                    decoration: InputDecoration(
                        prefixIcon: Text("Longitude:   ")
                    ),
                )
            ])

        )
      ],
    );

  }

  _getLocation() async {
    Map<String, double> location;
    var error = null;

    try {
      await SimplePermissions.requestPermission(Permission.AccessFineLocation);
      location = await _location.getLocation();
    } on PlatformException catch (e) {
      if (e.code == 'PERMISSION_DENIED') {
        error = 'Permission denied';
      } else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
        error =
        'Permission denied - please ask the user to enable it from the app settings';
      }
      location = null;
    }
    print("error $error");

    setState(() {
          lat.text = ('${location["latitude"]}');
          lon.text = ('${location["longitude"]}');
    });
  }
}

并显示如下,点击位置图标时出现位置坐标,如下:

我也可以将它作为一个小部件插入到我的主应用程序中,如下所示:

class _SignUpPageState extends State<SignUpPage> {
     @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      body: Form(
          key: _formKey,
          child: Column(
            children: <Widget>[
              LocationField(),
              RaisedButton(
                onPressed: signUp,
                child: Text('Sign up'),
              ),
            ],
          )
      ),
    );
  }

  void signUp() {
  // what to write here to get the geolocation points lat/lon printed?
}

我的问题是:如何在单击 signup 按钮时打印地理定位点纬度/经度,如何从子小部件中获取 2 个字段的值?

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    在 Flutter 中,使用 InheritedWidget & co. 将状态向下传递到小部件树非常容易,而向上传递数据实际上需要一些思考。

    类似于您使用的TextEditingControllers,您可以创建一个保存位置数据的LocationController

    class LocationController {
      Location _location = Location();
      get location => _location;
      set location(Location val) {
        _location = val;
        if (onChanged != null) _onChanged(val);
      }
    
      VoidCallback _onChanged;
    }
    

    然后可以像这样将该控制器传递给LocationField

    class LocationField extends StatefulWidget {
      LocationField({
        this.fieldKey,
        @required this.controller,
        this.onSaved,
      });
    
      final Key fieldKey;
      final LocationController controller;
      final FormFieldSetter<String> onSaved;
    
      @override
      _LocationFieldState createState() => _LocationFieldState();
    }
    
    class _LocationFieldState extends State<LocationField> {
      final lat = TextEditingController();
      final lon = TextEditingController();
    
      @override
      void initState() {
        super.initState();
        widget.controller._onChanged = (location) => setState(() {
          lat.text = ('${location["latitude"]}');
          lon.text = ('${location["longitude"]}');
        });
        lat.addListener(_addLatValue);
        lon.addListener(_addLonValue);
      }
    
      @override
      Widget build(BuildContext context) { ... }
    
      _getLocation() async {
        String error;
    
        try {
          await SimplePermissions.requestPermission(Permission.AccessFineLocation);
          widget.controller.location = await _location.getLocation();
        } on PlatformException catch (e) {
          if (e.code == 'PERMISSION_DENIED') {
            error = 'Permission denied';
          } else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
            error =
            'Permission denied - please ask the user to enable it from the app settings';
          }
          location = null;
        }
        print("error $error");
      }
    }
    

    然后,在树上的小部件中,您可以访问控制器以检索位置:

    class _SignUpPageState extends State<SignUpPage> {
      LocationController controller = LocationController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Form(
            key: _formKey,
            child: Column(
              children: <Widget>[
                LocationField(controller: controller),
                RaisedButton(onPressed: signUp, child: Text('Sign up')),
              ],
            )
          ),
        );
      }
    
      void signUp() {
        final location = controller.location;
      }
    }
    

    另一个好处是,您可以在树中的小部件中设置controllerlocationLocationField 将自动重建以反映该更改。

    【讨论】:

      猜你喜欢
      • 2020-04-13
      • 2011-03-01
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 2014-06-24
      • 2021-08-19
      • 2018-09-13
      相关资源
      最近更新 更多