amap_search_fluttify
This commit is contained in:
145
example/lib/get_map_data/get_address_desc.screen.dart
Normal file
145
example/lib/get_map_data/get_address_desc.screen.dart
Normal file
@ -0,0 +1,145 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:amap_search_fluttify_example/widgets/function_item.widget.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GetAddressDescScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('获取地址描述数据')),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
const FunctionItem(
|
||||
label: '地理编码(地址转坐标)',
|
||||
sublabel: 'AddressEncodeScreen',
|
||||
target: AddressEncodeScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '逆地理编码(坐标转地址)',
|
||||
sublabel: 'AddressDecodeScreen',
|
||||
target: AddressDecodeScreen(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 地理编码(地址转坐标)
|
||||
class AddressEncodeScreen extends StatefulWidget {
|
||||
const AddressEncodeScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AddressEncodeScreenState createState() => _AddressEncodeScreenState();
|
||||
}
|
||||
|
||||
class _AddressEncodeScreenState extends State<AddressEncodeScreen> {
|
||||
final _keywordController = TextEditingController(text: '阿里巴巴');
|
||||
final _cityController = TextEditingController(text: '杭州');
|
||||
|
||||
List<Geocode> _geocodeList = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('地理编码(地址转坐标)')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入关键字'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _cityController,
|
||||
decoration: const InputDecoration(hintText: '输入城市'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final geocodeList = await AmapSearch.instance.searchGeocode(
|
||||
_keywordController.text,
|
||||
city: _cityController.text,
|
||||
);
|
||||
setState(() {
|
||||
_geocodeList = geocodeList;
|
||||
});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
if (_geocodeList.isNotEmpty) Text(_geocodeList.toString()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 逆地理编码(坐标转地址)
|
||||
class AddressDecodeScreen extends StatefulWidget {
|
||||
@override
|
||||
_AddressDecodeScreenState createState() => _AddressDecodeScreenState();
|
||||
}
|
||||
|
||||
class _AddressDecodeScreenState extends State<AddressDecodeScreen> {
|
||||
final _latController = TextEditingController(text: '39.9824');
|
||||
final _lngController = TextEditingController(text: '116.3053');
|
||||
final _radiusController = TextEditingController(text: '200.0');
|
||||
|
||||
ReGeocode? _reGeocode;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('逆地理编码(坐标转地址)')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
DecoratedRow(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _latController,
|
||||
decoration: const InputDecoration(hintText: '输入纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _lngController,
|
||||
decoration: const InputDecoration(hintText: '输入经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextFormField(
|
||||
controller: _radiusController,
|
||||
decoration: const InputDecoration(hintText: '输入范围半径'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final reGeocodeList = await AmapSearch.instance.searchReGeocode(
|
||||
LatLng(
|
||||
double.parse(_latController.text),
|
||||
double.parse(_lngController.text),
|
||||
),
|
||||
radius: 200.0,
|
||||
);
|
||||
setState(() {
|
||||
_reGeocode = reGeocodeList;
|
||||
});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(_reGeocode?.toString() ?? ''),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
50
example/lib/get_map_data/get_bus_info.screen.dart
Normal file
50
example/lib/get_map_data/get_bus_info.screen.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:amap_search_fluttify_example/widgets/scrollable_text.widget.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 获取公交数据
|
||||
class GetBusInfoScreen extends StatefulWidget {
|
||||
@override
|
||||
_GetBusInfoScreenState createState() => _GetBusInfoScreenState();
|
||||
}
|
||||
|
||||
class _GetBusInfoScreenState extends State<GetBusInfoScreen> {
|
||||
final _keywordController = TextEditingController(text: '武林广场');
|
||||
final _cityController = TextEditingController(text: '杭州');
|
||||
|
||||
String _busStation = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('获取公交数据')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入公交站点名称'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _cityController,
|
||||
decoration: const InputDecoration(hintText: '输入城市'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final busStation = await AmapSearch.instance.searchBusStation(
|
||||
stationName: _keywordController.text,
|
||||
city: _cityController.text,
|
||||
);
|
||||
_busStation = await busStation.toFutureString();
|
||||
setState(() {});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(child: ScrollableText(_busStation)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
45
example/lib/get_map_data/get_district_info.screen.dart
Normal file
45
example/lib/get_map_data/get_district_info.screen.dart
Normal file
@ -0,0 +1,45 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 获取行政区划数据
|
||||
class GetDistrictInfoScreen extends StatefulWidget {
|
||||
@override
|
||||
_GetDistrictInfoScreenState createState() => _GetDistrictInfoScreenState();
|
||||
}
|
||||
|
||||
class _GetDistrictInfoScreenState extends State<GetDistrictInfoScreen> {
|
||||
final _keywordController = TextEditingController(text: '西湖区');
|
||||
|
||||
String _district = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('获取行政区划数据')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入地区'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final district = await AmapSearch.instance.searchDistrict(
|
||||
_keywordController.text,
|
||||
showBoundary: true,
|
||||
showChild: true,
|
||||
);
|
||||
_district = district.toString();
|
||||
setState(() {});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(child: SingleChildScrollView(child: Text(_district))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
234
example/lib/get_map_data/get_poi.screen.dart
Normal file
234
example/lib/get_map_data/get_poi.screen.dart
Normal file
@ -0,0 +1,234 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:amap_search_fluttify_example/widgets/function_item.widget.dart';
|
||||
import 'package:amap_search_fluttify_example/widgets/scrollable_text.widget.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GetPoiScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('获取POI数据')),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
FunctionItem(
|
||||
label: '关键字检索POI',
|
||||
sublabel: 'KeywordPoiScreen',
|
||||
target: KeywordPoiScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '周边检索POI',
|
||||
sublabel: 'AroundPoiScreen',
|
||||
target: AroundPoiScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '输入提示',
|
||||
sublabel: 'InputTipScreen',
|
||||
target: InputTipScreen(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 关键字检索POI
|
||||
class KeywordPoiScreen extends StatefulWidget {
|
||||
@override
|
||||
_KeywordPoiScreenState createState() => _KeywordPoiScreenState();
|
||||
}
|
||||
|
||||
class _KeywordPoiScreenState extends State<KeywordPoiScreen> {
|
||||
final _keywordController = TextEditingController(text: '肯德基');
|
||||
final _cityController = TextEditingController(text: '杭州');
|
||||
int _page = 1;
|
||||
|
||||
List<String> _poiTitleList = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('关键字检索POI')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入关键字'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _cityController,
|
||||
decoration: const InputDecoration(hintText: '输入城市'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final poiList = await AmapSearch.instance.searchKeyword(
|
||||
_keywordController.text,
|
||||
city: _cityController.text,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_poiTitleList = poiList.map((it) => it.toString()).toList();
|
||||
});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final poiList = await AmapSearch.instance.searchKeyword(
|
||||
_keywordController.text,
|
||||
city: _cityController.text,
|
||||
page: ++_page,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_poiTitleList = poiList.map((it) => it.toString()).toList();
|
||||
});
|
||||
},
|
||||
child: const Text('下一页'),
|
||||
),
|
||||
Expanded(child: ScrollableText(_poiTitleList.join("\n"))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 附近检索POI
|
||||
class AroundPoiScreen extends StatefulWidget {
|
||||
@override
|
||||
_AroundPoiScreenState createState() => _AroundPoiScreenState();
|
||||
}
|
||||
|
||||
class _AroundPoiScreenState extends State<AroundPoiScreen> {
|
||||
final _keywordController = TextEditingController();
|
||||
final _typeController = TextEditingController();
|
||||
final _latController = TextEditingController(text: '29.08');
|
||||
final _lngController = TextEditingController(text: '119.65');
|
||||
int _page = 1;
|
||||
|
||||
List<String> _poiTitleList = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('周边检索POI')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入关键字'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _typeController,
|
||||
decoration: const InputDecoration(hintText: '输入类别'),
|
||||
),
|
||||
DecoratedRow(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: TextField(
|
||||
controller: _latController,
|
||||
decoration: const InputDecoration(hintText: '输入纬度'),
|
||||
),
|
||||
),
|
||||
SPACE_4_HORIZONTAL,
|
||||
Flexible(
|
||||
child: TextField(
|
||||
controller: _lngController,
|
||||
decoration: const InputDecoration(hintText: '输入经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final poiList = await AmapSearch.instance.searchAround(
|
||||
LatLng(
|
||||
double.tryParse(_latController.text) ?? 29.08,
|
||||
double.tryParse(_lngController.text) ?? 119.65,
|
||||
),
|
||||
keyword: _keywordController.text,
|
||||
type: _typeController.text,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_poiTitleList = poiList.map((it) => it.toString()).toList();
|
||||
});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final poiList = await AmapSearch.instance.searchAround(
|
||||
LatLng(
|
||||
double.tryParse(_latController.text) ?? 29.08,
|
||||
double.tryParse(_lngController.text) ?? 119.65,
|
||||
),
|
||||
keyword: _keywordController.text,
|
||||
type: _typeController.text,
|
||||
page: ++_page,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_poiTitleList = poiList.map((it) => it.toString()).toList();
|
||||
});
|
||||
},
|
||||
child: const Text('下一页'),
|
||||
),
|
||||
Expanded(child: ScrollableText(_poiTitleList.join("\n"))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 输入提示
|
||||
class InputTipScreen extends StatefulWidget {
|
||||
@override
|
||||
_InputTipScreenState createState() => _InputTipScreenState();
|
||||
}
|
||||
|
||||
class _InputTipScreenState extends State<InputTipScreen> {
|
||||
final _keywordController = TextEditingController(text: '肯德基');
|
||||
final _cityController = TextEditingController(text: '杭州');
|
||||
|
||||
List<InputTip> _inputTipList = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('输入内容自动提示')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入关键字'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _cityController,
|
||||
decoration: const InputDecoration(hintText: '输入所在城市'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final inputTipList = await AmapSearch.instance.fetchInputTips(
|
||||
_keywordController.text,
|
||||
city: _cityController.text,
|
||||
);
|
||||
|
||||
setState(() => _inputTipList = inputTipList);
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(child: ScrollableText(_inputTipList.join("\n"))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
42
example/lib/get_map_data/get_weather_info.screen.dart
Normal file
42
example/lib/get_map_data/get_weather_info.screen.dart
Normal file
@ -0,0 +1,42 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 获取天气数据
|
||||
class GetWeatherInfoScreen extends StatefulWidget {
|
||||
@override
|
||||
_GetWeatherInfoScreenState createState() => _GetWeatherInfoScreenState();
|
||||
}
|
||||
|
||||
class _GetWeatherInfoScreenState extends State<GetWeatherInfoScreen> {
|
||||
final _keywordController = TextEditingController(text: '杭州');
|
||||
|
||||
String _district = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('获取天气数据')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _keywordController,
|
||||
decoration: const InputDecoration(hintText: '输入地区'),
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final district = await AmapSearch.instance
|
||||
.searchDistrict(_keywordController.text);
|
||||
_district = district.toString();
|
||||
setState(() {});
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(child: SingleChildScrollView(child: Text(_district))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
129
example/lib/main.dart
Normal file
129
example/lib/main.dart
Normal file
@ -0,0 +1,129 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'get_map_data/get_address_desc.screen.dart';
|
||||
import 'get_map_data/get_bus_info.screen.dart';
|
||||
import 'get_map_data/get_district_info.screen.dart';
|
||||
import 'get_map_data/get_poi.screen.dart';
|
||||
import 'get_map_data/get_weather_info.screen.dart';
|
||||
import 'route_plan/route_bus.screen.dart';
|
||||
import 'route_plan/route_drive.screen.dart';
|
||||
import 'route_plan/route_ride.screen.dart';
|
||||
import 'route_plan/route_walk.screen.dart';
|
||||
import 'widgets/function_group.widget.dart';
|
||||
import 'widgets/function_item.widget.dart';
|
||||
import 'widgets/todo.screen.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
await AmapSearch.instance.init('f583e0d5b70400167993615c3adc3ced');
|
||||
await AmapSearch.instance.updatePrivacyShow(true);
|
||||
await AmapSearch.instance.updatePrivacyAgree(true);
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const MaterialApp(home: Home());
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
const Home({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('AMaps examples')),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
FunctionGroup(
|
||||
headLabel: '获取地图数据',
|
||||
children: <Widget>[
|
||||
FunctionItem(
|
||||
label: '获取POI数据',
|
||||
sublabel: 'GetPoiScreen',
|
||||
target: GetPoiScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '获取地址描述数据',
|
||||
sublabel: 'GetAddressDescScreen',
|
||||
target: GetAddressDescScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '获取行政区划数据',
|
||||
sublabel: 'GetDistrictInfoScreen',
|
||||
target: GetDistrictInfoScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '获取公交数据',
|
||||
sublabel: 'GetBusInfoScreenScreen',
|
||||
target: GetBusInfoScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '后获取天气数据',
|
||||
sublabel: 'GetWeatherInfoScreen',
|
||||
target: GetWeatherInfoScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '获取业务数据(云图功能)',
|
||||
sublabel: 'TODO',
|
||||
target: TodoScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '获取交通态势信息',
|
||||
sublabel: 'TODO',
|
||||
target: TodoScreen(),
|
||||
),
|
||||
],
|
||||
),
|
||||
FunctionGroup(
|
||||
headLabel: '出行路线规划',
|
||||
children: <Widget>[
|
||||
FunctionItem(
|
||||
label: '驾车出行路线规划',
|
||||
sublabel: 'RouteDriveScreen',
|
||||
target: RouteDriveScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '步行出行路线规划',
|
||||
sublabel: 'RouteWalkScreen',
|
||||
target: RouteWalkScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '公交出行路线规划',
|
||||
sublabel: 'RouteBusScreen',
|
||||
target: RouteBusScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '骑行出行路线规划',
|
||||
sublabel: 'RouteRideScreen',
|
||||
target: RouteRideScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '货车出行路线规划',
|
||||
sublabel: 'TODO',
|
||||
target: TodoScreen(),
|
||||
),
|
||||
FunctionItem(
|
||||
label: '未来出行路线规划',
|
||||
sublabel: 'TODO',
|
||||
target: TodoScreen(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
97
example/lib/route_plan/route_bus.screen.dart
Normal file
97
example/lib/route_plan/route_bus.screen.dart
Normal file
@ -0,0 +1,97 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 公交路线规划
|
||||
class RouteBusScreen extends StatefulWidget {
|
||||
@override
|
||||
_RouteBusScreenState createState() => _RouteBusScreenState();
|
||||
}
|
||||
|
||||
class _RouteBusScreenState extends State<RouteBusScreen> {
|
||||
final _fromLatController = TextEditingController(text: '30.219933');
|
||||
final _fromLngController = TextEditingController(text: '120.023728');
|
||||
|
||||
final _toLatController = TextEditingController(text: '30.27065');
|
||||
final _toLngController = TextEditingController(text: '120.163117');
|
||||
|
||||
String _routeResult = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('公交路线规划')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('起点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('终点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final routeResult = await AmapSearch.instance.searchBusRoute(
|
||||
from: LatLng(
|
||||
double.parse(_fromLatController.text),
|
||||
double.parse(_fromLngController.text),
|
||||
),
|
||||
to: LatLng(
|
||||
double.parse(_toLatController.text),
|
||||
double.parse(_toLngController.text),
|
||||
),
|
||||
city: '杭州',
|
||||
);
|
||||
routeResult
|
||||
.toFutureString()
|
||||
.then((it) => setState(() => _routeResult = it));
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(_routeResult),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
100
example/lib/route_plan/route_drive.screen.dart
Normal file
100
example/lib/route_plan/route_drive.screen.dart
Normal file
@ -0,0 +1,100 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 驾车路线规划
|
||||
class RouteDriveScreen extends StatefulWidget {
|
||||
@override
|
||||
_RouteDriveScreenState createState() => _RouteDriveScreenState();
|
||||
}
|
||||
|
||||
class _RouteDriveScreenState extends State<RouteDriveScreen> {
|
||||
final _fromLatController = TextEditingController(text: '30.219933');
|
||||
final _fromLngController = TextEditingController(text: '120.023728');
|
||||
|
||||
final _toLatController = TextEditingController(text: '30.27065');
|
||||
final _toLngController = TextEditingController(text: '120.163117');
|
||||
|
||||
String _routeResult = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('驾车路线规划')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('起点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('终点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
final routeResult = await AmapSearch.instance.searchDriveRoute(
|
||||
from: LatLng(
|
||||
double.parse(_fromLatController.text),
|
||||
double.parse(_fromLngController.text),
|
||||
),
|
||||
to: LatLng(
|
||||
double.parse(_toLatController.text),
|
||||
double.parse(_toLngController.text),
|
||||
),
|
||||
);
|
||||
routeResult
|
||||
.toFutureString()
|
||||
.then((it) => setState(() => _routeResult = it));
|
||||
} catch (e) {
|
||||
setState(() => _routeResult = e.toString());
|
||||
}
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(_routeResult),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
92
example/lib/route_plan/route_ride.screen.dart
Normal file
92
example/lib/route_plan/route_ride.screen.dart
Normal file
@ -0,0 +1,92 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 骑行路线规划
|
||||
class RouteRideScreen extends StatefulWidget {
|
||||
@override
|
||||
_RouteRideScreenState createState() => _RouteRideScreenState();
|
||||
}
|
||||
|
||||
class _RouteRideScreenState extends State<RouteRideScreen> {
|
||||
final _fromLatController = TextEditingController(text: '30.219933');
|
||||
final _fromLngController = TextEditingController(text: '120.023728');
|
||||
|
||||
final _toLatController = TextEditingController(text: '30.27065');
|
||||
final _toLngController = TextEditingController(text: '120.163117');
|
||||
|
||||
String _routeResult = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('骑行路线规划')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('起点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('终点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final routeResult = await AmapSearch.instance.searchRideRoute(
|
||||
from: LatLng(
|
||||
double.parse(_fromLatController.text),
|
||||
double.parse(_fromLngController.text),
|
||||
),
|
||||
to: LatLng(
|
||||
double.parse(_toLatController.text),
|
||||
double.parse(_toLngController.text),
|
||||
),
|
||||
);
|
||||
routeResult
|
||||
.toFutureString()
|
||||
.then((it) => setState(() => _routeResult = it));
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(child: SingleChildScrollView(child: Text(_routeResult))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
96
example/lib/route_plan/route_walk.screen.dart
Normal file
96
example/lib/route_plan/route_walk.screen.dart
Normal file
@ -0,0 +1,96 @@
|
||||
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
|
||||
import 'package:core_location_fluttify/core_location_fluttify.dart';
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 步行路线规划
|
||||
class RouteWalkScreen extends StatefulWidget {
|
||||
@override
|
||||
_RouteWalkScreenState createState() => _RouteWalkScreenState();
|
||||
}
|
||||
|
||||
class _RouteWalkScreenState extends State<RouteWalkScreen> {
|
||||
final _fromLatController = TextEditingController(text: '30.219933');
|
||||
final _fromLngController = TextEditingController(text: '120.023728');
|
||||
|
||||
final _toLatController = TextEditingController(text: '30.27065');
|
||||
final _toLngController = TextEditingController(text: '120.163117');
|
||||
|
||||
String _routeResult = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(title: const Text('步行路线规划')),
|
||||
body: DecoratedColumn(
|
||||
padding: const EdgeInsets.all(kSpace16),
|
||||
children: <Widget>[
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('起点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _fromLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入出发点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
DecoratedRow(
|
||||
itemSpacing: kSpace8,
|
||||
children: <Widget>[
|
||||
const Text('终点:'),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLatController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点纬度'),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _toLngController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: '输入终点经度'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RaisedButton(
|
||||
onPressed: () async {
|
||||
final routeResult = await AmapSearch.instance.searchWalkRoute(
|
||||
from: LatLng(
|
||||
double.parse(_fromLatController.text),
|
||||
double.parse(_fromLngController.text),
|
||||
),
|
||||
to: LatLng(
|
||||
double.parse(_toLatController.text),
|
||||
double.parse(_toLngController.text),
|
||||
),
|
||||
);
|
||||
routeResult
|
||||
.toFutureString()
|
||||
.then((it) => setState(() => _routeResult = it));
|
||||
},
|
||||
child: const Text('搜索'),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(_routeResult),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
13
example/lib/utils/misc.dart
Normal file
13
example/lib/utils/misc.dart
Normal file
@ -0,0 +1,13 @@
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
Future<bool> requestPermission() async {
|
||||
final status = await Permission.location.request();
|
||||
|
||||
if (status == PermissionStatus.granted) {
|
||||
return true;
|
||||
} else {
|
||||
toast('需要定位权限!');
|
||||
return false;
|
||||
}
|
||||
}
|
1
example/lib/utils/utils.export.dart
Normal file
1
example/lib/utils/utils.export.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'misc.dart';
|
26
example/lib/widgets/button.widget.dart
Normal file
26
example/lib/widgets/button.widget.dart
Normal file
@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Button extends StatelessWidget {
|
||||
const Button({
|
||||
Key? key,
|
||||
required this.label,
|
||||
required this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
final String label;
|
||||
final ValueChanged<BuildContext> onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RaisedButton(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
color: Colors.black,
|
||||
onPressed: () => onPressed(context),
|
||||
shape: const StadiumBorder(),
|
||||
child: Text(
|
||||
label,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 15),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
74
example/lib/widgets/dimens.dart
Normal file
74
example/lib/widgets/dimens.dart
Normal file
@ -0,0 +1,74 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
//region space
|
||||
const kSpaceZero = 0.0;
|
||||
const kSpaceTiny = 1.0;
|
||||
const kSpaceSmall = 4.0;
|
||||
const kSpace8 = 8.0;
|
||||
const kSpaceLittleBig = 12.0;
|
||||
const kSpace16 = 16.0;
|
||||
const kSpaceLarge = 24.0;
|
||||
const kSpaceHuge = 32.0;
|
||||
const kSpaceGiant = 64.0;
|
||||
|
||||
const SPACE_ZERO = SizedBox.shrink();
|
||||
|
||||
const SPACE_TINY = SizedBox(width: kSpaceTiny, height: kSpaceTiny);
|
||||
const SPACE_TINY_HORIZONTAL = SizedBox(width: kSpaceTiny, height: kSpaceZero);
|
||||
const SPACE_TINY_VERTICAL = SizedBox(width: kSpaceZero, height: kSpaceTiny);
|
||||
|
||||
const SPACE_SMALL = SizedBox(width: kSpaceSmall, height: kSpaceSmall);
|
||||
const SPACE_4_HORIZONTAL = SizedBox(width: kSpaceSmall, height: kSpaceZero);
|
||||
const SPACE_SMALL_VERTICAL = SizedBox(width: kSpaceZero, height: kSpaceSmall);
|
||||
|
||||
const SPACE_NORMAL = SizedBox(width: kSpace8, height: kSpace8);
|
||||
const SPACE_NORMAL_HORIZONTAL = SizedBox(width: kSpace8, height: kSpaceZero);
|
||||
const SPACE_NORMAL_VERTICAL = SizedBox(width: kSpaceZero, height: kSpace8);
|
||||
|
||||
const SPACE_LITTLE_BIG =
|
||||
SizedBox(width: kSpaceLittleBig, height: kSpaceLittleBig);
|
||||
const SPACE_LITTLE_BIG_HORIZONTAL =
|
||||
SizedBox(width: kSpaceLittleBig, height: kSpaceZero);
|
||||
const SPACE_LITTLE_BIG_VERTICAL =
|
||||
SizedBox(width: kSpaceZero, height: kSpaceLittleBig);
|
||||
|
||||
const SPACE_BIG = SizedBox(width: kSpace16, height: kSpace16);
|
||||
const SPACE_BIG_HORIZONTAL = SizedBox(width: kSpace16, height: kSpaceZero);
|
||||
const SPACE_BIG_VERTICAL = SizedBox(width: kSpaceZero, height: kSpace16);
|
||||
|
||||
const SPACE_LARGE = SizedBox(width: kSpaceLarge, height: kSpaceLarge);
|
||||
const SPACE_LARGE_HORIZONTAL = SizedBox(width: kSpaceLarge, height: kSpaceZero);
|
||||
const SPACE_LARGE_VERTICAL = SizedBox(width: kSpaceZero, height: kSpaceLarge);
|
||||
|
||||
const SPACE_HUGE = SizedBox(width: kSpaceHuge, height: kSpaceHuge);
|
||||
const SPACE_HUGE_HORIZONTAL = SizedBox(width: kSpaceHuge, height: kSpaceZero);
|
||||
const SPACE_HUGE_VERTICAL = SizedBox(width: kSpaceZero, height: kSpaceHuge);
|
||||
|
||||
const SPACE_GIANT = SizedBox(width: kSpaceGiant, height: kSpaceGiant);
|
||||
const SPACE_GIANT_HORIZONTAL = SizedBox(width: kSpaceGiant, height: kSpaceZero);
|
||||
const SPACE_GIANT_VERTICAL = SizedBox(width: kSpaceZero, height: kSpaceGiant);
|
||||
|
||||
const kDividerTiny = Divider(height: kSpaceTiny);
|
||||
const kDividerSmall = Divider(height: kSpaceSmall);
|
||||
const kDividerNormal = Divider();
|
||||
const kDividerLittleBig = Divider(height: kSpaceLittleBig);
|
||||
const kDividerBig = Divider(height: kSpace16);
|
||||
const kDividerLarge = Divider(height: kSpaceLarge);
|
||||
const kDividerHuge = Divider(height: kSpaceHuge);
|
||||
const kDividerGiant = Divider(height: kSpaceGiant);
|
||||
//endregion
|
||||
|
||||
//region text
|
||||
const kTextNormal = 16.0;
|
||||
const kTextBig = 18.0;
|
||||
//endregion
|
||||
|
||||
//region elevation
|
||||
const kElevationZero = 0.0;
|
||||
const kElevationTiny = 1.0;
|
||||
const kElevationSmall = 2.0;
|
||||
const kElevationNormal = 4.0;
|
||||
const kElevationBig = 8.0;
|
||||
const kElevationHuge = 16.0;
|
||||
const kElevationGiant = 32.0;
|
||||
//endregion
|
36
example/lib/widgets/function_group.widget.dart
Normal file
36
example/lib/widgets/function_group.widget.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FunctionGroup extends StatelessWidget {
|
||||
const FunctionGroup({
|
||||
Key? key,
|
||||
required this.headLabel,
|
||||
this.children = const [],
|
||||
}) : super(key: key);
|
||||
|
||||
final String headLabel;
|
||||
final List<Widget> children;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(headLabel,
|
||||
style: Theme.of(context).textTheme.headline6),
|
||||
),
|
||||
const Divider(height: 1, indent: 16),
|
||||
],
|
||||
), ...children,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
34
example/lib/widgets/function_item.widget.dart
Normal file
34
example/lib/widgets/function_item.widget.dart
Normal file
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FunctionItem extends StatelessWidget {
|
||||
const FunctionItem({
|
||||
Key? key,
|
||||
required this.label,
|
||||
required this.sublabel,
|
||||
required this.target,
|
||||
}) : super(key: key);
|
||||
|
||||
final String label;
|
||||
final String sublabel;
|
||||
final Widget target;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(label),
|
||||
subtitle: Text(sublabel),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => target),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1, indent: 16),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
17
example/lib/widgets/future.widget.dart
Normal file
17
example/lib/widgets/future.widget.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:decorated_flutter/decorated_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FutureText extends StatelessWidget {
|
||||
const FutureText(this.data, {Key? key}) : super(key: key);
|
||||
|
||||
final Future<String> data;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleSubscriber<String>(
|
||||
future: data,
|
||||
showLoading: false,
|
||||
builder: (data) => Text(data),
|
||||
);
|
||||
}
|
||||
}
|
12
example/lib/widgets/scrollable_text.widget.dart
Normal file
12
example/lib/widgets/scrollable_text.widget.dart
Normal file
@ -0,0 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ScrollableText extends StatelessWidget {
|
||||
final String data;
|
||||
|
||||
const ScrollableText(this.data, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(child: Text(data));
|
||||
}
|
||||
}
|
209
example/lib/widgets/setting.widget.dart
Normal file
209
example/lib/widgets/setting.widget.dart
Normal file
@ -0,0 +1,209 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const SPACE_NORMAL = SizedBox(width: 8, height: 8);
|
||||
const kDividerTiny = Divider(height: 1);
|
||||
|
||||
/// 连续设置
|
||||
class ContinuousSetting extends StatefulWidget {
|
||||
const ContinuousSetting({
|
||||
Key? key,
|
||||
required this.head,
|
||||
required this.onChanged,
|
||||
this.min = 0,
|
||||
this.max = 1,
|
||||
}) : super(key: key);
|
||||
|
||||
final String head;
|
||||
final ValueChanged<double> onChanged;
|
||||
final double min;
|
||||
final double max;
|
||||
|
||||
@override
|
||||
_ContinuousSettingState createState() => _ContinuousSettingState();
|
||||
}
|
||||
|
||||
class _ContinuousSettingState extends State<ContinuousSetting> {
|
||||
late double _value;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
top: 16,
|
||||
right: 16,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(widget.head, style: Theme.of(context).textTheme.subtitle1),
|
||||
SPACE_NORMAL,
|
||||
Slider(
|
||||
value: _value,
|
||||
min: widget.min,
|
||||
max: widget.max,
|
||||
onChanged: (_) {},
|
||||
onChangeEnd: (value) {
|
||||
setState(() {
|
||||
_value = value;
|
||||
widget.onChanged(value);
|
||||
});
|
||||
},
|
||||
),
|
||||
kDividerTiny,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 离散设置
|
||||
class DiscreteSetting extends StatelessWidget {
|
||||
const DiscreteSetting({
|
||||
Key? key,
|
||||
required this.head,
|
||||
required this.options,
|
||||
required this.onSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
final String head;
|
||||
final List<String> options;
|
||||
final ValueChanged<String> onSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
PopupMenuButton<String>(
|
||||
onSelected: onSelected,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(head, style: Theme.of(context).textTheme.subtitle1),
|
||||
),
|
||||
itemBuilder: (context) {
|
||||
return options
|
||||
.map((value) => PopupMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
))
|
||||
.toList();
|
||||
},
|
||||
),
|
||||
kDividerTiny,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 颜色设置
|
||||
class ColorSetting extends StatelessWidget {
|
||||
const ColorSetting({
|
||||
Key? key,
|
||||
required this.head,
|
||||
required this.onSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
final String head;
|
||||
final ValueChanged<Color?> onSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DiscreteSetting(
|
||||
head: head,
|
||||
options: const ['绿色', '红色', '黄色'],
|
||||
onSelected: (value) {
|
||||
Color? color;
|
||||
switch (value) {
|
||||
case '绿色':
|
||||
color = Colors.green.withOpacity(0.6);
|
||||
break;
|
||||
case '红色':
|
||||
color = Colors.red.withOpacity(0.6);
|
||||
break;
|
||||
case '黄色':
|
||||
color = Colors.yellow.withOpacity(0.6);
|
||||
break;
|
||||
}
|
||||
|
||||
onSelected(color);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 二元设置
|
||||
class BooleanSetting extends StatefulWidget {
|
||||
const BooleanSetting({
|
||||
Key? key,
|
||||
required this.head,
|
||||
required this.onSelected,
|
||||
this.selected = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final String head;
|
||||
final ValueChanged<bool> onSelected;
|
||||
final bool selected;
|
||||
|
||||
@override
|
||||
_BooleanSettingState createState() => _BooleanSettingState();
|
||||
}
|
||||
|
||||
class _BooleanSettingState extends State<BooleanSetting> {
|
||||
late bool _selected;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_selected = widget.selected;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
SwitchListTile(
|
||||
title: Text(widget.head),
|
||||
value: _selected,
|
||||
onChanged: (selected) {
|
||||
setState(() {
|
||||
_selected = selected;
|
||||
widget.onSelected(selected);
|
||||
});
|
||||
},
|
||||
),
|
||||
kDividerTiny,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 输入文字
|
||||
class TextSetting extends StatelessWidget {
|
||||
final String leadingString;
|
||||
final String hintString;
|
||||
|
||||
const TextSetting({
|
||||
Key? key,
|
||||
required this.leadingString,
|
||||
required this.hintString,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Text(leadingString),
|
||||
title: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
hintText: hintString,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
11
example/lib/widgets/todo.screen.dart
Normal file
11
example/lib/widgets/todo.screen.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TodoScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Todo')),
|
||||
body: const Center(child: Text('Todo')),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user