select_address_page.dart 7.09 KB
import 'dart:async';
import 'dart:convert';
import 'package:Parlando/extension/widget_ext.dart';
import 'package:Parlando/models/nearby_response.dart' as nearby;
import 'package:Parlando/routers/fluro_navigator.dart';
import 'package:Parlando/util/log_utils.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> _nearByList = [];
  final ScrollController _controller = ScrollController();
  LatLng? _center;
  late GoogleMapController mapController;
  bool isLoading = true;
  Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
  late StreamSubscription _locationSubscription;
  String radiusMax = "1000";
  String apiKey = "AIzaSyDQZsMULyO-UtiSht4_MFi1uHT4BIqasjw";
  nearby.NearbyPlacesResponse nearbyPlacesResponse = nearby.NearbyPlacesResponse();


  @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;
      }
    }
    var currentLocation = await location.getLocation();
    _center = LatLng(currentLocation.latitude!, currentLocation.longitude!);
    getNearbyPlaces("");
    _goToCurrentCenter();
  }

  void getNearbyPlaces(String keyword) async {
    String host = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json';
    String location = 'location=${_center?.latitude},${_center?.longitude}';
    String radius = 'radius=$radiusMax';
    String types = 'type=point_of_interest';
    String uri = '${'$host?$location&$radius'}&key=$apiKey&keyword=$keyword&$types';
    print(uri);
    var url = Uri.parse(uri);
    var response = await http.post(url);
    nearbyPlacesResponse = nearby.NearbyPlacesResponse.fromJson(jsonDecode(response.body));
    _nearByList = nearbyPlacesResponse.results!;
    if (_nearByList.isNotEmpty) {
      selectItemLocation(_nearByList[0]);
    }
    setState(() {
      isLoading = false;
    });
    buildMarkers();
  }

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
    getNearbyPlaces("");
  }

  void _goToCurrentCenter() {
    if (_center != null) {
      mapController.moveCamera(CameraUpdate.newLatLng(_center!));
    }
  }

  @override
  Widget build(BuildContext context) {
    var loaderView = const GFLoader().expanded(flex: 11);
    Widget realList = ListView.separated(
      controller: _controller,
      itemCount: _nearByList.length,
      separatorBuilder: (_, index) => const Divider(),
      itemBuilder: (_, index) {
        var item = _nearByList[index];
        return _AddressItem(
          isSelected: item.isSelect,
          data: item,
          onTap: () {
            selectItemLocation(item);
          },
        );
      },
    ).expanded(flex: 11);
    if (_nearByList.isEmpty) {
      realList = const Center(child: Text("没有找到任何地点")).expanded(flex: 11);
    }
    var listHolder = isLoading ? loaderView : realList;

    var searchBar = SearchBar(
      hintText: '搜索地址',
      onPressed: (text) async {
        isLoading = true;
        _controller.animateTo(0.0, duration: const Duration(milliseconds: 10), curve: Curves.ease);
        // 构造检索参数
        getNearbyPlaces(text);
        setState(() {

        });
      },
    );
    var map = GoogleMap(
      onMapCreated: _onMapCreated,
      initialCameraPosition: CameraPosition(target: _center ?? const LatLng(45.521563, -122.677433), zoom: 16.0),
      markers: Set<Marker>.of(markers.values),
      myLocationEnabled: true,
      myLocationButtonEnabled: true,
    ).expanded(flex: 9);

    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: searchBar,
      body: Column(
        children: <Widget>[map, listHolder, initButton()],
      ).safe(),
    );
  }

  initButton() {
    return MyButton(
      onPressed: () {
        var selected = _nearByList.where((element) => element.isSelect);
        if (selected.isEmpty) {
          Toast.show('未选择地址!');
          return;
        }

        NavigatorUtils.goBackWithParams(context, selected.first);
      },
      text: '确认选择地址',
    );
  }

  void buildMarkers() {
    markers.clear();
    for (var value in _nearByList) {
      final MarkerId markerId = MarkerId(buildMarkerId(value));
      final Marker marker = Marker(
        icon: value.isSelect ? BitmapDescriptor.defaultMarker : BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
        markerId: markerId,
        position: buildMarkerLocation(value),
      );
      markers[markerId] = marker;
    }
    setState(() {});
  }

  String buildMarkerId(nearby.Results value) {
    var lat = value.geometry?.location?.lat;
    var lng = value.geometry?.location?.lng;
    return "$lat-$lng";
  }

  LatLng buildMarkerLocation(nearby.Results value) {
    var lat = value.geometry?.location?.lat;
    var lng = value.geometry?.location?.lng;
    return LatLng(lat ?? 0, lng ?? 0);
  }

  void selectItemLocation(nearby.Results item) {
    for (var element in _nearByList) {
      element.isSelect = false;
    }
    item.isSelect = true;
    var lat = item.geometry?.location?.lat;
    var lng = item.geometry?.location?.lng;
    if (lat != null && lng != null) {
      _center = LatLng(lat, lng);
    }
    _goToCurrentCenter();
    setState(() {});
    buildMarkers();
  }

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

class _AddressItem extends StatelessWidget {
  const _AddressItem({
    Key? key,
    required this.data,
    this.isSelected = false,
    this.onTap,
  }) : super(key: key);

  final nearby.Results data;
  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>[
            Text('${data.name}').expanded(),
            Visibility(visible: isSelected, child: const Icon(Icons.done, color: Colors.blue))
          ],
        ),
      ),
    );
  }
}