select_address_page.dart 6.07 KB
import 'dart:async';
import 'dart:convert';
import 'package:Parlando/models/nearby_response.dart' as nearby;
import 'package:Parlando/routers/fluro_navigator.dart';
import 'package:Parlando/util/toast_utils.dart';
import 'package:flutter/material.dart';
import 'package:Parlando/widgets/my_button.dart';
import 'package:Parlando/widgets/search_bar.dart';
import 'package:getwidget/getwidget.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:http/http.dart' as http;
import 'package:location/location.dart';

class AddressSelectPage extends StatefulWidget {
  const AddressSelectPage({Key? key}) : super(key: key);

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

class AddressSelectPageState extends State<AddressSelectPage> {
  List<nearby.Results> _list = [];
  int _index = 0;
  final ScrollController _controller = ScrollController();
  LatLng _center = const LatLng(45.521563, -122.677433);
  late GoogleMapController mapController;
  bool isLoading = false;
  int _markerIdCounter = 1;
  Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
  late StreamSubscription _locationSubscription;
  String radius = "1000";
  String apiKey = "AIzaSyDQZsMULyO-UtiSht4_MFi1uHT4BIqasjw";
  nearby.NearbyPlacesResponse nearbyPlacesResponse =
      nearby.NearbyPlacesResponse();

  @override
  void dispose() {
    _controller.dispose();
    _locationSubscription.cancel();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _getCurrentLocation();
  }

  Future<void> _getCurrentLocation() async {
    Location location = Location();
    bool serviceEnabled;
    PermissionStatus permissionGranted;
    serviceEnabled = await location.serviceEnabled();
    if (!serviceEnabled) {
      serviceEnabled = await location.requestService();
      if (!serviceEnabled) {
        return;
      }
    }
    permissionGranted = await location.hasPermission();
    if (permissionGranted == PermissionStatus.denied) {
      permissionGranted = await location.requestPermission();
      if (permissionGranted != PermissionStatus.granted) {
        return;
      }
    }

    _locationSubscription =
        location.onLocationChanged.listen((LocationData currentLocation) {
      _center = LatLng(currentLocation.latitude!, currentLocation.longitude!);
    });
  }

  void getNearbyPlaces(String keyword) async {
    String uri =
        '${'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${_center.latitude},${_center.longitude}&radius=$radius'}&key=$apiKey&keyword=$keyword';
    var url = Uri.parse(uri);
    var response = await http.post(url);
    nearbyPlacesResponse =
        nearby.NearbyPlacesResponse.fromJson(jsonDecode(response.body));
    _list = nearbyPlacesResponse.results!;
    setState(() {
      isLoading = false;
    });
  }

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
    final String markerIdVal = 'marker_id_$_markerIdCounter';
    _markerIdCounter++;
    final MarkerId markerId = MarkerId(markerIdVal);
    final Marker marker = Marker(
      markerId: markerId,
      position: _center,
    );
    mapController.moveCamera(CameraUpdate.newLatLng(_center));
    setState(() {
      markers[markerId] = marker;
    });
    getNearbyPlaces("");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: SearchBar(
        hintText: '搜索地址',
        onPressed: (text) async {
          isLoading = true;
          _controller.animateTo(0.0,
              duration: const Duration(milliseconds: 10), curve: Curves.ease);
          _index = 0;
          // 构造检索参数
          getNearbyPlaces(text);
        },
      ),
      body: SafeArea(
        child: Column(
          children: <Widget>[
            Expanded(
              flex: 9,
              child: GoogleMap(
                onMapCreated: _onMapCreated,
                initialCameraPosition: CameraPosition(
                  target: _center,
                  zoom: 16.0,
                ),
                markers: Set<Marker>.of(markers.values),
              ),
            ),
            Expanded(
              flex: 11,
              child: isLoading
                  ? const GFLoader()
                  : ListView.separated(
                controller: _controller,
                      itemCount: _list.length,
                      separatorBuilder: (_, index) => const Divider(),
                      itemBuilder: (_, index) {
                        return _AddressItem(
                          isSelected: _index == index,
                          date: _list[index],
                          onTap: () {
                            _index = index;
                            setState(() {});
                          },
                        );
                      },
                    ),
            ),
            MyButton(
              onPressed: () {
                if (_list.isEmpty) {
                  Toast.show('未选择地址!');
                  return;
                }
                NavigatorUtils.goBackWithParams(context, _list[_index]);
              },
              text: '确认选择地址',
            )
          ],
        ),
      ),
    );
  }
}

class _AddressItem extends StatelessWidget {
  const _AddressItem({
    Key? key,
    required this.date,
    this.isSelected = false,
    this.onTap,
  }) : super(key: key);
  final nearby.Results date;
  final bool isSelected;
  final GestureTapCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        alignment: Alignment.centerLeft,
        padding: const EdgeInsets.symmetric(horizontal: 16.0),
        height: 50.0,
        child: Row(
          children: <Widget>[
            Expanded(
              child: Text(
                '${date.name} ${date.vicinity}',
              ),
            ),
            Visibility(
              visible: isSelected,
              child: const Icon(Icons.done, color: Colors.blue),
            )
          ],
        ),
      ),
    );
  }
}