import 'dart:ui'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:geolocator/geolocator.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/main.dart'; import 'package:huixiang/retrofit/data/address.dart'; import 'package:huixiang/retrofit/data/ip_data.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/union/union_list.dart'; import 'package:huixiang/utils/event_type.dart'; import 'package:huixiang/utils/location.dart'; import 'package:huixiang/view_widget/my_tab.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:visibility_detector/visibility_detector.dart'; import '../view_widget/location_tips.dart'; import '../view_widget/no_data_view.dart'; class UnionPage extends StatefulWidget { final int initialIndex; UnionPage(Key key, this.initialIndex) : super(key: key); @override State createState() { return UnionPageState(); } } class UnionPageState extends State with AutomaticKeepAliveClientMixin, WidgetsBindingObserver, SingleTickerProviderStateMixin { final TextEditingController editingController = TextEditingController(); bool isKeyBoardShow = false; TabController tabController; Position latLng; String areaName; List _allKey = []; bool _isShowLocalTips = false; double visiblePercentage; jumpIndex(jpIndex) { tabController.index = jpIndex; } @override void dispose() { super.dispose(); WidgetsBinding.instance.removeObserver(this); // if (LocationInstance.getInstance() != null && // LocationInstance.getInstance().location != null) // LocationInstance.getInstance().location.stopLocation(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // 处理应用程序切换回前台的逻辑 if(visiblePercentage == 1) permissionSettings(); } else if (state == AppLifecycleState.paused) { // 处理应用程序切换到后台的逻辑 } } void permissionSettings() async { if (_isShowLocalTips && await Permission.location.isGranted){ _isShowLocalTips = false; getLocation(); } } @override void didChangeMetrics() { super.didChangeMetrics(); WidgetsBinding.instance.addPostFrameCallback((_) { setState(() { print("object: ${MediaQuery.of(context).viewInsets.bottom}"); if (MediaQuery.of(context).viewInsets.bottom == 0) { if (isKeyBoardShow) { isKeyBoardShow = false; //关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 FocusScope.of(context).requestFocus(FocusNode()); } } else { isKeyBoardShow = true; } }); }); } @override void initState() { super.initState(); tabController = TabController( length: 4, vsync: this, initialIndex: widget.initialIndex); WidgetsBinding.instance.addObserver(this); eventBus.on().listen((event) { if (event.type < 3) { setState(() {}); } }); queryIpInfo(); } getLocation({bool showLoading = true}) async { if(showLoading) EasyLoading.show( status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black, ); bool powerFlag = false; // bool finallyFlag = false; try { powerFlag = await LocationInstance.getInstance().startLocation(context, (Position result) async { if (result != null && result.latitude != null && result.longitude != null) { print("location: $result"); latLng = Position( latitude: result.latitude, longitude: result.longitude, ); Address address = await LocationInstance.getInstance().getAddress(result.latitude, result.longitude); if (address != null) { await saveLatLng(latLng, address.province, address.city, address.area); areaName = address.city.replaceAll("市", ""); } LocationInstance.getInstance().stopLocation(); } else { await getLatLng(); } loadFinish(showLoading: false); }); } finally { // finallyFlag = true; if (!powerFlag) { if (await Permission.locationWhenInUse.status.isGranted) { getLocation(); } else { _isShowLocalTips = true; loadFinish(showLoading: false); } } } } saveLatLng(Position latLng, province, city, district) async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString("latitude", "${latLng.latitude}"); await prefs.setString("longitude", "${latLng.longitude}"); if (province != null) await prefs.setString("province", province); if (city != null) await prefs.setString("city", city); if (district != null) await prefs.setString("district", district); } getLatLng() async { var tempLatLng = await SharedPreferences.getInstance(); if (tempLatLng.containsKey("latitude") && tempLatLng.containsKey("longitude") && tempLatLng.containsKey("province") && tempLatLng.containsKey("city") && tempLatLng.containsKey("district")) { latLng = Position( latitude: double.tryParse(tempLatLng.getString("latitude")), longitude: double.tryParse(tempLatLng.getString("longitude")), ); } } queryIpInfo() async { EasyLoading.show( status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black, ); try { ApiService apiIpService = ApiService(Dio(), context: context, isIp: true); IpData baseData = await apiIpService.getIpInfo().catchError((onError) {}); if (baseData?.city != null) { areaName = baseData.city.replaceAll("市", ""); } } finally { getLocation(showLoading: false); } } loadFinish({bool showLoading = true}) { if (showLoading) EasyLoading.show( status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black, ); _allKey = [GlobalKey(), GlobalKey(), GlobalKey(), GlobalKey()]; setState(() {}); } @override Widget build(BuildContext context) { super.build(context); return VisibilityDetector( key: Key('my-widget-key'), onVisibilityChanged: (visibilityInfo) { visiblePercentage = visibilityInfo.visibleFraction; if(visiblePercentage == 1) permissionSettings(); }, child: GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { FocusScope.of(context).requestFocus(FocusNode()); }, child: Stack( alignment: Alignment.bottomCenter, children: [ Container( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 17.h), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF32A060), Color(0xFF32A060), Colors.white, Colors.white, ], stops: [ 0, 0.2, 0.4, 1 ]), ), child: Column( children: [ Row( children: [ Padding( padding: EdgeInsets.only(left: 18.w, right: 10.w), child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { Navigator.of(context).pushNamed( '/router/union_select_city', arguments: {"cityName": areaName}).then((value) { if (value != null) { areaName = value; loadFinish(); } }); }, child: Row( children: [ Text( areaName ?? "", overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.bold, color: Colors.white), ), Icon( Icons.keyboard_arrow_down, color: Colors.white, size: 24, ) ], ), ), ), Expanded(child: buildSearchItem()) ], ), Align( alignment: Alignment.centerLeft, child: TabBar( controller: tabController, isScrollable: true, //可滚动 indicatorColor: Colors.white, labelColor: Colors.white, labelStyle: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, ), unselectedLabelStyle: TextStyle( fontSize: 15.sp, fontWeight: FontWeight.normal, ), //未选中文字颜色 unselectedLabelColor: Colors.white, indicatorSize: TabBarIndicatorSize.label, //指示器与文字等宽 tabs: [ MyTab(text: S.of(context).quanbu), MyTab(text: S.of(context).chi), MyTab(text: S.of(context).he), MyTab(text: S.of(context).wan), ], ), ), _allKey.isEmpty ? NoDataView( src: "assets/image/di_zhi.webp", isShowBtn: false, text: "暂无店铺列表~", fontSize: 16.sp, margin: EdgeInsets.only(top: 120.h), ) : Expanded( child: TabBarView( controller: tabController, children: [ UnionList(_allKey[0], "", latLng, editingController.text, areaName), UnionList(_allKey[1], "EATSTORE", latLng, editingController.text, areaName), UnionList(_allKey[2], "DRINKSTORE", latLng, editingController.text, areaName), UnionList(_allKey[3], "HAPPYSTORE", latLng, editingController.text, areaName), ], ), ) ], ), ), if (_isShowLocalTips) Padding( padding: EdgeInsets.only(bottom: 70.h), child: LocationTips(() { setState(() { _isShowLocalTips = false; }); }), ) ], ), )); } Widget buildSearchItem() { return Container( margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), padding: EdgeInsets.symmetric(vertical: 6.h), decoration: BoxDecoration( color: Color(0xFFF5FAF7), borderRadius: BorderRadius.circular(4), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 3), blurRadius: 14, spreadRadius: 0, ), ], ), child: TextField( textInputAction: TextInputAction.search, onEditingComplete: () { FocusScope.of(context).requestFocus(FocusNode()); loadFinish(); }, controller: editingController, style: TextStyle( fontSize: 14.sp, ), decoration: InputDecoration( hintText: "搜索联盟会员店", hintStyle: TextStyle( fontSize: 12.sp, color: Color(0xFFB3B3B3), ), isCollapsed: true, prefixIcon: Padding( padding: EdgeInsets.only(left: 5.w, right: 5.w), child: Image.asset( "assets/image/icon_search.webp", width: 16.h, height: 16.h, ), ), prefixIconConstraints: BoxConstraints(), border: InputBorder.none, ), ), ); } @override bool get wantKeepAlive => true; }