Flutter劫富濟貧計劃(三)——flutter佈局實戰

地圖導航搜索頁面佈局

在這裏插入圖片描述
在這裏插入圖片描述

整個頁面共使用的插件有

  • amap_location_fluttify: 高德定位控件
  • amap_search_fluttify: 高德搜索控件
  • permission_handler: 權限請求
  • azlistview: 城市列表選擇
  • shared_preferences: 保持歷史記錄(本地存儲)
  • lpinyin: 漢字轉拼音
  • provide: 狀態管理
  • rxdart: 搜索插件用到

其中城市列表插件,狀態管理,我就不詳細介紹了,如果有需要的話,可以自己去Pub上面搜一下,下載個實例工程,就知道怎麼用了, 如果有什麼問題,請給我留言,我看到後會給立刻您回覆

引入的包

Plugins.dart 是我封裝的計算經緯度距離的方法,在下面我會給出代碼的

ScreenAdapter.dart 是我之前封裝的屏幕適配類,如果有需要可以看我另一篇文章跳轉地址

PublicStorage.dart 是我之前封裝的本地存儲類,如果有需要可以看我另一篇文章跳轉地址·

rxdart.dart不太重要,是一個函數Dart類,本來想要使用其中的循環呢,後來直接用for循環代替了,可以不用引入

search_model.dart 是我寫的一個model類,主要用來轉換數據用的,下面會給出代碼

頁面代碼

import 'package:flutter/material.dart';
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
import 'package:project/plugins/Plugins.dart';

import 'package:project/plugins/ScreenAdapter.dart';
import 'package:project/plugins/PublicStorage.dart';
import 'package:rxdart/rxdart.dart';

import 'package:project/pages/model/search_model.dart';

class SearchMap extends StatefulWidget {
  @override
  _SearchMapState createState() => _SearchMapState();
}

class _SearchMapState extends State<SearchMap> {
  var city, address, latlng;
  final _addressController = TextEditingController();
  List<LocationSearch> _poiTitleList = [];

  @override
  void initState() {
    super.initState();
    _getLocation();
  }
  // 獲取本地存儲的定位
  _getLocation() async {
    var a = await PublicStorage.getHistoryList('LocationCity');
    var b = await PublicStorage.getHistoryList('LocationAddress');
    // var c = await PublicStorage.getHistoryList('LocationLatLng');
    setState(() {
      city = a[0];
      address = b[0];
      // latlng = c[0];
    });
    print(city);
    print(address);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('選擇地址'),
      ),
      body: ListView(
        children: <Widget>[
          searchMap(),
          searchList()
        ],
      ),
    );
  }

  // 選擇地址頂部搜索
  Widget searchMap() {
    return Container(
      padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
      child: Row(
        children: <Widget>[
          InkWell(
            child: Padding(
              padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
              child: Row(
                children: <Widget>[
                  Text('${city}'),
                  Icon(Icons.arrow_drop_down)
                ],
              ),
            ),
            onTap: () async {
              Navigator.pushNamed(context, '/city_select').then((data) {
                setState(() {
                  city = data;
                });
              });
            },
          ),
          Expanded(
            flex: 1,
            child: Container(
              decoration: BoxDecoration(
                  color: Color.fromRGBO(200, 200, 200, 0.3),
                  border: Border.all(
                      width: 1, color: Color.fromRGBO(150, 150, 150, 0.3))),
              child: TextField(
                controller: _addressController,
                decoration: InputDecoration(border: InputBorder.none),
              ),
            ),
          ),
          InkWell(
            child: Padding(
              padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
              child: Text(
                '搜索',
                style: TextStyle(color: Color.fromRGBO(150, 150, 150, 0.9)),
              ),
            ),
            onTap: () async {
              _poiTitleList = [];
              final poiList = await AmapSearch.searchKeyword(
                _addressController.text,
                city: city,
              );
              for (int i = 0; i < poiList.length; i++) {
                LocationSearch bean = LocationSearch();
                bean.title = await poiList[i].title;
                bean.address = await poiList[i].address;
                bean.latLng = await poiList[i].latLng;
                bean.distance = await Plugins.getdistance(context, bean.latLng);
                setState(() {
                  _poiTitleList.add(bean);
                });
              }
            },
          )
        ],
      ),
    );
  }

  // 周邊地理建築列表
  Widget searchList() {
    return Container(
      padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
      color: Color.fromRGBO(200, 200, 200, 0.3),
      child: Container(
          decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(ScreenAdapter.setWidth(10))),
          child: Column(
              children: _poiTitleList.map((val) {
            return Column(
              children: <Widget>[
                ListTile(
                  title: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text(val.title),
                      Text(
                        val.distance != null ? val.distance : 0,
                        // '18千米',
                        style: TextStyle(
                            fontSize: ScreenAdapter.size(25),
                            color: Color.fromRGBO(150, 150, 150, 0.9),
                            fontWeight: FontWeight.w400),
                      )
                    ],
                  ),
                  subtitle: Text(val.address),
                ),
                Divider(
                  height: ScreenAdapter.setHeight(0.5),
                )
              ],
            );
          }).toList())),
    );
  }
}

