5个文件已删除
1 文件已重命名
25个文件已修改
40个文件已添加
| | |
| | | if (flutterVersionName == null) { |
| | | flutterVersionName = '1.0' |
| | | } |
| | | //key |
| | | def keystorePropertiesFile = rootProject.file("key.properties") |
| | | def keystoreProperties = new Properties() |
| | | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) |
| | | |
| | | |
| | | apply plugin: 'com.android.application' |
| | | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" |
| | | |
| | | android { |
| | | compileSdkVersion 30 |
| | | compileSdkVersion 31 |
| | | |
| | | compileOptions { |
| | | sourceCompatibility JavaVersion.VERSION_1_8 |
| | |
| | | defaultConfig { |
| | | multiDexEnabled true |
| | | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). |
| | | applicationId "com.yeshi.location" |
| | | applicationId "com.dw.zzql" |
| | | minSdkVersion 19 |
| | | targetSdkVersion 30 |
| | | targetSdkVersion 31 |
| | | versionCode flutterVersionCode.toInteger() |
| | | versionName flutterVersionName |
| | | ndk { |
| | | //兼容64位与32位系统 |
| | | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' |
| | | } |
| | | } |
| | | signingConfigs { |
| | | release { |
| | | keyAlias keystoreProperties['keyAlias'] |
| | | keyPassword keystoreProperties['keyPassword'] |
| | | storeFile file(keystoreProperties['storeFile']) |
| | | storePassword keystoreProperties['storePassword'] |
| | | } |
| | | debug{ |
| | | keyAlias keystoreProperties['keyAlias'] |
| | | keyPassword keystoreProperties['keyPassword'] |
| | | storeFile file(keystoreProperties['storeFile']) |
| | | storePassword keystoreProperties['storePassword'] |
| | | } |
| | | } |
| | | |
| | | buildTypes { |
| | | release { |
| | | // TODO: Add your own signing config for the release build. |
| | | // Signing with the debug keys for now, so `flutter run --release` works. |
| | | signingConfig signingConfigs.debug |
| | | signingConfig signingConfigs.release |
| | | } |
| | | } |
| | | } |
| | |
| | | api files('lib/umeng-common-9.4.4.jar') |
| | | api files('lib/umeng-asms-armeabi-v1.4.1.aar') |
| | | //阿里云手机号认证 |
| | | implementation files('lib/crashshield-2.0.0-release.aar') |
| | | implementation files('lib/logger-2.0.0-release.aar') |
| | | implementation files('lib/main-2.0.0-release.aar') |
| | | implementation files('lib/phoneNumber-L-AuthSDK-2.12.0.aar') |
| | | implementation files('lib/crashshield-2.1.2-release.aar') |
| | | implementation files('lib/logger-2.1.2-release.aar') |
| | | implementation files('lib/main-2.1.2-release.aar') |
| | | implementation files('lib/auth_number_product-2.12.3-log-online-standard-release.aar') |
| | | //QQ互联 |
| | | implementation files('lib/open_sdk_3.5.7.4_r1bc9afe_lite.jar') |
| | | |
| | | } |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:tools="http://schemas.android.com/tools" |
| | | package="com.yeshi.location"> |
| | | <application |
| | | android:name=".MyApplication" |
| | | android:label="locations" |
| | | |
| | | <uses-permission android:name="android.permission.INTERNET"></uses-permission> |
| | | <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> |
| | | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> |
| | | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> |
| | | <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> |
| | | <application |
| | | android:name=".MyApplication" |
| | | android:label="@string/app_name" |
| | | android:usesCleartextTraffic="true" |
| | | android:icon="@mipmap/ic_launcher"> |
| | | <activity |
| | | android:name=".MainActivity" |
| | |
| | | android:theme="@style/LaunchTheme" |
| | | android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" |
| | | android:hardwareAccelerated="true" |
| | | android:windowSoftInputMode="adjustResize"> |
| | | android:windowSoftInputMode="adjustResize" |
| | | android:exported="true"> |
| | | <!-- Specifies an Android theme to apply to this Activity as soon as |
| | | the Android process has started. This theme is visible to the user |
| | | while the Flutter UI initializes. After that, this theme continues |
| | |
| | | <activity |
| | | android:name="com.tencent.tauth.AuthActivity" |
| | | android:launchMode="singleTask" |
| | | android:noHistory="true" > |
| | | android:noHistory="true" |
| | | android:exported="true" |
| | | tools:ignore="AppLinkUrlError"> |
| | | <intent-filter> |
| | | <action android:name="android.intent.action.VIEW" /> |
| | | <category android:name="android.intent.category.DEFAULT" /> |
| | | <category android:name="android.intent.category.BROWSABLE" /> |
| | | <data android:scheme="[QQ APPId]" /> |
| | | <data android:scheme="tencent1112069290" /> |
| | | </intent-filter> |
| | | </activity> |
| | | |
| | | <!-- 阿里云手机号认证 --> |
| | | |
| | | <!--联通电信授权⻚--> |
| | | <activity |
| | | android:name="com.mobile.auth.gatewayauth.LoginAuthActivity" |
| | | android:configChanges="orientation|keyboardHidden|screenSize" |
| | | android:exported="false" |
| | | android:launchMode="singleTop" |
| | | android:theme="@style/authsdk_activity_dialog" /> |
| | | <activity |
| | | android:name="com.mobile.auth.gatewayauth.activity.AuthWebVeiwActivity" |
| | | android:configChanges="orientation|keyboardHidden|screenSize" |
| | | android:exported="false" |
| | | android:launchMode="singleTop" |
| | | android:screenOrientation="behind" /> |
| | | |
| | | <activity |
| | | android:name="com.cmic.sso.sdk.activity.LoginAuthActivity" |
| | | android:configChanges="orientation|keyboardHidden|screenSize" |
| | | android:exported="false" |
| | | android:launchMode="singleTop" /> |
| | | |
| | | <!--百度地图 --> |
| | | |
| | | <meta-data |
| | | android:name="com.baidu.lbsapi.API_KEY" |
| | | android:value="cOlR8Kpr9SKqL3gghONxxltcZOxEqFh0" /> |
| | | |
| | | </application> |
| | | </manifest> |
| | |
| | | |
| | | import android.os.Bundle; |
| | | |
| | | import com.yeshi.location.plugins.FlutterPlugins; |
| | | import com.yeshi.location.plugins.FlutterAliyunPhoneNumberAuthPlugins; |
| | | import com.yeshi.location.plugins.InitAppFlutterPlugins; |
| | | import com.yeshi.location.plugins.LoginFlutterPlugins; |
| | | import com.yeshi.location.plugins.ShareFlutterPlugins; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.annotation.Nullable; |
| | |
| | | public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { |
| | | super.configureFlutterEngine(flutterEngine); |
| | | Log.i(TAG,"configureFlutterEngine"); |
| | | FlutterPlugins.registerWith(MainActivity.this, flutterEngine.getDartExecutor().getBinaryMessenger()); |
| | | //原生分享 |
| | | ShareFlutterPlugins.registerWith(MainActivity.this, flutterEngine.getDartExecutor().getBinaryMessenger()); |
| | | //阿里云一键登录 |
| | | FlutterAliyunPhoneNumberAuthPlugins.registerWith(MainActivity.this,flutterEngine.getDartExecutor().getBinaryMessenger()); |
| | | //系统初始化 |
| | | InitAppFlutterPlugins.registerWith(flutterEngine.getDartExecutor().getBinaryMessenger()); |
| | | //登录插件 |
| | | LoginFlutterPlugins.registerWith(MainActivity.this,flutterEngine.getDartExecutor().getBinaryMessenger()); |
| | | } |
| | | } |
| | |
| | | package com.yeshi.location; |
| | | |
| | | import com.baidu.mapapi.base.BmfMapApplication; |
| | | import android.Manifest; |
| | | import android.app.Application; |
| | | import android.content.Context; |
| | | import android.os.Build; |
| | | import android.telephony.TelephonyManager; |
| | | import android.util.Log; |
| | | |
| | | public class MyApplication extends BmfMapApplication { |
| | | import com.baidu.mapapi.SDKInitializer; |
| | | import com.tencent.tauth.Tencent; |
| | | import com.umeng.analytics.MobclickAgent; |
| | | import com.umeng.commonsdk.UMConfigure; |
| | | import com.yeshi.location.utils.ManifestDataUtil; |
| | | |
| | | import androidx.multidex.MultiDex; |
| | | |
| | | |
| | | public class MyApplication extends Application { |
| | | |
| | | public static MyApplication application; |
| | | |
| | | //兼容4.4以下版本 |
| | | protected void attachBaseContext(Context newBase) { |
| | | super.attachBaseContext(newBase); |
| | | MultiDex.install(this); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void onCreate() { |
| | | super.onCreate(); |
| | | application = this; |
| | | MultiDex.install(this); |
| | | |
| | | } |
| | | |
| | | public static void init(final Application application) { |
| | | //友盟初始化 |
| | | String channel = ManifestDataUtil.getAppMetaData(application, "UMENG_CHANNEL"); |
| | | try { |
| | | UMConfigure.setLogEnabled(false); |
| | | UMConfigure.init(application, application.getResources().getString(R.string.umeng_key), channel, UMConfigure.DEVICE_TYPE_PHONE, null); |
| | | // 选用AUTO页面采集模式 |
| | | MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO); |
| | | } catch (Throwable e) { |
| | | |
| | | } |
| | | //百度地图 |
| | | SDKInitializer.initialize(application); |
| | | //初始化QQ登录 |
| | | Tencent.setIsPermissionGranted(true); |
| | | } |
| | | } |
| | |
| | | package com.yeshi.location.plugins; |
| | | |
| | | import android.app.Activity; |
| | | import android.app.AlertDialog; |
| | | import android.content.DialogInterface; |
| | | import android.graphics.Color; |
| | | import android.util.Log; |
| | | import android.widget.ImageView; |
| | | |
| | | import com.mobile.auth.gatewayauth.AuthUIConfig; |
| | | import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; |
| | | import com.mobile.auth.gatewayauth.ResultCode; |
| | | import com.mobile.auth.gatewayauth.TokenResultListener; |
| | | import com.mobile.auth.gatewayauth.model.TokenRet; |
| | | import com.yeshi.location.R; |
| | | import com.yeshi.location.utils.DimenUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.annotation.Nullable; |
| | | import io.flutter.plugin.common.BasicMessageChannel; |
| | | import io.flutter.plugin.common.BinaryMessenger; |
| | | import io.flutter.plugin.common.MethodCall; |
| | | import io.flutter.plugin.common.MethodChannel; |
| | | import io.flutter.plugin.common.StandardMessageCodec; |
| | | import io.flutter.plugin.common.StringCodec; |
| | | |
| | | public class FlutterAliyunPhoneNumberAuthPlugins implements MethodChannel.MethodCallHandler { |
| | | public static String CHANNEL = "com.yeshi.location/aliyunOneKeyLogin"; // 分析1 |
| | | public class FlutterAliyunPhoneNumberAuthPlugins implements BasicMessageChannel.MessageHandler<Object> { |
| | | |
| | | static MethodChannel channel; |
| | | private Activity activity; |
| | | private static final String TAG = "AliyunPhoneNumberAuth"; |
| | | |
| | | private final Activity activity; |
| | | private final BasicMessageChannel<Object> messageChannel; |
| | | |
| | | private PhoneNumberAuthHelper mPhoneNumberAuthHelper; |
| | | private BasicMessageChannel.Reply<Object> reply; |
| | | |
| | | private FlutterAliyunPhoneNumberAuthPlugins(Activity activity) { |
| | | |
| | | private FlutterAliyunPhoneNumberAuthPlugins(Activity activity, BinaryMessenger messager) { |
| | | this.activity = activity; |
| | | this.messageChannel = new BasicMessageChannel<Object>(messager, "AliyunPhoneNumberAuth", StandardMessageCodec.INSTANCE); |
| | | messageChannel.setMessageHandler(this); |
| | | } |
| | | |
| | | public static void registerWith(Activity activity, BinaryMessenger messager) { |
| | | channel = new MethodChannel(messager, CHANNEL); |
| | | FlutterAliyunPhoneNumberAuthPlugins instance = new FlutterAliyunPhoneNumberAuthPlugins(activity); |
| | | channel.setMethodCallHandler(instance); |
| | | public static FlutterAliyunPhoneNumberAuthPlugins registerWith(Activity activity, BinaryMessenger messager) { |
| | | return new FlutterAliyunPhoneNumberAuthPlugins(activity, messager); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) { // 分析 2 |
| | | String method = methodCall.method; |
| | | public void onMessage(@Nullable Object message, @NonNull BasicMessageChannel.Reply<Object> reply) { |
| | | this.reply = reply; |
| | | Map<String, String> arguments = (Map<String, String>) message; |
| | | String method = arguments.get("method"); |
| | | switch (method) { |
| | | //初始化 |
| | | case "init": |
| | | initOneKeyLogin(); |
| | | result.success(true); |
| | | initOneKeyLogin(arguments.get("secret"), arguments.get("privacy"), arguments.get("protocol")); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", 0); |
| | | reply.reply(map); |
| | | break; |
| | | default: |
| | | result.notImplemented(); |
| | | |
| | | case "checkEnv": |
| | | mPhoneNumberAuthHelper.checkEnvAvailable(2); |
| | | break; |
| | | case "startLogin": |
| | | mPhoneNumberAuthHelper.getLoginToken(activity, 5000); |
| | | break; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 向Dart发送消息,并接受Dart的反馈 |
| | | * |
| | | * @param message 要给Dart发送的消息内容 |
| | | * @param callback 来自Dart的反馈 |
| | | */ |
| | | void send(String message, BasicMessageChannel.Reply<Object> callback) { |
| | | messageChannel.send(message, callback); |
| | | } |
| | | |
| | | |
| | | private void initOneKeyLogin() { |
| | | sdkInit(""); |
| | | initUI(); |
| | | private void initOneKeyLogin(String secretInfo, String privacyUrl, String userProtocolUrl) { |
| | | sdkInit(secretInfo); |
| | | initUI(privacyUrl, userProtocolUrl); |
| | | } |
| | | |
| | | private void initUI(String privacy, String protocol) { |
| | | |
| | | |
| | | private void initUI() { |
| | | |
| | | int width = DimenUtils.getScreenWidth(this); |
| | | int widthDP = DimenUtils.px2dip(this, width); |
| | | int width = DimenUtils.getScreenWidth(activity); |
| | | int widthDP = DimenUtils.px2dip(activity, width); |
| | | AuthUIConfig uiCOnfig = new AuthUIConfig.Builder() |
| | | .setPageBackgroundPath("shape_login_onkey_bg") |
| | | |
| | |
| | | .setNavColor(Color.WHITE) |
| | | .setNavHidden(false) |
| | | .setNavReturnImgPath("ic_login_close") |
| | | .setNavReturnImgWidth(22) |
| | | .setNavReturnImgHeight(22) |
| | | .setNavReturnImgWidth(32) |
| | | .setNavReturnImgHeight(32) |
| | | .setNavReturnScaleType(ImageView.ScaleType.FIT_XY) |
| | | .setWebNavColor(Color.BLACK) |
| | | .setWebNavReturnImgPath("ic_back_two") |
| | | // .setWebNavReturnImgPath("ic_back_two") |
| | | .setWebViewStatusBarColor(Color.WHITE) |
| | | .setStatusBarColor(Color.WHITE) |
| | | |
| | | .setLogoWidth(147) |
| | | .setLogoHeight(36) |
| | | .setLogoImgPath("ic_login_logo") |
| | | .setLogoWidth(0) |
| | | .setLogoHeight(0) |
| | | // .setLogoImgPath("ic_login_logo") |
| | | .setLogoOffsetY(24 - 10) |
| | | |
| | | .setSloganOffsetY(171 - 10) |
| | | .setSloganOffsetY(125 - 10) |
| | | .setSloganTextSize(12) |
| | | .setSloganTextColor(Color.parseColor("#F804F5")) |
| | | .setSloganTextColor(activity.getResources().getColor(R.color.onekey_login_theme_color)) |
| | | |
| | | .setLogBtnText("⼀键登录") |
| | | .setLogBtnTextSize(17) |
| | | .setLogBtnTextColor(Color.parseColor("#F4DE4A")) |
| | | .setLogBtnTextColor(Color.WHITE) |
| | | .setLogBtnBackgroundPath("shape_login_btn") |
| | | .setLogBtnOffsetY(229 - 10) |
| | | .setLogBtnOffsetY(170 - 10) |
| | | .setLogBtnHeight(44) |
| | | |
| | | |
| | | .setDialogWidth(305 * widthDP / 375) |
| | | .setDialogHeight(454) |
| | | .setDialogHeight(378) |
| | | .setNavColor(Color.RED) |
| | | .setSwitchAccHidden(true) |
| | | .setNumberColor(Color.parseColor("#0052F6")) |
| | | .setNumberColor(activity.getResources().getColor(R.color.onekey_login_theme_color)) |
| | | .setNumberSize(36) |
| | | .setNumFieldOffsetY(128 - 10) |
| | | .setNumFieldOffsetY(65) |
| | | |
| | | .setAppPrivacyOne("《用户服务协议》", BeibeiConstant.USER_AGREEMENT) |
| | | .setAppPrivacyTwo("《隐私政策》", BeibeiConstant.PRIVACY_POLICY) |
| | | .setAppPrivacyColor(Color.parseColor("#B3B8D3"), Color.parseColor("#51B3FF")) |
| | | .setAppPrivacyOne("《用户服务协议》", protocol) |
| | | .setAppPrivacyTwo("《隐私政策》", privacy) |
| | | .setAppPrivacyColor(activity.getResources().getColor(R.color.onekey_login_notify_color), activity.getResources().getColor(R.color.onekey_login_theme_color)) |
| | | .setPrivacyBefore("登录即表示同意") |
| | | .setPrivacyEnd("") |
| | | .setCheckedImgPath("ic_login_privacy_checked") |
| | | .setUncheckedImgPath("ic_login_privacy_unchecked") |
| | | .setPrivacyTextSize(11) |
| | | .setPrivacyState(false) |
| | | .setVendorPrivacyPrefix("《") |
| | |
| | | |
| | | mPhoneNumberAuthHelper.setAuthUIConfig(uiCOnfig); |
| | | } |
| | | |
| | | private void sdkInit(String secretInfo) { |
| | | mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(activity.getApplicationContext(), new TokenResultListener(){ |
| | | mPhoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(activity.getApplicationContext(), new TokenResultListener() { |
| | | |
| | | @Override |
| | | public void onTokenSuccess(String s) { |
| | | Log.i(TAG, "onTokenSuccess:" + s); |
| | | TokenRet tokenRet = null; |
| | | try { |
| | | tokenRet = TokenRet.fromJson(s); |
| | | |
| | | switch (tokenRet.getCode()) { |
| | | case ResultCode.CODE_ERROR_ENV_CHECK_SUCCESS: { |
| | | Log.i(TAG |
| | | , "终端环境校验成功:" + s); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", 0); |
| | | map.put("msg", "环境监测正常"); |
| | | reply.reply(map); |
| | | } |
| | | break; |
| | | |
| | | case ResultCode.CODE_START_AUTHPAGE_SUCCESS: |
| | | Log.i(TAG, "唤起授权页成功:" + s); |
| | | break; |
| | | |
| | | case ResultCode.CODE_ERROR_USER_CANCEL: { |
| | | Log.i(TAG, "用户取消操作:" + s); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", Integer.parseInt(tokenRet.getCode())); |
| | | map.put("msg", "取消操作"); |
| | | reply.reply(map); |
| | | } |
| | | break; |
| | | |
| | | |
| | | case ResultCode.CODE_SUCCESS: { |
| | | Log.i(TAG, "获取token成功:" + s); |
| | | mPhoneNumberAuthHelper.setAuthListener(null); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", 0); |
| | | map.put("token", tokenRet.getToken()); |
| | | map.put("msg", "获取token成功"); |
| | | reply.reply(map); |
| | | } |
| | | break; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onTokenFailed(String s) { |
| | | |
| | | Log.i(TAG, "onTokenFailed:" + s); |
| | | TokenRet |
| | | tokenRet = TokenRet.fromJson(s); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", Integer.parseInt(tokenRet.getCode())); |
| | | map.put("msg", tokenRet.getMsg()); |
| | | reply.reply(map); |
| | | } |
| | | }); |
| | | mPhoneNumberAuthHelper.getReporter().setLoggerEnable(true); |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.yeshi.location.plugins; |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Context; |
| | | import android.net.Uri; |
| | | import android.os.Build; |
| | | import android.util.Log; |
| | | |
| | | import com.tencent.tauth.Tencent; |
| | | import com.yeshi.location.MyApplication; |
| | | import com.yeshi.location.utils.ShareImageUtil; |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | |
| | | import androidx.core.content.FileProvider; |
| | | import io.flutter.plugin.common.BinaryMessenger; |
| | | import io.flutter.plugin.common.MethodCall; |
| | | import io.flutter.plugin.common.MethodChannel; |
| | | |
| | | /** |
| | | * 应用初始化插件 |
| | | */ |
| | | public class InitAppFlutterPlugins implements MethodChannel.MethodCallHandler { |
| | | public static String CHANNEL = "com.yeshi.location/init"; // 分析1 |
| | | |
| | | static MethodChannel channel; |
| | | |
| | | |
| | | private InitAppFlutterPlugins() { |
| | | } |
| | | |
| | | public static void registerWith(BinaryMessenger messager) { |
| | | channel = new MethodChannel(messager, CHANNEL); |
| | | InitAppFlutterPlugins instance = new InitAppFlutterPlugins(); |
| | | channel.setMethodCallHandler(instance); |
| | | } |
| | | |
| | | @Override |
| | | public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) { // 分析 2 |
| | | String method = methodCall.method; |
| | | switch (method) { |
| | | case "initApp": |
| | | MyApplication.init(MyApplication.application); |
| | | result.success(true); |
| | | break; |
| | | default: |
| | | result.notImplemented(); |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.yeshi.location.plugins; |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Context; |
| | | import android.graphics.Color; |
| | | import android.util.Log; |
| | | import android.widget.ImageView; |
| | | |
| | | import com.mobile.auth.gatewayauth.AuthUIConfig; |
| | | import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper; |
| | | import com.mobile.auth.gatewayauth.ResultCode; |
| | | import com.mobile.auth.gatewayauth.TokenResultListener; |
| | | import com.mobile.auth.gatewayauth.model.TokenRet; |
| | | import com.tencent.tauth.IUiListener; |
| | | import com.tencent.tauth.Tencent; |
| | | import com.tencent.tauth.UiError; |
| | | import com.yeshi.location.R; |
| | | import com.yeshi.location.utils.DimenUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.annotation.Nullable; |
| | | import io.flutter.plugin.common.BasicMessageChannel; |
| | | import io.flutter.plugin.common.BinaryMessenger; |
| | | import io.flutter.plugin.common.StandardMessageCodec; |
| | | |
| | | /** |
| | | * 登录插件 |
| | | * https://wiki.connect.qq.com/qq%e7%99%bb%e5%bd%95 |
| | | */ |
| | | public class LoginFlutterPlugins implements BasicMessageChannel.MessageHandler<Object> { |
| | | |
| | | private static final String TAG = "LoginFlutterPlugins"; |
| | | Tencent mTencent; |
| | | |
| | | private final Activity activity; |
| | | private final Context context; |
| | | private final BasicMessageChannel<Object> messageChannel; |
| | | |
| | | private PhoneNumberAuthHelper mPhoneNumberAuthHelper; |
| | | private BasicMessageChannel.Reply<Object> reply; |
| | | |
| | | |
| | | private LoginFlutterPlugins(Activity activity, BinaryMessenger messager) { |
| | | this.activity = activity; |
| | | this.context = activity.getApplicationContext(); |
| | | this.messageChannel = new BasicMessageChannel<Object>(messager, "ThirdLogin", StandardMessageCodec.INSTANCE); |
| | | messageChannel.setMessageHandler(this); |
| | | } |
| | | |
| | | public static LoginFlutterPlugins registerWith(Activity activity, BinaryMessenger messager) { |
| | | return new LoginFlutterPlugins(activity, messager); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void onMessage(@Nullable Object message, @NonNull BasicMessageChannel.Reply<Object> reply) { |
| | | this.reply = reply; |
| | | Map<String, String> arguments = (Map<String, String>) message; |
| | | String method = arguments.get("method"); |
| | | switch (method) { |
| | | case "loginQQ": |
| | | //QQ登录 |
| | | mTencent = Tencent.createInstance(context.getString(R.string.qq_appid), context); |
| | | if (!mTencent.isSessionValid()) { |
| | | mTencent.login(activity, "all", new IUiListener() { |
| | | @Override |
| | | public void onComplete(Object o) { |
| | | Log.i(TAG, "登录成功:" + o.toString()); |
| | | replyResult(0, null, "登录成功"); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(UiError uiError) { |
| | | Log.i(TAG, "登录出错:" + uiError.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public void onCancel() { |
| | | Log.i(TAG, "取消登录"); |
| | | } |
| | | |
| | | @Override |
| | | public void onWarning(int i) { |
| | | Log.i(TAG, "onWarning"); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", 0); |
| | | reply.reply(map); |
| | | break; |
| | | } |
| | | |
| | | } |
| | | |
| | | void replyResult(int code, Object data, String msg) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("code", code); |
| | | if (data != null) |
| | | map.put("data", data); |
| | | if (msg != null) |
| | | map.put("msg", msg); |
| | | reply.reply(map); |
| | | } |
| | | |
| | | /** |
| | | * 向Dart发送消息,并接受Dart的反馈 |
| | | * |
| | | * @param message 要给Dart发送的消息内容 |
| | | * @param callback 来自Dart的反馈 |
| | | */ |
| | | void send(String message, BasicMessageChannel.Reply<Object> callback) { |
| | | messageChannel.send(message, callback); |
| | | } |
| | | |
| | | } |
File was renamed from android/app/src/main/java/com/yeshi/location/plugins/FlutterPlugins.java |
| | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.core.content.FileProvider; |
| | | import io.flutter.plugin.common.BinaryMessenger; |
| | | import io.flutter.plugin.common.MethodCall; |
| | | import io.flutter.plugin.common.MethodChannel; |
| | | import io.flutter.plugin.common.PluginRegistry; |
| | | |
| | | public class FlutterPlugins implements MethodChannel.MethodCallHandler { |
| | | public class ShareFlutterPlugins implements MethodChannel.MethodCallHandler { |
| | | public static String CHANNEL = "com.yeshi.location/share"; // 分析1 |
| | | |
| | | static MethodChannel channel; |
| | | |
| | | private Activity activity; |
| | | |
| | | private FlutterPlugins(Activity activity) { |
| | | private ShareFlutterPlugins(Activity activity) { |
| | | this.activity = activity; |
| | | } |
| | | |
| | | public static void registerWith(Activity activity, BinaryMessenger messager) { |
| | | channel = new MethodChannel(messager, CHANNEL); |
| | | FlutterPlugins instance = new FlutterPlugins(activity); |
| | | ShareFlutterPlugins instance = new ShareFlutterPlugins(activity); |
| | | channel.setMethodCallHandler(instance); |
| | | } |
| | | |
| | |
| | | String path = methodCall.argument("path"); |
| | | ArrayList<Uri> uris = new ArrayList<>(); |
| | | uris.add(getUriForFile(activity,new File(path))); |
| | | Log.i("FlutterPlugins",platform); |
| | | Log.i("ShareFlutterPlugins",platform); |
| | | switch(platform){ |
| | | case "qq": |
| | | ShareImageUtil.shareQQPictureByIntent(activity, uris); |
New file |
| | |
| | | package com.yeshi.location.utils; |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Context; |
| | | import android.content.res.Resources; |
| | | import android.util.DisplayMetrics; |
| | | import android.util.TypedValue; |
| | | |
| | | public class DimenUtils { |
| | | |
| | | public static int dipToPixels(int dip, Context context) { |
| | | Resources r = context.getResources(); |
| | | float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, |
| | | r.getDisplayMetrics()); |
| | | return (int) px; |
| | | } |
| | | |
| | | public static int pxToDip(int px, Context context) { |
| | | Resources r = context.getResources(); |
| | | // float dip = TypedValue.complexToDimensionPixelSize(data, metrics) |
| | | // TypedValue.complexToDimensionPixelOffset(data, metrics) |
| | | return 0; |
| | | } |
| | | |
| | | public static int spToPixels(int sp, Context context) { |
| | | Resources r = context.getResources(); |
| | | float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, |
| | | r.getDisplayMetrics()); |
| | | return (int) px; |
| | | } |
| | | |
| | | private static int deviceWidth = 0; |
| | | |
| | | public static int getScreenWidth(Activity activity) { |
| | | if (deviceWidth == 0) { |
| | | DisplayMetrics metric = new DisplayMetrics(); |
| | | activity.getWindowManager().getDefaultDisplay().getMetrics(metric); |
| | | deviceWidth = metric.widthPixels; |
| | | } |
| | | return deviceWidth; |
| | | } |
| | | |
| | | public static int getScreenHeight(Activity activity) { |
| | | DisplayMetrics metric = new DisplayMetrics(); |
| | | activity.getWindowManager().getDefaultDisplay().getMetrics(metric); |
| | | return metric.heightPixels; |
| | | } |
| | | |
| | | /** |
| | | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) |
| | | */ |
| | | public static int dip2px(Context context, float dpValue) { |
| | | final float scale = context.getResources().getDisplayMetrics().density; |
| | | return (int) (dpValue * scale + 0.5f); |
| | | } |
| | | |
| | | /** |
| | | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp |
| | | */ |
| | | public static int px2dip(Context context, float pxValue) { |
| | | final float scale = context.getResources().getDisplayMetrics().density; |
| | | return (int) (pxValue / scale + 0.5f); |
| | | } |
| | | |
| | | /** |
| | | * 获取状态栏高度 |
| | | * |
| | | * @param context |
| | | * @return |
| | | */ |
| | | public static int getStatusBarHeight(Context context) { |
| | | Resources resources = context.getResources(); |
| | | int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); |
| | | int height = resources.getDimensionPixelSize(resourceId); |
| | | return height; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.yeshi.location.utils; |
| | | |
| | | import android.content.Context; |
| | | import android.content.pm.ApplicationInfo; |
| | | import android.content.pm.PackageManager; |
| | | import android.text.TextUtils; |
| | | |
| | | public class ManifestDataUtil { |
| | | |
| | | private static final String TAG ="ManifestDataUtil" ; |
| | | |
| | | /** |
| | | * 获取application中指定的meta-data。本例中,调用方法时key就是UMENG_CHANNEL |
| | | * |
| | | * @return 如果没有获取成功(没有对应值 , 或者异常),则返回值为空 |
| | | */ |
| | | public static String getAppMetaData(Context ctx, String key) { |
| | | if (ctx == null || TextUtils.isEmpty(key)) { |
| | | return null; |
| | | } |
| | | String resultData = null; |
| | | try { |
| | | PackageManager packageManager = ctx.getPackageManager(); |
| | | if (packageManager != null) { |
| | | ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA); |
| | | if (applicationInfo != null) { |
| | | if (applicationInfo.metaData != null) { |
| | | resultData = applicationInfo.metaData.getString(key); |
| | | } |
| | | } |
| | | } |
| | | } catch (PackageManager.NameNotFoundException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | return resultData; |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="#FF0E95FE" /> |
| | | <corners android:radius="10dp" /> |
| | | |
| | | |
| | | </shape> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="#FFFFFF" /> |
| | | <corners |
| | | android:radius="15dp" /> |
| | | </shape> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <color name="onekey_login_theme_color">#0E95FE</color> |
| | | <color name="onekey_login_notify_color">#FF9DAAB3</color> |
| | | </resources> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <string name="app_name">定位追踪轨迹</string> |
| | | <string name="umeng_key">618a2aa7e014255fcb7215c2</string> |
| | | <string name="qq_appid">1112069290</string> |
| | | </resources> |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:locations/ui/common/browser.dart'; |
| | | import 'package:locations/ui/mine/advice.dart'; |
| | | import 'package:locations/ui/mine/login.dart'; |
| | | import 'package:locations/ui/mine/permission.dart'; |
| | | import 'package:locations/ui/mine/settings.dart'; |
| | | import 'package:locations/ui/mine/share_to_friends.dart'; |
| | | import 'package:locations/ui/mine/try_functions.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:locations/utils/app_util.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'package:locations/utils/user_util.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | |
| | | import 'ui/main/main.dart'; |
| | | import 'ui/widget/dialog.dart'; |
| | | import 'utils/ui_constant.dart'; |
| | | |
| | | void main() { |
| | | if (Platform.isAndroid) { |
| | | SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( |
| | | statusBarColor: Colors.transparent, |
| | | systemNavigationBarColor: Color(0xFF000000), |
| | | systemNavigationBarDividerColor: null, |
| | | systemNavigationBarIconBrightness: Brightness.light, |
| | | statusBarIconBrightness: Brightness.dark, |
| | | statusBarBrightness: Brightness.light, |
| | | )); |
| | | } |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | |
| | | // or simply save your changes to "hot reload" in a Flutter IDE). |
| | | // Notice that the counter didn't reset back to zero; the application |
| | | // is not restarted. |
| | | primaryColor: Color.fromARGB(255, 150, 150, 150)), |
| | | home: MinePage(title: ''), |
| | | |
| | | primaryColor: Color(0xFFFFFFFF)), |
| | | home: SplashPage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class MinePage extends StatefulWidget { |
| | | MinePage({Key? key, required this.title}) : super(key: key); |
| | | class SplashPage extends StatefulWidget { |
| | | SplashPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | |
| | | final String title; |
| | | |
| | | @override |
| | | _MinePageState createState() => _MinePageState(); |
| | | _SplashPageState createState() => _SplashPageState(); |
| | | } |
| | | |
| | | class _MinePageState extends State<MinePage> |
| | | with AutomaticKeepAliveClientMixin { |
| | | class _SplashPageState extends State<SplashPage> |
| | | with SingleTickerProviderStateMixin { |
| | | int selectIndex = 1; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | // Timer(const Duration(seconds: 5), () { |
| | | // Navigator.of(context).push(CustomRouteSlide(MainPage(title: ""))); |
| | | // }); |
| | | |
| | | Timer(const Duration(seconds: 2), () { |
| | | // Navigator.of(context).push(CustomRouteSlide(MainPage(title: ""))); |
| | | |
| | | // showGeneralDialog(context: context, |
| | | // pageBuilder: (BuildContext buildContext, Animation<double> animation, |
| | | // Animation<double> secondaryAnimation) { |
| | | // return PermissionNotifyDialog(() { |
| | | // Navigator.of(context).pop(); |
| | | // Navigator.of(context).push(CustomRouteSlide(MainPage(title: ""))); |
| | | // }); |
| | | // }); |
| | | }); |
| | | // showDialog( |
| | | // context: context, |
| | | // builder: (context) => PermissionNotifyDialog((){ |
| | | // Navigator.of(context).push(CustomRouteSlide(MainPage(title: ""))); |
| | | // })); |
| | | // String content="欢迎您使用百度地图服务!<a href='http://www.baidu.com'> http://www.baidu.com </a> 我们非常重视您的隐私保护和个人信息保护。本隐私政策适用于您通过任何方式对百度地图各项服务的访问和使用。您可以利用百度地图搜索路况信息、商家信息、定位您所在的位置,进行路径规划、导航您想去的地址,搜索周边的服务等(以下统称“百度地图产品或服务”)。您具体获得的百度地图服务内容可能因为您使用的百度地图的版本及搭载设备不同而有所差异,如果在部分版本或搭载设备中不涵盖某些服务内容或未提供特定功能(例如:部分版本不支持登录,我们可能无法为您提供第三方服务以及其他登录后才能使用的功能;手表等穿戴设备暂时只支持步骑行的路线规划及导航,所以我们在穿戴设备上搭载的地图无法为您提供如驾车路线规划及导航等其他功能),本隐私政策中涉及到上述服务/功能及相关个人信息的内容将不适用。您可以通过多种不同的方式来使用我们的产品和服务,包括百度地图的网站、软件、供第三方网站和应用程序使用的百度地图软件开发工具包(SDK)和应用程序编程接口(API)、车载导航仪、智能后视镜等智能硬件设备。"; |
| | | // showDialog( |
| | | // context: context, |
| | | // builder: (context) => NotifyDialog("用户协议&隐私政策", content, () {}, () {},richText: true,height: 400,)); |
| | | } |
| | | |
| | | void init() { |
| | | AppUtil.initApp(context).then((value) { |
| | | //TODO 显示开屏广告 |
| | | |
| | | NavigatorUtil.navigateToNextPageWithFinish(context, |
| | | MaterialPageRoute(builder: (context) { |
| | | return MainPage(title: ""); |
| | | })); |
| | | }); |
| | | } |
| | | |
| | | Future requestPermission() async { |
| | | final status = await Permission.phone.request(); |
| | | await Permission.storage.request(); |
| | | return; |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | backgroundColor: Colors.white, |
| | | body: Container()); |
| | | UserUtil.isAgreeProtocol().then((value) { |
| | | if (!value) { |
| | | //弹出用户协议框 |
| | | String content = |
| | | "欢迎您使用百度地图服务!<a href='${Constant.PROTOCOL_URL}'> 用户协议 </a>和<a href='${Constant.PRIVACY_URL}'>隐私政策</a> 我们非常重视您的隐私保护和个人信息保护。本隐私政策适用于您通过任何方式对百度地图各项服务的访问和使用。您可以利用百度地图搜索路况信息、商家信息、定位您所在的位置,进行路径规划、导航您想去的地址,搜索周边的服务等(以下统称“百度地图产品或服务”)。您具体获得的百度地图服务内容可能因为您使用的百度地图的版本及搭载设备不同而有所差异,如果在部分版本或搭载设备中不涵盖某些服务内容或未提供特定功能(例如:部分版本不支持登录,我们可能无法为您提供第三方服务以及其他登录后才能使用的功能;手表等穿戴设备暂时只支持步骑行的路线规划及导航,所以我们在穿戴设备上搭载的地图无法为您提供如驾车路线规划及导航等其他功能),本隐私政策中涉及到上述服务/功能及相关个人信息的内容将不适用。您可以通过多种不同的方式来使用我们的产品和服务,包括百度地图的网站、软件、供第三方网站和应用程序使用的百度地图软件开发工具包(SDK)和应用程序编程接口(API)、车载导航仪、智能后视镜等智能硬件设备。"; |
| | | showGeneralDialog( |
| | | context: context, |
| | | pageBuilder: (BuildContext buildContext, |
| | | Animation<double> animation, |
| | | Animation<double> secondaryAnimation) => |
| | | NotifyDialog( |
| | | "用户协议&隐私政策", |
| | | content, |
| | | () { |
| | | Navigator.of(context).pop(); |
| | | }, |
| | | () { |
| | | UserUtil.setAgreeProtocol().then((value) { |
| | | if (value) { |
| | | //弹出权限框 |
| | | showGeneralDialog( |
| | | context: context, |
| | | pageBuilder: (BuildContext buildContext, |
| | | Animation<double> animation, |
| | | Animation<double> secondaryAnimation) { |
| | | return PermissionNotifyDialog(() { |
| | | Navigator.of(context).pop(); |
| | | requestPermission().then((value) { |
| | | init(); |
| | | }); |
| | | }); |
| | | }); |
| | | } else {} |
| | | }); |
| | | }, |
| | | richText: true, |
| | | height: 400, |
| | | )); |
| | | } else { |
| | | //已经同意了 |
| | | init(); |
| | | } |
| | | }); |
| | | |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Scaffold( |
| | | backgroundColor: Colors.white, |
| | | body: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Expanded( |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.all(72), |
| | | color: Colors.white, |
| | | child: Image.asset("assets/images/ic_splash.png"), |
| | | )), |
| | | Container( |
| | | alignment: Alignment.center, |
| | | color: Color(0xFFF8F8F8), |
| | | height: 94, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Text( |
| | | "定位追踪轨迹", |
| | | style: |
| | | TextStyle(color: Color(0xFF03B5FF), fontSize: 23), |
| | | ), |
| | | SizedBox( |
| | | height: 15, |
| | | ), |
| | | Text( |
| | | "腾讯云提供网络服务", |
| | | style: TextStyle(color: Color(0xFF999999), fontSize: 9), |
| | | ), |
| | | ], |
| | | ), |
| | | ) |
| | | ], |
| | | ))); |
| | | } |
| | | |
| | | @override |
| | | bool get wantKeepAlive => true; |
| | | } |
| | | |
New file |
| | |
| | | import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
| | | import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
| | | class MapShowInfo{ |
| | | BMFCoordinate? center; |
| | | int? zoomLevel; |
| | | MapShowInfo(this.center,this.zoomLevel); |
| | | } |
| | |
| | | class QQLoginResult{ |
| | | |
| | | final int code; |
| | | final String message; |
| | | late final int code; |
| | | late final String message; |
| | | |
| | | |
| | | |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:typed_data'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/rendering.dart'; |
| | | import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
| | | import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
| | | import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; |
| | | import 'package:locations/ui/map/location_search.dart'; |
| | | import 'package:locations/ui/mine/advice.dart'; |
| | | import 'package:locations/ui/mine/permission.dart'; |
| | | import 'package:locations/ui/mine/settings.dart'; |
| | | import 'package:locations/ui/mine/share_to_friends.dart'; |
| | | import 'package:locations/ui/mine/try_functions.dart'; |
| | | import 'package:locations/ui/widget/button.dart'; |
| | | import 'package:locations/utils/location_util.dart'; |
| | | import 'package:locations/utils/map_util.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | |
| | | typedef OnPositionHiidenChange = void Function(bool hidden); |
| | | |
| | |
| | | |
| | | class _LocationPageState extends State<LocationPage> |
| | | with AutomaticKeepAliveClientMixin { |
| | | GlobalKey rootWidgetKey = GlobalKey(); |
| | | |
| | | BMFMapOptions mapOptions = BMFMapOptions( |
| | | showMapScaleBar: false, |
| | | mapType: BMFMapType.Standard, |
| | |
| | | body: Stack( |
| | | children: [ |
| | | getMapView(), |
| | | // PositionInfoPage((bool hiiden) { |
| | | // |
| | | // |
| | | // }), |
| | | LocationSearchPage(), |
| | | PositionInfoPage(), |
| | | Positioned( |
| | | top: -100, |
| | | child: |
| | | RepaintBoundary( |
| | | key: rootWidgetKey, |
| | | child: Image.asset( |
| | | "assets/images/mine/icon_mine_default_portrait.png", |
| | | height: 33, |
| | | width: 33, |
| | | ))), |
| | | Align( |
| | | alignment: Alignment.bottomCenter, |
| | | child: getAddLocationObjectView()), |
| | |
| | | return Container( |
| | | child: BMFMapWidget( |
| | | onBMFMapCreated: (controller) { |
| | | // onBMFMapCreated(controller); |
| | | _mapController = controller; |
| | | |
| | | |
| | | Timer(Duration(seconds: 3),(){ |
| | | _capturePng().then((value) { |
| | | BMFMarker marker = BMFMarker( |
| | | position: BMFCoordinate(39.928617, 116.40329), |
| | | title: 'flutterMaker', |
| | | identifier: 'flutter_marker', |
| | | icon:value!.path); |
| | | |
| | | /// 添加Marker |
| | | _mapController?.addMarker(marker); |
| | | }); |
| | | }); |
| | | |
| | | |
| | | |
| | | }, |
| | | mapOptions: mapOptions, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | Future<File?> _capturePng() async { |
| | | await Permission.storage.request(); |
| | | try { |
| | | RenderRepaintBoundary? boundary = rootWidgetKey.currentContext! |
| | | .findRenderObject() as RenderRepaintBoundary; |
| | | var image = await boundary.toImage(pixelRatio: 3.0); |
| | | ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); |
| | | Uint8List pngBytes = byteData!.buffer.asUint8List(); |
| | | Directory? tempDir = await getExternalStorageDirectory(); |
| | | String tempPath = tempDir!.path; |
| | | String shareImgPath = "$tempPath/test.jpg"; |
| | | File(shareImgPath!).writeAsBytesSync(pngBytes!); |
| | | int length=await File(shareImgPath!).length(); |
| | | print("截图大小为:${length}"); |
| | | return File(shareImgPath!); |
| | | } catch (e) { |
| | | print(e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | //添加想定位的人 |
| | |
| | | //位置信息是否隐藏 |
| | | bool locationInfoHidden = true; |
| | | |
| | | GlobalKey rootWidgetKey = GlobalKey(); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Container( |
| | |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | print("跳转定位"); |
| | | NavigatorUtil.navigateToNextPage(context, LocationSearchPage(), |
| | | (data) { }); |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | |
| | | } else { |
| | | return Container(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /********************POI搜索********************/ |
| | | class LocationSearchPage extends StatefulWidget { |
| | | @override |
| | | _LocationSearchPageState createState() => _LocationSearchPageState(); |
| | | } |
| | | |
| | | class _LocationSearchPageState extends State<LocationSearchPage> |
| | | with SingleTickerProviderStateMixin { |
| | | //1-搜索页面 2-建议搜索页面 3-结果展示页面 |
| | | int state = 1; |
| | | |
| | | TextEditingController? editingController; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | editingController = TextEditingController(); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Flex(direction: Axis.vertical, children: [ |
| | | //搜索框 |
| | | Container( |
| | | margin: EdgeInsets.fromLTRB(10, 35, 10, 11), |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.fromLTRB(8, 0, 8, 0), |
| | | height: 45, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.circular(10), |
| | | boxShadow: getViewShadow()), |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/map/icon_location_back.png", |
| | | height: 30, |
| | | ), |
| | | Container( |
| | | width: 10, |
| | | ), |
| | | Expanded( |
| | | child: TextField( |
| | | autofocus: false, |
| | | controller: editingController, |
| | | onChanged: (text) { |
| | | print(text); |
| | | setState(() { |
| | | if (text.isNotEmpty) |
| | | state = 2; |
| | | else |
| | | state = 1; |
| | | }); |
| | | }, |
| | | decoration: const InputDecoration( |
| | | focusedBorder: InputBorder.none, |
| | | border: InputBorder.none, |
| | | hintText: "地图上找位置", |
| | | hintStyle: TextStyle(fontSize: 14, color: Color(0xFFC4CDD1))), |
| | | )), |
| | | InkWell( |
| | | child: Container( |
| | | padding: EdgeInsets.only(right: 10), |
| | | child: Text( |
| | | "搜索", |
| | | style: TextStyle(color: ColorConstant.theme, fontSize: 15), |
| | | )), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | |
| | | Expanded(child: getContentView()) |
| | | ]); |
| | | } |
| | | |
| | | Widget getContentView() { |
| | | if (state == 1) |
| | | return getNotSearchView(); |
| | | else if (state == 2) { |
| | | return getSearchSuggestView(); |
| | | } else |
| | | return Container(); |
| | | } |
| | | |
| | | Widget getNotSearchView() { |
| | | return Column( |
| | | children: [ |
| | | Container( |
| | | padding: EdgeInsets.only(left: 7, right: 7, bottom: 7, top: 7), |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.only( |
| | | topRight: Radius.circular(15), topLeft: Radius.circular(15)), |
| | | boxShadow: getViewShadow(), |
| | | ), |
| | | child: Column(mainAxisSize: MainAxisSize.min, children: [ |
| | | //分类 |
| | | Container( |
| | | padding: |
| | | EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 9), |
| | | child: Row( |
| | | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| | | children: [ |
| | | getSugguestSearchType( |
| | | "酒店", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_hotel.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("酒店"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "餐馆", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_eat.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("餐馆"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "外卖", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_waimai.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("外卖"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "电影院", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_movie.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("电影院"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "景点", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_sense.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("景点"); |
| | | }), |
| | | ], |
| | | )), |
| | | //广告 |
| | | Container( |
| | | height: 210, |
| | | ), |
| | | ]), |
| | | ), |
| | | //分隔线 |
| | | Container( |
| | | height: 10, |
| | | color: Color(0xFFF0F0F0), |
| | | ), |
| | | Expanded( |
| | | child: Container( |
| | | color: Colors.white, |
| | | padding: EdgeInsets.only(left: 20, right: 20), |
| | | child: Column( |
| | | children: [getHistoryItem("融恒盈嘉中心-西门", "重庆市江北区", 0)], |
| | | ), |
| | | )) |
| | | ], |
| | | ); |
| | | } |
| | | |
| | | setSearchKey(String key) { |
| | | editingController!.text = key; |
| | | editingController!.selection = TextSelection( |
| | | baseOffset: key.length, extentOffset: editingController!.text.length); |
| | | startPOISearch(key); |
| | | } |
| | | |
| | | startPOISearch(String key) async { |
| | | BMFPoiNearbySearchOption poiNearbySearchOption = BMFPoiNearbySearchOption( |
| | | keywords: <String>[key], |
| | | location: BMFCoordinate(40.049557, 116.279295), |
| | | isRadiusLimit: false); |
| | | // 检索实例 |
| | | BMFPoiNearbySearch nearbySearch = BMFPoiNearbySearch(); |
| | | // 检索回调 |
| | | nearbySearch.onGetPoiNearbySearchResult( |
| | | callback: (BMFPoiSearchResult result, BMFSearchErrorCode errorCode) { |
| | | print("poi周边检索回调 errorCode = ${errorCode} result = ${result.toMap()}"); |
| | | // 解析reslut,具体参考demo |
| | | }); |
| | | // 发起检索 |
| | | bool flag = await nearbySearch.poiNearbySearch(poiNearbySearchOption); |
| | | } |
| | | |
| | | //建议搜索视图 |
| | | Widget getSearchSuggestView() { |
| | | return Container( |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.only( |
| | | topLeft: Radius.circular(15), topRight: Radius.circular(15)), |
| | | boxShadow: getViewShadow()), |
| | | padding: EdgeInsets.fromLTRB(20, 0, 20, 0), |
| | | child: ListView( |
| | | padding: const EdgeInsets.all(0), |
| | | children: [ |
| | | getHistoryItem("标题", "内容", 0), |
| | | getHistoryItem("标题", "内容", 1), |
| | | getHistoryItem("标题", "内容", 2), |
| | | getHistoryItem("标题", "内容", 3), |
| | | getHistoryItem("标题", "内容", 4), |
| | | getHistoryItem("标题", "内容", 5), |
| | | getHistoryItem("标题", "内容", 6), |
| | | getHistoryItem("标题", "内容", 7), |
| | | getHistoryItem("标题", "内容", 8), |
| | | getHistoryItem("标题", "内容", 9), |
| | | ], |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | //历史记录项目 |
| | | Widget getHistoryItem(String title, String content, int index) { |
| | | return InkWell( |
| | | onTap: () { |
| | | print("点击:$index"); |
| | | }, |
| | | child: Container( |
| | | height: 67, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | border: const Border( |
| | | bottom: BorderSide( |
| | | // 设置单侧边框的样式 |
| | | color: Color(0xFFF1F2F3), |
| | | width: 1, |
| | | style: BorderStyle.solid))), |
| | | child: Row( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | padding: EdgeInsets.only(top: 12, right: 9), |
| | | alignment: Alignment.topCenter, |
| | | child: Image.asset( |
| | | "assets/images/map/icon_location_location.png", |
| | | height: 16, |
| | | )), |
| | | Expanded( |
| | | child: Column( |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Text( |
| | | title, |
| | | softWrap: false, |
| | | overflow: TextOverflow.ellipsis, |
| | | style: |
| | | const TextStyle(color: Color(0xFF333333), fontSize: 13), |
| | | ), |
| | | Container( |
| | | height: 5, |
| | | ), |
| | | Text( |
| | | content, |
| | | style: |
| | | const TextStyle(color: Color(0xFF9DAAB3), fontSize: 11), |
| | | ), |
| | | ], |
| | | )), |
| | | Image.asset( |
| | | "assets/images/map/icon_location_position_input.png", |
| | | height: 20, |
| | | ) |
| | | ], |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | Widget getSugguestSearchType( |
| | | String title, Image icon, GestureTapCallback _onClick) { |
| | | return InkWell( |
| | | onTap: () { |
| | | _onClick(); |
| | | }, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | icon, |
| | | Container( |
| | | height: 5, |
| | | ), |
| | | Text( |
| | | title, |
| | | style: const TextStyle(color: Color(0xFF333333), fontSize: 11), |
| | | ) |
| | | ], |
| | | )); |
| | | } |
| | | } |
| | | |
| | | /********************位置详情********************/ |
| | | class PositionDetailPage extends StatefulWidget { |
| | | @override |
| | | _PositionDetailPageState createState() => _PositionDetailPageState(); |
| | | } |
| | | |
| | | class _PositionDetailPageState extends State<PositionDetailPage> |
| | | with SingleTickerProviderStateMixin { |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Container(); |
| | | } |
| | | } |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:locations/ui/main/travel_main.dart'; |
| | | import 'package:locations/ui/mine/advice.dart'; |
| | | import 'package:locations/ui/mine/permission.dart'; |
| | | import 'package:locations/ui/widget/dialog.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | |
| | |
| | | @override |
| | | void initState() { |
| | | _pages |
| | | ..add(KeepAliveWrapper(child: AdvicePage(title: "建议"))) |
| | | ..add(KeepAliveWrapper(child: MainTravelPage())) |
| | | ..add(KeepAliveWrapper(child: LocationPage(title: "定位"))) |
| | | ..add(KeepAliveWrapper(child: MinePage(title: "我的"))); |
| | | _tabController = |
| | | TabController(length: _pages.length, initialIndex: 1, vsync: this); |
| | | super.initState(); |
| | | |
| | | Timer(Duration(seconds: 4), () { |
| | | }); |
| | | } |
| | | |
| | | //设置选中的导航栏 |
| | |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | print("build"); |
| | | return Scaffold( |
| | | backgroundColor: Colors.white, |
| | | resizeToAvoidBottomInset: false, |
| | |
| | | void _login() { |
| | | print("登录"); |
| | | NavigatorUtil.navigateToNextPage(context, |
| | | MaterialPageRoute(builder: (context) { |
| | | return LoginPage(title: ""); |
| | | }), (data) {}); |
| | | LoginPage(title: ""), (data) {}); |
| | | |
| | | // setState(() { |
| | | // isLogin = !isLogin; |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:typed_data'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/rendering.dart'; |
| | | import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
| | | import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
| | | import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; |
| | | import 'package:locations/ui/map/location_search.dart'; |
| | | import 'package:locations/ui/map/travel.dart'; |
| | | import 'package:locations/ui/mine/advice.dart'; |
| | | import 'package:locations/ui/mine/permission.dart'; |
| | | import 'package:locations/ui/mine/settings.dart'; |
| | | import 'package:locations/ui/mine/share_to_friends.dart'; |
| | | import 'package:locations/ui/mine/try_functions.dart'; |
| | | import 'package:locations/ui/widget/button.dart'; |
| | | import 'package:locations/ui/widget/custom.dart'; |
| | | import 'package:locations/utils/location_util.dart'; |
| | | import 'package:locations/utils/map_util.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | |
| | | //控件阴影 |
| | | List<BoxShadow> getViewShadow() { |
| | | return [ |
| | | BoxShadow( |
| | | blurRadius: 6.5, |
| | | spreadRadius: 1, |
| | | color: Color(0x4D0E96FF), |
| | | ) |
| | | ]; |
| | | } |
| | | |
| | | class MainTravelPage extends StatefulWidget { |
| | | @override |
| | | _MainTravelPageState createState() => _MainTravelPageState(); |
| | | } |
| | | |
| | | class _MainTravelPageState extends State<MainTravelPage> |
| | | with SingleTickerProviderStateMixin { |
| | | BMFMapController? _mapController; |
| | | BMFMapOptions mapOptions = BMFMapOptions( |
| | | showMapScaleBar: false, |
| | | mapType: BMFMapType.Standard, |
| | | center: BMFCoordinate(39.917215, 116.380341), |
| | | mapScaleBarPosition: BMFPoint(0, 200), |
| | | zoomLevel: 12, |
| | | mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 200)); |
| | | |
| | | //选择地图类型索引(0-2D 1-3D 2-卫星) |
| | | int selectMapTypeIndex = 0; |
| | | |
| | | //是否正在录制轨迹 |
| | | bool travelRECIng = false; |
| | | List<BMFMarker> startMarkers = []; |
| | | |
| | | //用戶目前的位置 |
| | | BMFCoordinate? currentPosition; |
| | | |
| | | TextEditingController? editingController; |
| | | List<BMFPoiInfo>? suggestList; |
| | | |
| | | AnimationController? _animationController; |
| | | Animation<double>? _animation; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | editingController = TextEditingController(); |
| | | _animationController = new AnimationController( |
| | | duration: const Duration(milliseconds: 300), vsync: this); |
| | | final CurvedAnimation curve = |
| | | CurvedAnimation(parent: _animationController!, curve: Curves.easeIn); |
| | | _animation = Tween(begin: -240.0, end: 0.0).animate(curve) |
| | | ..addListener(() { |
| | | setState(() {}); |
| | | }); |
| | | } |
| | | |
| | | //获取地图视图 |
| | | Widget getMapView() { |
| | | return Container( |
| | | child: BMFMapWidget( |
| | | onBMFMapCreated: (controller) { |
| | | _mapController = controller; |
| | | _startLocation(); |
| | | drawLine(); |
| | | }, |
| | | mapOptions: mapOptions, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | void _startLocation() { |
| | | //启动定位 |
| | | LocationUtil.init(0); |
| | | LocationUtil.startLocation((map) { |
| | | double lat = map["latitude"] as double; |
| | | double lng = map["logitude"] as double; |
| | | _mapController!.setCenterCoordinate(BMFCoordinate(lng, lat), true); |
| | | }); |
| | | } |
| | | |
| | | void drawLine() { |
| | | List<BMFCoordinate> coordinates = []; |
| | | coordinates.add(BMFCoordinate(29.523624, 106.48916)); |
| | | coordinates.add(BMFCoordinate(29.535189, 106.502095)); |
| | | coordinates.add(BMFCoordinate(29.545747, 106.528829)); |
| | | coordinates.add(BMFCoordinate(29.556304, 106.545789)); |
| | | coordinates.add(BMFCoordinate(29.565101, 106.566486)); |
| | | coordinates.add(BMFCoordinate(29.568619, 106.588045)); |
| | | coordinates.add(BMFCoordinate(29.578922, 106.580284)); |
| | | coordinates.add(BMFCoordinate(29.587968, 106.575972)); |
| | | coordinates.add(BMFCoordinate(29.596762, 106.568211)); |
| | | coordinates.add(BMFCoordinate(29.607062, 106.567923)); |
| | | coordinates.add(BMFCoordinate(29.614096, 106.574247)); |
| | | MapUtil.drawLine(coordinates, ColorConstant.theme, _mapController); |
| | | MapUtil.getMapShowParams(coordinates).then((value) { |
| | | _mapController!.setCenterCoordinate(value!.center!, true); |
| | | _mapController!.setZoomTo(value.zoomLevel!.toDouble()); |
| | | }); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | resizeToAvoidBottomInset: false, |
| | | backgroundColor: Colors.white, |
| | | body: Stack(children: [ |
| | | getMapView(), |
| | | Flex(direction: Axis.vertical, children: [ |
| | | //搜索框 |
| | | Container( |
| | | margin: const EdgeInsets.fromLTRB(10, 35, 10, 11), |
| | | child: //----------搜索框-------- |
| | | Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, LocationSearchPage(), (data) {}); |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.fromLTRB(13, 0, 13, 0), |
| | | height: 45, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.circular(10), |
| | | boxShadow: getViewShadow()), |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/main/icon_location_search.png", |
| | | height: 19, |
| | | ), |
| | | Container( |
| | | width: 10, |
| | | ), |
| | | const Expanded( |
| | | child: Text("地图上找位置", |
| | | style: TextStyle( |
| | | fontSize: 14, |
| | | color: Color(0xFFC4CDD1)))) |
| | | ], |
| | | ), |
| | | ))), |
| | | ], |
| | | ), |
| | | ), |
| | | |
| | | Expanded(child: getContentView()) |
| | | ]), |
| | | //--------轨迹记录--------- |
| | | Positioned( |
| | | left: 10, |
| | | right: 10, |
| | | bottom: 0, |
| | | child: InkWell( |
| | | onTap: () { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | MyTravelPage( |
| | | title: '', |
| | | ), |
| | | (data) {}); |
| | | }, |
| | | child: Container( |
| | | padding: const EdgeInsets.fromLTRB(23, 15, 23, 30), |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: const BorderRadius.only( |
| | | topLeft: Radius.circular(10), |
| | | topRight: Radius.circular(10)), |
| | | boxShadow: getViewShadow(), |
| | | ), |
| | | child: Row( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/map/icon_travel_record.png", |
| | | width: 15, |
| | | ), |
| | | Container( |
| | | width: 9, |
| | | ), |
| | | const Text( |
| | | "轨迹记录", |
| | | style: TextStyle( |
| | | fontSize: 15, color: ColorConstant.theme), |
| | | ) |
| | | ], |
| | | )))), |
| | | |
| | | //-----地图类型选择----- |
| | | Positioned( |
| | | left: 10, |
| | | right: 10, |
| | | bottom: _animation!.value, |
| | | child: Container( |
| | | padding: const EdgeInsets.fromLTRB(23, 15, 23, 20), |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: const BorderRadius.only( |
| | | topLeft: Radius.circular(10), |
| | | topRight: Radius.circular(10)), |
| | | boxShadow: getViewShadow(), |
| | | ), |
| | | child: Column( |
| | | children: [ |
| | | Row( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/map/icon_map_type.png", |
| | | width: 21, |
| | | ), |
| | | Container( |
| | | width: 9, |
| | | ), |
| | | const Text( |
| | | "地图类型", |
| | | style: TextStyle( |
| | | fontSize: 15, color: ColorConstant.theme), |
| | | ) |
| | | ], |
| | | ), |
| | | Container( |
| | | height: 20, |
| | | ), |
| | | Row( |
| | | mainAxisAlignment: MainAxisAlignment.spaceAround, |
| | | children: [ |
| | | getMapTypeView("2D平面图", |
| | | "assets/images/map/icon_map_type_2d.png", 0), |
| | | getMapTypeView("3D俯视图", |
| | | "assets/images/map/icon_map_type_3d.png", 1), |
| | | getMapTypeView("卫星图", |
| | | "assets/images/map/icon_map_type_star.png", 2), |
| | | ], |
| | | ), |
| | | Container( |
| | | height: 20, |
| | | ), |
| | | MyOutlineButton( |
| | | "确定", |
| | | 10, |
| | | height: 40, |
| | | fontSize: 18, |
| | | onClick: () { |
| | | if (_animationController!.status == |
| | | AnimationStatus.completed) { |
| | | //动画执行完成 |
| | | _animationController!.reverse(); |
| | | } |
| | | }, |
| | | ) |
| | | ], |
| | | ))), |
| | | Positioned(top: 100, child: |
| | | PersonLocationMarker()) |
| | | ])); |
| | | } |
| | | |
| | | Widget getMapTypeView(String name, String imgPath, int index) { |
| | | return InkWell( |
| | | onTap: () { |
| | | setState(() { |
| | | selectMapTypeIndex = index; |
| | | }); |
| | | if (index == 2) { |
| | | _mapController?.updateMapOptions( |
| | | BMFMapOptions(mapType: BMFMapType.Satellite)); |
| | | } else if (index == 1) { |
| | | _mapController?.updateMapOptions(BMFMapOptions( |
| | | mapType: BMFMapType.Standard, |
| | | buildingsEnabled: true, |
| | | baseIndoorMapEnabled: true, |
| | | overlookEnabled: true)); |
| | | _mapController?.showBaseIndoorMap(true); |
| | | } else if (index == 0) { |
| | | _mapController?.updateMapOptions(BMFMapOptions( |
| | | mapType: BMFMapType.Standard, |
| | | buildingsEnabled: false, |
| | | baseIndoorMapEnabled: false)); |
| | | } |
| | | }, |
| | | child: Column( |
| | | children: [ |
| | | ClipRRect( |
| | | borderRadius: BorderRadius.circular(23), |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | color: selectMapTypeIndex == index |
| | | ? ColorConstant.theme |
| | | : Color(0xFF9DAAB3), |
| | | width: 71, |
| | | height: 71, |
| | | child: Image.asset( |
| | | imgPath, |
| | | width: 65, |
| | | height: 65, |
| | | ), |
| | | )), |
| | | Text( |
| | | name, |
| | | style: TextStyle( |
| | | fontSize: 14, |
| | | color: index == selectMapTypeIndex |
| | | ? ColorConstant.theme |
| | | : Color(0xFF9DAAB3)), |
| | | ) |
| | | ], |
| | | )); |
| | | } |
| | | |
| | | Widget getContentView() { |
| | | //------------工具栏----------- |
| | | return Stack(children: [ |
| | | Positioned( |
| | | right: 10, |
| | | top: 10, |
| | | child: Container( |
| | | padding: EdgeInsets.only(top: 13, bottom: 13), |
| | | width: 43, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, borderRadius: BorderRadius.circular(7.5)), |
| | | child: Column( |
| | | children: [ |
| | | InkWell( |
| | | onTap: () { |
| | | if (!travelRECIng) { |
| | | currentPosition = BMFCoordinate(29.523624, 106.48916); |
| | | if (currentPosition == null) { |
| | | Fluttertoast.showToast(msg: "定位失败,请重新定位"); |
| | | return; |
| | | } |
| | | MapUtil.addMarker(_mapController, currentPosition!, |
| | | "assets/images/map/icon_travel_start.png", |
| | | zIndex: 1) |
| | | .then((value) { |
| | | startMarkers.add(value); |
| | | }); |
| | | MapUtil.addMarker(_mapController, currentPosition!, |
| | | "assets/images/map/icon_travel_start_1.png", |
| | | offset: BMFPoint(0, 38)) |
| | | .then((value) { |
| | | startMarkers.add(value); |
| | | }); |
| | | } else { |
| | | //结束录制 |
| | | if (startMarkers.length > 0) |
| | | MapUtil.removeMarkers(_mapController, startMarkers); |
| | | } |
| | | |
| | | setState(() { |
| | | travelRECIng = !travelRECIng; |
| | | }); |
| | | }, |
| | | child: Column( |
| | | children: [ |
| | | Image.asset( |
| | | travelRECIng |
| | | ? "assets/images/map/icon_rec_location_ing.png" |
| | | : "assets/images/map/icon_rec_location.png", |
| | | width: 21, |
| | | ), |
| | | Container( |
| | | height: 2, |
| | | ), |
| | | Text(travelRECIng ? "录制中.." : "录制轨迹", |
| | | style: TextStyle( |
| | | fontSize: 7, |
| | | color: travelRECIng |
| | | ? Color(0xFFFF1F35) |
| | | : Color(0xFF9DAAB3))) |
| | | ], |
| | | ), |
| | | ), |
| | | Container( |
| | | height: 14, |
| | | ), |
| | | InkWell( |
| | | onTap: () { |
| | | if (_animationController!.status == |
| | | AnimationStatus.dismissed) { |
| | | _animationController!.forward(); |
| | | } else if (_animationController!.status == |
| | | AnimationStatus.completed) { |
| | | _animationController!.reverse(); |
| | | } |
| | | }, |
| | | child: Column( |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/map/icon_select_map_type.png", |
| | | width: 21, |
| | | ), |
| | | Container( |
| | | height: 2, |
| | | ), |
| | | Text("选择图层", |
| | | style: |
| | | TextStyle(fontSize: 7, color: Color(0xFF9DAAB3))) |
| | | ], |
| | | ), |
| | | ), |
| | | Container( |
| | | height: 14, |
| | | ), |
| | | InkWell( |
| | | onTap: () { |
| | | _startLocation(); |
| | | }, |
| | | child: Column( |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/map/icon_current_position.png", |
| | | width: 21, |
| | | ), |
| | | Container( |
| | | height: 2, |
| | | ), |
| | | Text("我的位置", |
| | | style: |
| | | TextStyle(fontSize: 7, color: Color(0xFF9DAAB3))) |
| | | ], |
| | | ), |
| | | ) |
| | | ], |
| | | ), |
| | | )), |
| | | ]); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:typed_data'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/rendering.dart'; |
| | | import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
| | | import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
| | | import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; |
| | | import 'package:locations/ui/mine/advice.dart'; |
| | | import 'package:locations/ui/mine/permission.dart'; |
| | | import 'package:locations/ui/mine/settings.dart'; |
| | | import 'package:locations/ui/mine/share_to_friends.dart'; |
| | | import 'package:locations/ui/mine/try_functions.dart'; |
| | | import 'package:locations/ui/widget/button.dart'; |
| | | import 'package:locations/utils/location_util.dart'; |
| | | import 'package:locations/utils/map_util.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | |
| | | //控件阴影 |
| | | List<BoxShadow> getViewShadow() { |
| | | return [ |
| | | BoxShadow( |
| | | blurRadius: 6.5, |
| | | spreadRadius: 1, |
| | | color: Color(0x4D0E96FF), |
| | | ) |
| | | ]; |
| | | } |
| | | |
| | | /********************POI搜索********************/ |
| | | class LocationSearchPage extends StatefulWidget { |
| | | @override |
| | | _LocationSearchPageState createState() => _LocationSearchPageState(); |
| | | } |
| | | |
| | | class _LocationSearchPageState extends State<LocationSearchPage> |
| | | with SingleTickerProviderStateMixin { |
| | | BMFMapController? _mapController; |
| | | BMFMapOptions mapOptions = BMFMapOptions( |
| | | showMapScaleBar: false, |
| | | mapType: BMFMapType.Standard, |
| | | center: BMFCoordinate(39.917215, 116.380341), |
| | | mapScaleBarPosition: BMFPoint(0, 200), |
| | | zoomLevel: 12, |
| | | mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 200)); |
| | | |
| | | //1-搜索页面 2-建议搜索页面 3-结果展示页面 |
| | | int state = 1; |
| | | |
| | | TextEditingController? editingController; |
| | | List<BMFPoiInfo>? suggestList; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | editingController = TextEditingController(); |
| | | } |
| | | |
| | | //获取地图视图 |
| | | Widget getMapView() { |
| | | return Container( |
| | | child: BMFMapWidget( |
| | | onBMFMapCreated: (controller) { |
| | | _mapController = controller; |
| | | //启动定位 |
| | | LocationUtil.init(0); |
| | | LocationUtil.startLocation((map) { |
| | | double lat = map["latitude"] as double; |
| | | double lng = map["logitude"] as double; |
| | | _mapController!.setCenterCoordinate(BMFCoordinate(lng,lat), true); |
| | | }); |
| | | }, |
| | | mapOptions: mapOptions, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | resizeToAvoidBottomInset: false, |
| | | backgroundColor: Colors.white, |
| | | body: Stack(children: [ |
| | | getMapView(), |
| | | Flex(direction: Axis.vertical, children: [ |
| | | //搜索框 |
| | | Container( |
| | | margin: const EdgeInsets.fromLTRB(10, 35, 10, 11), |
| | | alignment: Alignment.center, |
| | | padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), |
| | | height: 45, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.circular(10), |
| | | boxShadow: getViewShadow()), |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | InkWell( |
| | | onTap: () { |
| | | Navigator.of(context).pop(); |
| | | }, |
| | | child: Image.asset( |
| | | "assets/images/map/icon_location_back.png", |
| | | height: 30, |
| | | )), |
| | | Container( |
| | | width: 10, |
| | | ), |
| | | Expanded( |
| | | child: TextField( |
| | | autofocus: false, |
| | | controller: editingController, |
| | | onChanged: (text) { |
| | | print(text); |
| | | // setState(() { |
| | | // if (text.isNotEmpty) |
| | | // state = 2; |
| | | // else |
| | | // state = 1; |
| | | // }); |
| | | startPOISearch(text); |
| | | }, |
| | | decoration: const InputDecoration( |
| | | focusedBorder: InputBorder.none, |
| | | border: InputBorder.none, |
| | | hintText: "地图上找位置", |
| | | hintStyle: |
| | | TextStyle(fontSize: 14, color: Color(0xFFC4CDD1))), |
| | | )), |
| | | InkWell( |
| | | child: Container( |
| | | padding: const EdgeInsets.only(right: 10), |
| | | child: const Text( |
| | | "搜索", |
| | | style: TextStyle( |
| | | color: ColorConstant.theme, fontSize: 15), |
| | | )), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | |
| | | Expanded(child: getContentView()) |
| | | ]) |
| | | ])); |
| | | } |
| | | |
| | | Widget getContentView() { |
| | | if (state == 1) |
| | | return getNotSearchView(); |
| | | else if (state == 2) { |
| | | return getSearchSuggestView(); |
| | | } else |
| | | return Container(); |
| | | } |
| | | |
| | | Widget getNotSearchView() { |
| | | return Column( |
| | | children: [ |
| | | Container( |
| | | padding: const EdgeInsets.only(left: 7, right: 7, bottom: 7, top: 7), |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: const BorderRadius.only( |
| | | topRight: Radius.circular(15), topLeft: Radius.circular(15)), |
| | | boxShadow: getViewShadow(), |
| | | ), |
| | | child: Column(mainAxisSize: MainAxisSize.min, children: [ |
| | | //分类 |
| | | Container( |
| | | padding: const EdgeInsets.only( |
| | | left: 20, right: 20, bottom: 15, top: 9), |
| | | child: Row( |
| | | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| | | children: [ |
| | | getSugguestSearchType( |
| | | "酒店", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_hotel.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("酒店"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "餐馆", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_eat.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("餐馆"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "外卖", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_waimai.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("外卖"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "电影院", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_movie.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("电影院"); |
| | | }), |
| | | getSugguestSearchType( |
| | | "景点", |
| | | Image.asset( |
| | | "assets/images/map/icon_location_search_type_sense.png", |
| | | height: 34, |
| | | ), () { |
| | | setSearchKey("景点"); |
| | | }), |
| | | ], |
| | | )), |
| | | //广告 |
| | | Container( |
| | | height: 210, |
| | | ), |
| | | ]), |
| | | ), |
| | | //分隔线 |
| | | Container( |
| | | height: 10, |
| | | color: const Color(0xFFF0F0F0), |
| | | ), |
| | | Expanded( |
| | | child: Container( |
| | | color: Colors.white, |
| | | padding: const EdgeInsets.only(left: 20, right: 20), |
| | | child: Column( |
| | | children: [getHistoryItem("融恒盈嘉中心-西门", "重庆市江北区", 0)], |
| | | ), |
| | | )) |
| | | ], |
| | | ); |
| | | } |
| | | |
| | | setSearchKey(String key) { |
| | | editingController!.text = key; |
| | | editingController!.selection = TextSelection( |
| | | baseOffset: key.length, extentOffset: editingController!.text.length); |
| | | startPOISearch(key); |
| | | } |
| | | |
| | | startPOISearch(String key) async { |
| | | setState(() { |
| | | suggestList = null; |
| | | if (key.isNotEmpty) |
| | | state = 2; |
| | | else |
| | | state = 1; |
| | | }); |
| | | |
| | | print("startPOISearch-$key"); |
| | | BMFPoiNearbySearchOption poiNearbySearchOption = BMFPoiNearbySearchOption( |
| | | keywords: <String>[key], |
| | | location: BMFCoordinate(40.049557, 116.279295), |
| | | isRadiusLimit: false); |
| | | |
| | | BMFPoiNearbySearch nearbySearch = BMFPoiNearbySearch(); |
| | | nearbySearch.onGetPoiNearbySearchResult( |
| | | callback: (BMFPoiSearchResult result, BMFSearchErrorCode errorCode) { |
| | | setState(() { |
| | | suggestList = result.poiInfoList; |
| | | }); |
| | | }); |
| | | bool flag = await nearbySearch.poiNearbySearch(poiNearbySearchOption); |
| | | |
| | | // BMFSuggestionSearchOption suggestionSearchOption = |
| | | // BMFSuggestionSearchOption(keyword: key,cityLimit: false); |
| | | // BMFSuggestionSearch suggestionSearch = BMFSuggestionSearch(); |
| | | // suggestionSearch.onGetSuggestSearchResult(callback: |
| | | // (BMFSuggestionSearchResult result, BMFSearchErrorCode errorCode) { |
| | | // print("result:$result errorCode:$errorCode"); |
| | | // setState(() { |
| | | // suggestList = result.suggestionList; |
| | | // }); |
| | | // }); |
| | | // bool flag = await suggestionSearch.suggestionSearch(suggestionSearchOption); |
| | | |
| | | print("结束$flag"); |
| | | } |
| | | |
| | | //建议搜索视图 |
| | | Widget getSearchSuggestView() { |
| | | return Container( |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.only( |
| | | topLeft: Radius.circular(15), topRight: Radius.circular(15)), |
| | | boxShadow: getViewShadow()), |
| | | padding: EdgeInsets.fromLTRB(20, 0, 20, 0), |
| | | child: ListView.builder( |
| | | itemBuilder: (BuildContext context, int index) { |
| | | if (suggestList == null) { |
| | | return Container( |
| | | margin: EdgeInsets.only(top: 50), |
| | | alignment: Alignment.center, |
| | | height: 50, |
| | | width: 50, |
| | | child: CircularProgressIndicator(strokeWidth: 3.0)); |
| | | } else if (suggestList!.length == 0) { |
| | | return Container( |
| | | alignment: Alignment.center, child: Text("暂无数据")); |
| | | } else { |
| | | return getHistoryItem(suggestList![index].name!, |
| | | suggestList![index].address!, index); |
| | | } |
| | | }, |
| | | itemCount: suggestList != null ? suggestList!.length : 1, |
| | | padding: const EdgeInsets.all(0), |
| | | )); |
| | | } |
| | | |
| | | //历史记录项目 |
| | | Widget getHistoryItem(String title, String content, int index) { |
| | | return InkWell( |
| | | onTap: () { |
| | | print("点击:$index"); |
| | | }, |
| | | child: Container( |
| | | height: 67, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | border: const Border( |
| | | bottom: BorderSide( |
| | | // 设置单侧边框的样式 |
| | | color: Color(0xFFF1F2F3), |
| | | width: 1, |
| | | style: BorderStyle.solid))), |
| | | child: Row( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | padding: EdgeInsets.only(top: 12, right: 9), |
| | | alignment: Alignment.topCenter, |
| | | child: Image.asset( |
| | | "assets/images/map/icon_location_location.png", |
| | | height: 16, |
| | | )), |
| | | Expanded( |
| | | child: Column( |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Text( |
| | | title, |
| | | softWrap: false, |
| | | overflow: TextOverflow.ellipsis, |
| | | style: |
| | | const TextStyle(color: Color(0xFF333333), fontSize: 13), |
| | | ), |
| | | Container( |
| | | height: 5, |
| | | ), |
| | | Text( |
| | | content, |
| | | style: |
| | | const TextStyle(color: Color(0xFF9DAAB3), fontSize: 11), |
| | | ), |
| | | ], |
| | | )), |
| | | Image.asset( |
| | | "assets/images/map/icon_location_position_input.png", |
| | | height: 20, |
| | | ) |
| | | ], |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | Widget getSugguestSearchType( |
| | | String title, Image icon, GestureTapCallback _onClick) { |
| | | return InkWell( |
| | | onTap: () { |
| | | _onClick(); |
| | | }, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | icon, |
| | | Container( |
| | | height: 5, |
| | | ), |
| | | Text( |
| | | title, |
| | | style: const TextStyle(color: Color(0xFF333333), fontSize: 11), |
| | | ) |
| | | ], |
| | | )); |
| | | } |
| | | } |
| | | |
| | | /********************位置详情********************/ |
| | | class PositionDetailPage extends StatefulWidget { |
| | | @override |
| | | _PositionDetailPageState createState() => _PositionDetailPageState(); |
| | | } |
| | | |
| | | class _PositionDetailPageState extends State<PositionDetailPage> |
| | | with SingleTickerProviderStateMixin { |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Container(); |
| | | } |
| | | } |
| | |
| | | child: InkWell( |
| | | onTap: () { |
| | | NavigatorUtil.navigateToNextPage(context, |
| | | MaterialPageRoute(builder: (context) { |
| | | return MyTravelMapPage(title: ""); |
| | | }), (data) {}); |
| | | MyTravelMapPage(title: ""), (data) {}); |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:flutter_html/flutter_html.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; |
| | | import 'package:html/dom.dart' as dom; |
| | | import 'package:locations/ui/widget/button.dart'; |
| | | import 'package:locations/ui/widget/nav.dart'; |
| | | import 'package:locations/utils/pageutils.dart'; |
| | | import 'package:locations/utils/string_util.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; |
| | | |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | import 'package:locations/utils/user_util.dart'; |
| | | import 'advice_submit.dart'; |
| | | import 'package:html/dom.dart' as dom; |
| | | |
| | | void main() { |
| | | runApp(MyApp()); |
| | |
| | | String code = ""; |
| | | Timer? timer; |
| | | |
| | | |
| | | //重新发送验证码倒计时 |
| | | int? reSendSMSTimeLeft; |
| | | |
| | |
| | | int errCode = res.errCode; |
| | | if (errCode == 0) { |
| | | String? code = res.code; |
| | | //把微信登录返回的code传给后台,剩下的事就交给后台处理 |
| | | //TODO 把微信登录返回的code传给后台,剩下的事就交给后台处理 |
| | | } else if (errCode == -4) { |
| | | //showToast("用户拒绝授权"); |
| | | } else if (errCode == -2) { |
| | |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | //阿里云一键登录 |
| | | static const messageChannel = const BasicMessageChannel( |
| | | 'AliyunPhoneNumberAuth', StandardMessageCodec()); |
| | | void aliyunOneKeyLogin() async { |
| | | Map value = await messageChannel.send({ |
| | | "method": "init", |
| | | "secret": Constant.ALIYUN_AUTH_SECRETINFO, |
| | | "privacy": Constant.PRIVACY_URL, |
| | | "protocol": Constant.PROTOCOL_URL |
| | | }) as Map; |
| | | if (value["code"] == 0) { |
| | | value = await messageChannel.send({"method": "checkEnv"}) as Map; |
| | | if (value["code"] == 0) { |
| | | value = await messageChannel.send({"method": "startLogin"}) as Map; |
| | | if (value["code"] == 0) { |
| | | Fluttertoast.showToast(msg: "token:" + value["token"]); |
| | | } else if (value["code"] == 700000) { |
| | | Fluttertoast.showToast(msg: "取消登录了"); |
| | | } |
| | | } else { |
| | | Fluttertoast.showToast(msg: value["msg"]); |
| | | setState(() { |
| | | oneKeyLogin = false; |
| | | }); |
| | | } |
| | | } else { |
| | | Fluttertoast.showToast(msg: value["msg"]); |
| | | } |
| | | } |
| | | |
| | | void qqLogin() async { |
| | | Map value = await UserUtil.loginQQ(); |
| | | } |
| | | |
| | | @override |
| | |
| | | child: Container( |
| | | child: Html( |
| | | data: |
| | | "<p>登录即表明同意<a href='http://www.baidu.com'> 用户协议 </a>和<a href='http://www.baidu.com'> 隐私政策 </a></p>", |
| | | "<p>登录即表明同意<a href='${Constant.PROTOCOL_URL}'> 用户协议 </a>和<a href='${Constant.PRIVACY_URL}'> 隐私政策 </a></p>", |
| | | style: { |
| | | "a": Style( |
| | | textDecoration: TextDecoration.none, |
| | |
| | | 10, |
| | | height: 45, |
| | | fontSize: 17, |
| | | onClick: () {}, |
| | | onClick: () { |
| | | aliyunOneKeyLogin(); |
| | | }, |
| | | ) |
| | | ])) |
| | | : Column( |
| | |
| | | textAlign: TextAlign.start, |
| | | keyboardType: TextInputType.phone, |
| | | controller: phoneController, |
| | | maxLength: 11, |
| | | decoration: InputDecoration( |
| | | counterText: "", |
| | | hintText: "请输入手机号", |
| | | hintStyle: |
| | | TextStyle(color: Color(0xFFCCCCCC), fontSize: 17), |
| | |
| | | textAlign: TextAlign.start, |
| | | keyboardType: TextInputType.phone, |
| | | controller: codeController, |
| | | decoration: InputDecoration( |
| | | maxLength: 8, |
| | | decoration: const InputDecoration( |
| | | counterText: "", |
| | | hintText: "请输入验证码", |
| | | hintStyle: |
| | | TextStyle(color: Color(0xFFCCCCCC), fontSize: 17), |
| | |
| | | .toString(), |
| | | 10, |
| | | height: 34, |
| | | padding: EdgeInsets.fromLTRB(10, 0, 10, 0), |
| | | enable: (reSendSMSTimeLeft! < 1), |
| | | padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), |
| | | enable: (reSendSMSTimeLeft! < 1 && |
| | | StringUtil.isMobile(phoneController!.value.text)), |
| | | onClick: () { |
| | | if (reSendSMSTimeLeft! > 0) { |
| | | if (!(reSendSMSTimeLeft! < 1 && |
| | | StringUtil.isMobile(phoneController!.value.text))) { |
| | | return; |
| | | } |
| | | setState(() { |
| | |
| | | "获取短信验证码", |
| | | 10, |
| | | height: 45, |
| | | color: phone.length == 11 |
| | | ? const Color(0xFFFF2B4B) |
| | | : const Color(0xFFCBCBCB), |
| | | color: const Color(0xFFFF2B4B), |
| | | fontSize: 17, |
| | | onClick: () {}, |
| | | enable: StringUtil.isMobile(phoneController!.value.text) && |
| | | codeController!.value.text.length >= 4, |
| | | onClick: () { |
| | | if (!(StringUtil.isMobile(phoneController!.value.text) && |
| | | codeController!.value.text.length >= 4)) { |
| | | return; |
| | | } |
| | | }, |
| | | ), |
| | | ], |
| | | ); |
| | |
| | | setState(() { |
| | | oneKeyLogin = !oneKeyLogin; |
| | | }); |
| | | } else if (name == "QQ登录") { |
| | | qqLogin(); |
| | | } else if (name == "微信登录") { |
| | | UserUtil.loginWX(); |
| | | } |
| | | }, |
| | | child: Container( |
| | |
| | | rightText: "紧急联系人", |
| | | rightClick: () { |
| | | NavigatorUtil.navigateToNextPage(context, |
| | | MaterialPageRoute(builder: (context) { |
| | | return SOSContactPage(title: ""); |
| | | }), (data) {}); |
| | | SOSContactPage(title: ""), (data) {}); |
| | | }, |
| | | backIcon: Image.asset( |
| | | "assets/images/common/icon_sos_back.png", |
New file |
| | |
| | | import 'dart:typed_data'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/rendering.dart'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | |
| | | ///对widget截图 |
| | | |
| | | |
| | | class CaptureWidget extends StatelessWidget { |
| | | //截图组件 |
| | | GlobalKey rootWidgetKey = GlobalKey(); |
| | | final Widget widget; |
| | | |
| | | CaptureWidget(this.widget); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return RepaintBoundary(key: rootWidgetKey, child: widget); |
| | | } |
| | | |
| | | Future<Uint8List?> capturePng() async { |
| | | try { |
| | | RenderRepaintBoundary? boundary = rootWidgetKey.currentContext! |
| | | .findRenderObject() as RenderRepaintBoundary; |
| | | var image = await boundary.toImage(pixelRatio: 3.0); |
| | | ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); |
| | | Uint8List pngBytes = byteData!.buffer.asUint8List(); |
| | | return pngBytes; |
| | | } catch (e) {} |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:locations/utils/ui_constant.dart'; |
| | | import 'dart:math' as math; |
| | | |
| | | //三角形 |
| | | class TrianglePainter extends CustomPainter { |
| | | final Color color; |
| | | Paint? _paint; //画笔 |
| | | Path? _path; //绘制路径 |
| | | |
| | | TrianglePainter(this.color) { |
| | | _paint = Paint() |
| | | ..strokeWidth = 1.0 //线宽 |
| | | ..color = color |
| | | ..isAntiAlias = true; |
| | | _path = Path(); |
| | | } |
| | | |
| | | @override |
| | | void paint(Canvas canvas, Size size) { |
| | | final baseX = size.width * 0.5; |
| | | final baseY = size.height * 0.5; |
| | | //起点 |
| | | // _path!.moveTo(baseX - 0.86 * baseX, 0.5 * baseY); |
| | | // _path!.lineTo(baseY, 1.5 * baseY); |
| | | // _path!.lineTo(baseX + 0.86 * baseX, 0.5 * baseY); |
| | | |
| | | _path!.moveTo(size.width / 2, 0); |
| | | _path!.lineTo(size.width, size.height); |
| | | _path!.lineTo(0, size.height); |
| | | canvas.drawPath(_path!, _paint!); |
| | | } |
| | | |
| | | @override |
| | | bool shouldRepaint(CustomPainter oldDelegate) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | ///用户位置marker |
| | | class PersonLocationMarker extends StatelessWidget { |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Container( |
| | | width: 70, |
| | | height: 70, |
| | | child: Stack( |
| | | alignment: Alignment.center, |
| | | children: [ |
| | | Positioned( |
| | | top: 0, |
| | | child: Transform.rotate( |
| | | angle: -math.pi / 2, |
| | | child: Container( |
| | | height: 69.28, |
| | | width: 69.28, |
| | | child: Stack(alignment: Alignment.topCenter, children: [ |
| | | CustomPaint( |
| | | size: Size(40, 34.64), |
| | | painter: TrianglePainter(ColorConstant.theme), |
| | | ) |
| | | ])), |
| | | )), |
| | | Container( |
| | | width: 42, |
| | | height: 42, |
| | | padding: EdgeInsets.all(3), |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, borderRadius: BorderRadius.circular(40)), |
| | | child: Container( |
| | | width: 42 - 3 * 2, |
| | | height: 42 - 3 * 2, |
| | | padding: EdgeInsets.all(2), |
| | | decoration: BoxDecoration( |
| | | color: ColorConstant.theme, |
| | | borderRadius: BorderRadius.circular(40)), |
| | | child: Image.asset( |
| | | "assets/images/mine/icon_mine_default_portrait.png", |
| | | ), |
| | | ), |
| | | ), |
| | | ], |
| | | )); |
| | | } |
| | | } |
| | |
| | | import 'package:flutter_html/flutter_html.dart'; |
| | | import 'package:html/dom.dart' as dom; |
| | | |
| | | //通用弹框 |
| | | class NotifyDialog extends Dialog { |
| | | BuildContext? context; |
| | | final String title; |
| | |
| | | } |
| | | } |
| | | |
| | | ///权限弹框 |
| | | class PermissionNotifyDialog extends Dialog { |
| | | final GestureTapCallback onOpen; |
| | | |
| | |
| | | height: 30, |
| | | ), |
| | | getPermissionItem( |
| | | title: "定位", |
| | | title: "存储", |
| | | content: "缓存图片和视频,降低流量消耗", |
| | | icon: Image.asset( |
| | | "assets/images/common/icon_permission_notify_save.png", |
| | | width: 26, |
| | | )), |
| | | Container( |
| | | height: 30, |
| | | ), |
| | | getPermissionItem( |
| | | title: "位置", |
| | | content: "定位用户", |
| | | icon: Image.asset( |
| | | "assets/images/common/icon_permission_notify_location.png", |
| | | width: 26, |
| | |
| | | ); |
| | | } |
| | | } |
| | | |
| | | ///邀请定位 |
| | | class RequireLocationDialog extends Dialog { |
| | | BuildContext? context; |
| | | final String phone; |
| | | final GestureTapCallback onCancel; |
| | | final GestureTapCallback onSure; |
| | | |
| | | RequireLocationDialog(this.phone, this.onCancel, this.onSure); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | double width = MediaQuery.of(context).size.width; |
| | | double dialogWidth = width * 4 / 5; |
| | | print("屏幕宽:$width"); |
| | | |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Container( |
| | | decoration: const BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.circular(15)), |
| | | color: Colors.white), |
| | | alignment: Alignment.topCenter, |
| | | height: 380, |
| | | width: dialogWidth, |
| | | child: Flex( |
| | | mainAxisAlignment: MainAxisAlignment.start, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | //-------标题区域-------- |
| | | Image.asset( |
| | | "assets/images/common/ic_require_location_top.png"), |
| | | //-------内容区域-------- |
| | | Expanded( |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.fromLTRB(15, 5, 15, 5), |
| | | child: Column( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | height: 15, |
| | | ), |
| | | const Text( |
| | | "位置共享授权", |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), fontSize: 17), |
| | | ), |
| | | Container( |
| | | height: 49, |
| | | ), |
| | | Row( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/images/common/icon_require_location_phone.png", |
| | | height: 15, |
| | | ), |
| | | Container( |
| | | width: 10, |
| | | ), |
| | | Text( |
| | | phone, |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), |
| | | fontSize: 18), |
| | | ), |
| | | ], |
| | | ), |
| | | Container( |
| | | height: 10, |
| | | ), |
| | | const Text( |
| | | "该手机号用户请求与你进行位置共享。", |
| | | style: TextStyle( |
| | | color: Color(0xFF666666), fontSize: 15), |
| | | ), |
| | | Container( |
| | | height: 10, |
| | | ), |
| | | const Text( |
| | | "温馨提醒:你同意后可在定位人列表中删除", |
| | | style: TextStyle( |
| | | color: Color(0xFFA0A0A0), fontSize: 12), |
| | | ), |
| | | ], |
| | | ))), |
| | | |
| | | //------按钮区域-------- |
| | | Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | onCancel(); |
| | | }, |
| | | child: Container( |
| | | margin: EdgeInsets.fromLTRB(15, 0, 6, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | border: Border.all(color: Color(0xFF0E96FF)), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | "不同意", |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), fontSize: 18), |
| | | ), |
| | | ), |
| | | )), |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | onSure(); |
| | | }, |
| | | child: Container( |
| | | margin: EdgeInsets.fromLTRB(6, 0, 15, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | color: Color(0xFF0E96FF), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | "同意", |
| | | style: TextStyle( |
| | | color: Colors.white, fontSize: 18), |
| | | ), |
| | | ), |
| | | )) |
| | | ], |
| | | ) |
| | | ], |
| | | ), |
| | | )))); |
| | | } |
| | | } |
| | | |
| | | ///ListView弹框 |
| | | class ListViewDialog extends Dialog { |
| | | BuildContext? context; |
| | | final ListView listView; |
| | | final GestureTapCallback onClose; |
| | | final double maxHeight; |
| | | |
| | | ListViewDialog(this.listView, this.onClose, {this.maxHeight = 420}); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | double width = MediaQuery.of(context).size.width; |
| | | double dialogWidth = width - 20; |
| | | print("屏幕宽:$width"); |
| | | |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Column( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | mainAxisSize:MainAxisSize.min, |
| | | children: [ |
| | | ClipRRect( |
| | | borderRadius: BorderRadius.circular(10), |
| | | child: Container( |
| | | constraints: BoxConstraints(maxHeight: maxHeight), |
| | | color: Colors.white, |
| | | alignment: Alignment.topCenter, |
| | | width: dialogWidth, |
| | | child: listView, |
| | | )), |
| | | Container( |
| | | height: 20, |
| | | ), |
| | | InkWell( |
| | | child: Image.asset( |
| | | "assets/images/common/icon_dialog_close.png", |
| | | height: 32, |
| | | width: 32, |
| | | ), |
| | | onTap: () { |
| | | onClose(); |
| | | }, |
| | | ), |
| | | ])))); |
| | | } |
| | | } |
| | |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart'; |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | import 'package:flutter_baidu_mapapi_base/src/map/bmf_map_sdk.dart'; |
| | | import 'package:flutter_baidu_mapapi_base/src/map/bmf_types.dart'; |
| | | |
| | | class AppUtil { |
| | | //初始化应用 |
| | | static Future<bool> initApp(BuildContext context) async { |
| | | print("initApp"); |
| | | await registerWxApi( |
| | | appId: "wxd930ea5d5a228f5f", |
| | | universalLink: "https://your.univerallink.com/link/"); |
| | | await registerWxApi( |
| | | appId: "wxd930ea5d5a228f5f", |
| | | universalLink: "https://your.univerallink.com/link/"); |
| | | |
| | | |
| | | //地图 |
| | | if (Platform.isIOS) { |
| | | BMFMapSDK.setApiKeyAndCoordType( |
| | | '请输入百度开放平台申请的iOS端API KEY', BMF_COORD_TYPE.BD09LL); |
| | | } else if (Platform.isAndroid) { |
| | | // Android 目前不支持接口设置Apikey, |
| | | // 请在主工程的Manifest文件里设置,详细配置方法请参考[https://lbs.baidu.com/ 官网][https://lbs.baidu.com/)demo |
| | | BMFMapSDK.setCoordType(BMF_COORD_TYPE.BD09LL); |
| | | } |
| | | // |
| | | await _initNativeApp(); |
| | | //初始化应用 |
| | | return true; |
| | | } |
| | | |
| | | //本地应用初始化 |
| | | static _initNativeApp() async { |
| | | if (Platform.isAndroid) { |
| | | const platform = MethodChannel("com.yeshi.location/init"); //分析1 |
| | | try { |
| | | await platform.invokeMethod("initApp"); //分析2 |
| | | } on PlatformException catch (e) { |
| | | print(e.toString()); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import 'package:flutter_bmflocation/bdmap_location_flutter_plugin.dart'; |
| | | import 'package:flutter_bmflocation/flutter_baidu_location.dart'; |
| | | import 'package:flutter_bmflocation/flutter_baidu_location_android_option.dart'; |
| | | import 'package:flutter_bmflocation/flutter_baidu_location_ios_option.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | |
| | | typedef OnLocationCallback = void Function(Map map); |
| | | |
| | | class LocationUtil { |
| | | static LocationFlutterPlugin? _locationFlutterPlugin=LocationFlutterPlugin(); |
| | | |
| | | static Map _getAndroidOption(int scanspan) { |
| | | BaiduLocationAndroidOption androidOption = new BaiduLocationAndroidOption(); |
| | | androidOption.setCoorType("bd09ll"); |
| | | |
| | | /// 可选,设置返回经纬度坐标类型,默认gcj02 |
| | | /// gcj02:国测局坐标; |
| | | /// bd09ll:百度经纬度坐标; |
| | | /// bd09:百度墨卡托坐标; |
| | | /// 海外地区定位,无需设置坐标类型,统一返回wgs84类型坐标 |
| | | androidOption.setIsNeedAltitude(true); |
| | | |
| | | /// 可选,设置是否需要返回海拔高度信息,true为需要返回 |
| | | androidOption.setIsNeedAddres(false); |
| | | |
| | | /// 可选,设置是否需要返回地址信息,true为需要返回 |
| | | androidOption.setIsNeedLocationPoiList(false); |
| | | |
| | | /// 可选,设置是否需要返回周边poi信息,true为需要返回 |
| | | androidOption.setIsNeedNewVersionRgc(false); |
| | | |
| | | /// 可选,设置是否需要返回新版本rgc信息,true为需要返回 |
| | | androidOption.setIsNeedLocationDescribe(true); |
| | | |
| | | /// 可选,设置是否需要返回位置描述信息,true为需要返回 |
| | | androidOption.setOpenGps(true); |
| | | |
| | | /// 可选,设置是否需要使用gps,true为需要使用 |
| | | androidOption.setLocationMode(LocationMode.Hight_Accuracy); |
| | | |
| | | /// 可选,设置定位模式,可选的模式有高精度、低功耗、仅设备,默认为高精度模式,可选值如下: |
| | | /// 高精度模式: LocationMode.Hight_Accuracy |
| | | /// 低功耗模式:LocationMode.Battery_Saving |
| | | /// 仅设备(Gps)模式:LocationMode.Device_Sensors |
| | | androidOption.setScanspan(scanspan); |
| | | |
| | | /// 可选,设置发起定位请求的间隔,int类型,单位ms |
| | | /// 如果设置为0,则代表单次定位,即仅定位一次,默认为0 |
| | | /// 如果设置非0,需设置1000ms以上才有效 |
| | | // androidOption.setLocationPurpose(BDLocationPurpose.SignIn); |
| | | |
| | | /// 可选,设置场景定位参数,包括签到场景、运动场景、出行场景,可选值如下: |
| | | /// 签到场景: BDLocationPurpose.SignIn |
| | | /// 运动场景: BDLocationPurpose.Transport |
| | | /// 出行场景: BDLocationPurpose.Sport |
| | | return androidOption.getMap(); |
| | | } |
| | | |
| | | static Map _getIosOption() { |
| | | BaiduLocationIOSOption iosOption = new BaiduLocationIOSOption(); |
| | | |
| | | iosOption.setIsNeedNewVersionRgc(true); |
| | | |
| | | /// 可选,设置是否需要返回新版本rgc信息,true为需要返回 |
| | | |
| | | iosOption.setBMKLocationCoordinateType("BMKLocationCoordinateTypeBMK09LL"); |
| | | |
| | | /// 可选,设置返回位置的坐标系类型 ,参数为String类型,可选值如下: |
| | | /// "BMKLocationCoordinateTypeBMK09LL" 百度经纬度坐标 |
| | | /// "BMKLocationCoordinateTypeBMK09MC" 百度墨卡托坐标 |
| | | /// "BMKLocationCoordinateTypeWGS84" gps坐标 |
| | | /// "BMKLocationCoordinateTypeGCJ02" 国测局坐标 |
| | | |
| | | iosOption.setActivityType("CLActivityTypeAutomotiveNavigation"); |
| | | |
| | | /// 可选,设置应用位置类型,参数为String类型,可选值如下: |
| | | /// "CLActivityTypeOther" |
| | | /// "CLActivityTypeAutomotiveNavigation" |
| | | /// "CLActivityTypeFitness" |
| | | /// "CLActivityTypeOtherNavigation" |
| | | |
| | | iosOption.setDesiredAccuracy("kCLLocationAccuracyBest"); |
| | | |
| | | /// 可选,设置期望定位精度,参数为String类型,可选值如下: |
| | | /// "kCLLocationAccuracyBest" |
| | | /// "kCLLocationAccuracyNearestTenMeters" |
| | | /// "kCLLocationAccuracyHundredMeters" |
| | | /// "kCLLocationAccuracyKilometer" |
| | | |
| | | iosOption.setLocationTimeout(10); |
| | | |
| | | /// 可选,设置位置获取超时时间,参数为int类型 |
| | | |
| | | iosOption.setReGeocodeTimeout(10); |
| | | |
| | | /// 可选,设置获取rgc信息超时时间,参数为int类型 |
| | | |
| | | iosOption.setPauseLocUpdateAutomatically(true); |
| | | |
| | | /// 可选,指定定位是否会被系统自动暂停,参数为bool类型 |
| | | /// true表示定位会被系统自动暂停,false表示不会 |
| | | |
| | | iosOption.setAllowsBackgroundLocationUpdates(true); |
| | | |
| | | /// 可选,设置是否允许后台定位,参数为bool类型 |
| | | /// true表示允许后台定位,false表示不允许后台定位 |
| | | |
| | | iosOption.setDistanceFilter(10); |
| | | |
| | | /// 可选,设置定位的最小更新距离,参数为double类型 |
| | | return iosOption.getMap(); |
| | | } |
| | | |
| | | static void init(int scanSpan) { |
| | | _locationFlutterPlugin!.prepareLoc( |
| | | _getAndroidOption(scanSpan), _getIosOption()); |
| | | } |
| | | |
| | | static void startLocation(OnLocationCallback callback) async { |
| | | final status = await requestLocationPermission(); |
| | | if (status.isGranted) { |
| | | print("定位权限申请通过"); |
| | | } else { |
| | | print("定位权限申请不通过"); |
| | | } |
| | | _locationFlutterPlugin!.startLocation(); |
| | | Stream<Map<String, Object>?> result = |
| | | _locationFlutterPlugin!.onResultCallback(); |
| | | await for (Map<String, Object>? s in result) { |
| | | callback(s!); |
| | | } |
| | | } |
| | | |
| | | ///请求定位权限 |
| | | static Future<PermissionStatus> requestLocationPermission() async { |
| | | final status = await Permission.location.request(); |
| | | return status; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; |
| | | import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart'; |
| | | import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; |
| | | import 'package:locations/model/map/map_model.dart'; |
| | | |
| | | class MapUtil { |
| | | ///画线 |
| | | ///https://lbs.baidu.com/index.php?title=flutter/loc/render-map/ployline |
| | | ///https://mapopen-pub-androidsdk.bj.bcebos.com/map/flutter/docs/utils_api_1.2/flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils-library.html |
| | | static drawLine(List<BMFCoordinate> points, Color lineColor, |
| | | BMFMapController? _mapController, |
| | | {int width = 16}) { |
| | | List<Color> colors = [lineColor]; |
| | | List<int> indexs = List.filled(points.length - 1, 0); |
| | | |
| | | /// 创建polyline |
| | | BMFPolyline colorsPolyline = BMFPolyline( |
| | | coordinates: points, |
| | | indexs: indexs, |
| | | colors: colors, |
| | | width: width, |
| | | dottedLine: false, |
| | | lineDashType: BMFLineDashType.LineDashTypeNone, |
| | | lineCapType: BMFLineCapType.LineCapRound, |
| | | lineJoinType: BMFLineJoinType.LineJoinRound); |
| | | _mapController?.addPolyline(colorsPolyline); |
| | | } |
| | | |
| | | //获取地图的显示参数 |
| | | static Future<MapShowInfo> getMapShowParams( |
| | | List<BMFCoordinate> points) async { |
| | | List<double?> outSides = _getOutSidePoint(points); |
| | | BMFCoordinate center = BMFCoordinate( |
| | | (outSides[0]! + outSides[1]!) / 2, (outSides[2]! + outSides[3]!) / 2); |
| | | //留1/20的边界 |
| | | int zoom = |
| | | await _getZoom(outSides[0], outSides[1], outSides[2], outSides[3]); |
| | | return MapShowInfo(center, zoom); |
| | | } |
| | | |
| | | // |
| | | |
| | | ///获取地图的中心点 |
| | | static List<double?> _getOutSidePoint(List<BMFCoordinate> points) { |
| | | double? maxLat = points[0].latitude; |
| | | double? minLat = points[0].latitude; |
| | | double? maxLng = points[0].longitude; |
| | | double? minLng = points[0].longitude; |
| | | |
| | | //获取东南西北四个点 |
| | | points.forEach((element) { |
| | | if (maxLat! < element.latitude) { |
| | | maxLat = element.latitude; |
| | | } |
| | | if (minLat! > element.latitude) { |
| | | minLat = element.latitude; |
| | | } |
| | | |
| | | if (maxLng! < element.longitude) { |
| | | maxLng = element.longitude; |
| | | } |
| | | |
| | | if (minLng! > element.longitude) { |
| | | minLng = element.longitude; |
| | | } |
| | | }); |
| | | |
| | | return [maxLat, minLat, maxLng, minLng]; |
| | | } |
| | | |
| | | static Future<int> _getZoom( |
| | | double? maxLat, double? minLat, double? maxLng, double? minLng) async { |
| | | List<double> zoom = [ |
| | | 50, |
| | | 100, |
| | | 200, |
| | | 500, |
| | | 1000, |
| | | 2000, |
| | | 5000, |
| | | 10000, |
| | | 20000, |
| | | 25000, |
| | | 50000, |
| | | 100000, |
| | | 200000, |
| | | 500000, |
| | | 1000000, |
| | | 2000000 |
| | | ]; //级别18到3。 |
| | | var pointA = BMFCoordinate(maxLat!, maxLng!); // 创建点坐标A |
| | | var pointB = BMFCoordinate(minLat!, minLng!); // 创建点坐标B |
| | | //留1/20的边界 |
| | | double? distance = |
| | | await BMFCalculateUtils.getLocationDistance(pointA, pointB); |
| | | distance = distance! / 10 + distance; |
| | | for (var i = 0, zoomLen = zoom.length; i < zoomLen; i++) { |
| | | if (zoom[i] - distance > 0) { |
| | | return 18 - i + 3; //之所以会多3,是因为地图范围常常是比例尺距离的10倍以上。所以级别会增加3。 |
| | | } |
| | | } |
| | | return 18; |
| | | } |
| | | |
| | | static Future<BMFMarker> addMarker( |
| | | BMFMapController? _mapController, BMFCoordinate position, String icon, |
| | | {String identifier = "flutter_marker",int zIndex=0,BMFPoint? offset}) async { |
| | | BMFMarker marker = |
| | | BMFMarker(position: position, identifier: identifier, icon: icon,zIndex: zIndex,centerOffset: offset); |
| | | /// 添加Marker |
| | | await _mapController?.addMarker(marker); |
| | | return marker; |
| | | } |
| | | |
| | | static removeMarker(BMFMapController? _mapController, BMFMarker marker) { |
| | | _mapController!.removeMarker(marker); |
| | | } |
| | | |
| | | static removeMarkers(BMFMapController? _mapController, List<BMFMarker> markers) { |
| | | _mapController!.removeMarkers(markers); |
| | | } |
| | | |
| | | static cleanAllMarkers(BMFMapController? _mapController) { |
| | | _mapController!.cleanAllMarkers(); |
| | | } |
| | | } |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | |
| | | typedef PageDataLisener = void Function(dynamic data); |
| | | |
| | |
| | | } |
| | | |
| | | class NavigatorUtil { |
| | | static void navigateToNextPage(BuildContext context, PageRoute route, |
| | | PageDataLisener? dataLisener) async { |
| | | final result = await Navigator.of(context).push(route); |
| | | // static void navigateToNextPage(BuildContext context, PageRoute route, |
| | | // PageDataLisener? dataLisener) async { |
| | | // final result = await Navigator.of(context).push(route); |
| | | // dataLisener!(result); |
| | | // } |
| | | |
| | | static void navigateToNextPage( |
| | | BuildContext context, Widget page, PageDataLisener? dataLisener) async { |
| | | final result = |
| | | await Navigator.of(context).push(MaterialPageRoute(builder: (context) { |
| | | return page; |
| | | })); |
| | | dataLisener!(result); |
| | | } |
| | | |
| | |
| | | |
| | | @override |
| | | void didUpdateWidget(covariant KeepAliveWrapper oldWidget) { |
| | | if(oldWidget.keepAlive != widget.keepAlive) { |
| | | if (oldWidget.keepAlive != widget.keepAlive) { |
| | | // keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中 |
| | | updateKeepAlive(); |
| | | } |
New file |
| | |
| | | class StringUtil { |
| | | |
| | | //是否为电话号码 |
| | | static bool isMobile(String str) { |
| | | return RegExp( |
| | | '^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$') |
| | | .hasMatch(str); |
| | | } |
| | | } |
| | |
| | | |
| | | //滑动效果 |
| | | class ColorConstant { |
| | | static const Color theme = Color(0xFF0E95FE); |
| | | static const Color theme = Color(0xFF0E95FE); |
| | | } |
| | | |
| | | class Constant { |
| | | //阿里云授权登录 |
| | | static const String ALIYUN_AUTH_SECRETINFO = "v+dQBemz/CZaLI0YP/A5AxxG2YgF7IvP+RNzRkmOGln1bbd7tcMt7uvqt8dvb9ekawjGbvSZ6Y/N9WT0kpUb6lrkS11BxfhCpXtuxmOxei97xP3l5Hd8PVqPv2jPC8uVDRhl6kaAqf/6I1gwL1d7am+8w1sGkYnZ3UEgd9ljDBKjeRbbpp+KEzLiqnKWYDNqMLSRdU0BmzTSGqtkM5c1TYOZgx68NxwE2oM9VzcjQEeFP0yiQatMyNIQ5mJjbyU3zi9qiyMQaeTLHeACvqZ2XCYQBbAeqJh6DPrhIHGlfGc="; |
| | | //隐私政策链接 |
| | | static const String PRIVACY_URL="http://www.baidu.com"; |
| | | //用户协议链接 |
| | | static const String PROTOCOL_URL="http://www.baidu.com"; |
| | | |
| | | //微信 |
| | | static const String WX_APPID="wxd930ea5d5a228f5f"; |
| | | static const String WX_UNIVERSAL_LINK="https://your.univerallink.com/link/"; |
| | | |
| | | } |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter_qq/flutter_qq.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | |
| | | class UserUtil { |
| | | static const _loginMessageChannel = |
| | | const BasicMessageChannel('ThirdLogin', StandardMessageCodec()); |
| | | |
| | | //是否同意了用户协议 |
| | | static Future<bool> isAgreeProtocol() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | |
| | | return prefs.setBool("agree_protocol", true); |
| | | } |
| | | |
| | | /// QQ登录 |
| | | static Future<QQResult> loginQQ() async{ |
| | | return await FlutterQq.login(); |
| | | } |
| | | |
| | | ///微信登录 |
| | | static void loginWX() async{ |
| | | fluwx.sendWeChatAuth(scope: "snsapi_userinfo", state: "wechat_sdk_demo_test").then((value) { |
| | | }); |
| | | static void loginWX() async { |
| | | fluwx |
| | | .sendWeChatAuth(scope: "snsapi_userinfo", state: "wechat_sdk_demo_test") |
| | | .then((value) {}); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | static Future<Map> loginQQ() async { |
| | | Map value = await _loginMessageChannel.send({"method": "loginQQ"}) as Map; |
| | | return value; |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.15.0" |
| | | crypto: |
| | | dependency: transitive |
| | | description: |
| | | name: crypto |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.1" |
| | | csslib: |
| | | dependency: transitive |
| | | description: |
| | |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.0" |
| | | flutter_bmflocation: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_bmflocation |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.0-nullsafety.1" |
| | | flutter_datetime_picker: |
| | | dependency: "direct dev" |
| | | description: |
| | |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.4" |
| | | flutter_qq: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_qq |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.0.5" |
| | | flutter_svg: |
| | | dependency: transitive |
| | | description: |
| | |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "8.0.8" |
| | | fluwx: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: fluwx |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.6.1+4" |
| | | fluwx_no_pay: |
| | | dependency: "direct dev" |
| | | description: |
| | |
| | | name: permission_handler |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.3.0" |
| | | version: "8.2.6" |
| | | permission_handler_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: permission_handler_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.7.0" |
| | | petitparser: |
| | | dependency: transitive |
| | | description: |
| | |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | uuid: |
| | | dependency: transitive |
| | | description: |
| | | name: uuid |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.5" |
| | | vector_math: |
| | | dependency: transitive |
| | | description: |
| | |
| | | flutter_lints: ^1.0.0 |
| | | |
| | | cupertino_icons: ^1.0.3 |
| | | permission_handler: ^3.2.0 |
| | | permission_handler: ^8.2.6 |
| | | |
| | | |
| | | shared_preferences: ^2.0.8 |
| | |
| | | flutter_baidu_mapapi_map: ^3.0.0+2 |
| | | flutter_baidu_mapapi_search: ^3.0.0 |
| | | flutter_baidu_mapapi_utils: ^3.0.0 |
| | | #百度定位 |
| | | flutter_bmflocation: ^2.0.0-nullsafety.1 |
| | | # flutter_bmflocation: ^2.0.0-nullsafety.1 |
| | | |
| | | webview_flutter: ^2.1.2 |
| | |
| | | #微信登录 |
| | | fluwx_no_pay: ^3.6.1+5 |
| | | |
| | | fluwx: ^3.6.1+4 |
| | | |
| | | flutter_qq: ^0.0.5 |
| | | |
| | | # For information on the generic Dart part of this file, see the |
| | | # following page: https://dart.dev/tools/pub/pubspec |