Plugins.dart

// 公用 的方法
import 'dart:convert';

import 'package:permission_handler/permission_handler.dart'; // 權限申請
import 'package:fluttertoast/fluttertoast.dart';
import 'package:amap_map_fluttify/amap_map_fluttify.dart';    // 獲取距離

import 'package:provide/provide.dart';
import 'package:project/provide/userinformation.dart';        // 用戶地理信息

import 'package:project/plugins/PublicStorage.dart';

class Plugins {
  ///大陸手機號碼11位數,匹配格式:前三位固定格式+後8位任意數
  /// 此方法中前三位格式有:
  /// 13+任意數 * 15+除4的任意數 * 18+除1和4的任意數 * 17+除9的任意數 * 147
  static bool isChinaPhoneLegal(String str) {
    return new RegExp(
            '^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$')
        .hasMatch(str);
  }

  static getdistance(context, str) async {

    var mylatlng = await PublicStorage.getHistoryList('LocationLatLng');
    var city = await PublicStorage.getHistoryList('LocationCity');
    List searchList = [];

    searchList = str.toString().substring(7, str.toString().lastIndexOf('}')).split(',');
    

    final result = await AmapService.calculateDistance(
      LatLng(
        double.parse(mylatlng[0][0].toString().substring(5)),
        double.parse(mylatlng[0][1].toString().substring(5)),
      ),
      LatLng(
        double.parse(searchList[0].toString().substring(5)),
        double.parse(searchList[1].toString().substring(5)),
      ),
    );

    return result.round().toString()+'米';
  }
}

userinformation.dart

import 'package:flutter/material.dart';
import 'package:project/plugins/PublicStorage.dart';

class UserInfomation with ChangeNotifier{
  var city = '';
  var address = '';
  var select_city = '';         // 用戶經過城市選擇之後選擇到的城市
  var latlng = null;             // 經緯度

  setCity(val) async{
    print(val);
    this.city = val;
    notifyListeners();
  }

  setAddress(val) async {
    this.address = val;
    notifyListeners();
  }
  setLatLng(val) async {
    this.latlng = val;
    notifyListeners();
  }

  setSelectCity(val) async {
    this.select_city = val;
    notifyListeners();
  }
}

search_model.dart



import 'package:amap_search_fluttify/amap_search_fluttify.dart';

class LocationSearch {
  String title;
  String address;
  LatLng latLng;
  String distance;

  LocationSearch({this.title, this.address, this.distance, this.latLng});

  LocationSearch.fromJson(Map json){
    this.title = json['title'];
    this.address = json['price'];
    this.distance = json['distance'];
    this.latLng = json['latLng'];
  }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章