android 地图
This commit is contained in:
@@ -68,3 +68,8 @@ android {
|
|||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.amap.api:navi-3dmap-location-search:10.0.700_3dmap10.0.700_loc6.4.5_sea9.7.2")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
android:label="小羚羚"
|
android:label="小羚羚"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/logo">
|
android:icon="@mipmap/logo">
|
||||||
|
|
||||||
|
<!-- 高德地图Key -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.amap.api.v2.apikey"
|
||||||
|
android:value="92495660f7bc990cb475426c47c03b65" />
|
||||||
|
|
||||||
|
<!-- 高德地图定位服务 -->
|
||||||
|
<service android:name="com.amap.api.location.APSService" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -1,6 +1,195 @@
|
|||||||
package com.lnkj.ln_jq_app;
|
package com.lnkj.ln_jq_app;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import io.flutter.embedding.android.FlutterActivity;
|
import io.flutter.embedding.android.FlutterActivity;
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
public class MainActivity extends FlutterActivity {
|
public class MainActivity extends FlutterActivity {
|
||||||
|
|
||||||
|
private static final String CHANNEL = "com.lnkj.ln_jq_app/map";
|
||||||
|
private static final String TAG = "MainActivity";
|
||||||
|
|
||||||
|
// 权限请求码
|
||||||
|
private static final int PERMISSION_REQUEST_CODE = 1001;
|
||||||
|
|
||||||
|
private NativeMapView mapView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
|
||||||
|
super.configureFlutterEngine(flutterEngine);
|
||||||
|
|
||||||
|
// 注册高德地图导航Platform View
|
||||||
|
flutterEngine
|
||||||
|
.getPlatformViewsController()
|
||||||
|
.getRegistry()
|
||||||
|
.registerViewFactory(
|
||||||
|
"NativeFirstPage",
|
||||||
|
new NativeMapFactory(this)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 注册方法通道用于地图控制
|
||||||
|
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
|
||||||
|
.setMethodCallHandler((call, result) -> {
|
||||||
|
switch (call.method) {
|
||||||
|
case "requestPermissions":
|
||||||
|
requestPermissions();
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "onResume":
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onResume();
|
||||||
|
}
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "onPause":
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onPause();
|
||||||
|
}
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "onDestroy":
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.dispose();
|
||||||
|
mapView = null;
|
||||||
|
}
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.notImplemented();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前系统版本需要申请的权限列表
|
||||||
|
*/
|
||||||
|
private String[] getRequiredPermissions() {
|
||||||
|
List<String> permissions = new ArrayList<>();
|
||||||
|
// 定位权限是必须的
|
||||||
|
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||||
|
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
|
||||||
|
|
||||||
|
// 存储权限处理:Android 13 (API 33) 以下才需要申请 legacy 存储权限
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
|
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查并申请权限
|
||||||
|
*/
|
||||||
|
private void checkAndRequestPermissions() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
String[] requiredPermissions = getRequiredPermissions();
|
||||||
|
List<String> deniedPermissions = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String permission : requiredPermissions) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
deniedPermissions.add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deniedPermissions.isEmpty()) {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
this,
|
||||||
|
deniedPermissions.toArray(new String[0]),
|
||||||
|
PERMISSION_REQUEST_CODE
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "所有必要权限已授予");
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.startLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.startLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestPermissions() {
|
||||||
|
checkAndRequestPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapView(NativeMapView mapView) {
|
||||||
|
this.mapView = mapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// 注意:高德SDK合规检查通过后再进行定位相关操作
|
||||||
|
// 这里仅保留地图生命周期调用,权限建议在Flutter端或按需触发
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onResume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.dispose();
|
||||||
|
mapView = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
|
||||||
|
if (requestCode == PERMISSION_REQUEST_CODE) {
|
||||||
|
boolean locationGranted = false;
|
||||||
|
for (int i = 0; i < permissions.length; i++) {
|
||||||
|
if (Manifest.permission.ACCESS_FINE_LOCATION.equals(permissions[i])
|
||||||
|
&& grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
locationGranted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locationGranted) {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.startLocation();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 只有在定位权限确实被拒绝时才弹出提示
|
||||||
|
Toast.makeText(this, "请授予应用定位权限以正常使用地图功能", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.lnkj.ln_jq_app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.MessageCodec;
|
||||||
|
import io.flutter.plugin.common.StandardMessageCodec;
|
||||||
|
import io.flutter.plugin.platform.PlatformView;
|
||||||
|
import io.flutter.plugin.platform.PlatformViewFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高德地图导航 Platform View Factory
|
||||||
|
* 对应iOS的NativeViewFactory
|
||||||
|
*/
|
||||||
|
public class NativeMapFactory extends PlatformViewFactory {
|
||||||
|
|
||||||
|
private static final String VIEW_TYPE_ID = "NativeFirstPage";
|
||||||
|
private static NativeMapView mapViewInstance = null;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public NativeMapFactory(Context context) {
|
||||||
|
super(StandardMessageCodec.INSTANCE);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlatformView create(Context context, int viewId, Object args) {
|
||||||
|
mapViewInstance = new NativeMapView(context, viewId, args);
|
||||||
|
return mapViewInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取地图实例,供MainActivity使用
|
||||||
|
*/
|
||||||
|
public static NativeMapView getMapView() {
|
||||||
|
return mapViewInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
package com.lnkj.ln_jq_app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.amap.api.location.AMapLocation;
|
||||||
|
import com.amap.api.location.AMapLocationClient;
|
||||||
|
import com.amap.api.location.AMapLocationClientOption;
|
||||||
|
import com.amap.api.location.AMapLocationListener;
|
||||||
|
import com.amap.api.maps.AMap;
|
||||||
|
import com.amap.api.maps.LocationSource;
|
||||||
|
import com.amap.api.maps.MapView;
|
||||||
|
import com.amap.api.maps.MapsInitializer;
|
||||||
|
import com.amap.api.maps.model.MyLocationStyle;
|
||||||
|
|
||||||
|
import io.flutter.plugin.platform.PlatformView;
|
||||||
|
|
||||||
|
public class NativeMapView implements PlatformView, LocationSource, AMapLocationListener {
|
||||||
|
private static final String TAG = "NativeMapView";
|
||||||
|
private final MapView mapView;
|
||||||
|
private final AMap aMap;
|
||||||
|
private OnLocationChangedListener mListener;
|
||||||
|
private AMapLocationClient mlocationClient;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
public NativeMapView(Context context, int id, Object args) {
|
||||||
|
this.mContext = context;
|
||||||
|
|
||||||
|
// 隐私合规接口,必须在创建MapView之前设置
|
||||||
|
MapsInitializer.updatePrivacyShow(context, true, true);
|
||||||
|
MapsInitializer.updatePrivacyAgree(context, true);
|
||||||
|
|
||||||
|
mapView = new MapView(context);
|
||||||
|
// 在 Flutter PlatformView 中,savedInstanceState 通常为 null
|
||||||
|
mapView.onCreate(null);
|
||||||
|
aMap = mapView.getMap();
|
||||||
|
|
||||||
|
// 设置地图的 UI 选项
|
||||||
|
setupMapUi();
|
||||||
|
|
||||||
|
// 注册到 MainActivity 以便同步生命周期
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).setMapView(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupMapUi() {
|
||||||
|
aMap.setLocationSource(this);
|
||||||
|
aMap.setMyLocationEnabled(true);
|
||||||
|
|
||||||
|
MyLocationStyle myLocationStyle = new MyLocationStyle();
|
||||||
|
myLocationStyle.interval(2000);
|
||||||
|
// 连续定位并将视角移动到地图中心点,定位蓝点跟随设备移动
|
||||||
|
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
|
||||||
|
myLocationStyle.showMyLocation(true);
|
||||||
|
myLocationStyle.strokeColor(Color.TRANSPARENT);
|
||||||
|
myLocationStyle.radiusFillColor(Color.TRANSPARENT);
|
||||||
|
aMap.setMyLocationStyle(myLocationStyle);
|
||||||
|
|
||||||
|
// 显示缩放按钮
|
||||||
|
aMap.getUiSettings().setZoomControlsEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView() {
|
||||||
|
return mapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(OnLocationChangedListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
startLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivate() {
|
||||||
|
mListener = null;
|
||||||
|
if (mlocationClient != null) {
|
||||||
|
mlocationClient.stopLocation();
|
||||||
|
mlocationClient.onDestroy();
|
||||||
|
}
|
||||||
|
mlocationClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startLocation() {
|
||||||
|
if (mlocationClient == null) {
|
||||||
|
try {
|
||||||
|
AMapLocationClient.updatePrivacyShow(mContext, true, true);
|
||||||
|
AMapLocationClient.updatePrivacyAgree(mContext, true);
|
||||||
|
mlocationClient = new AMapLocationClient(mContext);
|
||||||
|
AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
|
||||||
|
mlocationClient.setLocationListener(this);
|
||||||
|
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
|
||||||
|
mlocationClient.setLocationOption(mLocationOption);
|
||||||
|
mlocationClient.startLocation();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "startLocation error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(AMapLocation amapLocation) {
|
||||||
|
if (mListener != null && amapLocation != null) {
|
||||||
|
if (amapLocation.getErrorCode() == 0) {
|
||||||
|
mListener.onLocationChanged(amapLocation);
|
||||||
|
// 首次定位成功后缩放地图
|
||||||
|
// aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "定位失败," + amapLocation.getErrorCode() + ": " + amapLocation.getErrorInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onResume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPause() {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
if (mapView != null) {
|
||||||
|
mapView.onDestroy();
|
||||||
|
}
|
||||||
|
deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
ln_jq_app/android/app/src/main/res/drawable/amap_loc.xml
Normal file
10
ln_jq_app/android/app/src/main/res/drawable/amap_loc.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="48"
|
||||||
|
android:viewportHeight="48">
|
||||||
|
<path
|
||||||
|
android:fillColor="#2196F3"
|
||||||
|
android:pathData="M24,4C13.4,4 4,13.4 4,24s9.4,20 20,20 20,-9.4 20,-20S34.6,4 24,4zM24,40c-8.8,0 -16,-7.2 -16,-16s7.2,-16 16,-16 16,7.2 16,16 -7.2,16 -16,16zM24,36c-6.6,0 -12,-5.4 -12,-12s5.4,-12 12,-12 12,5.4 12,12 -5.4,12 -12,12zM24,32c-4.4,0 -8,-3.6 -8,-8s3.6,-8 8,-8 8,3.6 8,8 -3.6,8 -8,8zM24,30c-3.3,0 -6,-2.7 -6,-6s2.7,-6 6,-6 6,2.7 6,6 -2.7,6 -6,6zM24,24c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32dp"
|
||||||
|
android:height="32dp"
|
||||||
|
android:viewportWidth="32"
|
||||||
|
android:viewportHeight="32">
|
||||||
|
<path
|
||||||
|
android:fillColor="#F44336"
|
||||||
|
android:pathData="M16,4C10.48,4 6,8.48 6,14c0,4.84 9.2,13.76 9.2,13.76C15.49,28.05 15.74,28.14 16,28.14s0.51,-0.09 0.8,-0.38C16.8,27.76 26,18.84 26,14C26,8.48 21.52,4 16,4zM16,17c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3z"/>
|
||||||
|
</vector>
|
||||||
10
ln_jq_app/android/app/src/main/res/drawable/ic_location.xml
Normal file
10
ln_jq_app/android/app/src/main/res/drawable/ic_location.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#666666"
|
||||||
|
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||||
|
</vector>
|
||||||
13
ln_jq_app/android/app/src/main/res/drawable/ic_route.xml
Normal file
13
ln_jq_app/android/app/src/main/res/drawable/ic_route.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M12,16l-4,4h8z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32dp"
|
||||||
|
android:height="32dp"
|
||||||
|
android:viewportWidth="32"
|
||||||
|
android:viewportHeight="32">
|
||||||
|
<path
|
||||||
|
android:fillColor="#4CAF50"
|
||||||
|
android:pathData="M16,4C10.48,4 6,8.48 6,14c0,4.84 9.2,13.76 9.2,13.76C15.49,28.05 15.74,28.14 16,28.14s0.51,-0.09 0.8,-0.38C16.8,27.76 26,18.84 26,14C26,8.48 21.52,4 16,4zM16,17c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32dp"
|
||||||
|
android:height="32dp"
|
||||||
|
android:viewportWidth="32"
|
||||||
|
android:viewportHeight="32">
|
||||||
|
<path
|
||||||
|
android:fillColor="#2196F3"
|
||||||
|
android:pathData="M16,2C9.38,2 4,7.38 4,14c0,5.28 10,14 10,14s10,-8.72 10,-14C24,7.38 18.62,2 16,2zM16,17c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM16,12c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,44 +1,69 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
/// 原生地图页面
|
||||||
class NativePageIOS extends StatelessWidget {
|
class NativePageIOS extends StatelessWidget {
|
||||||
const NativePageIOS({super.key});
|
const NativePageIOS({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
return Container(
|
return _buildIOSView(context);
|
||||||
// onTap: () => _handleTap(context),
|
} else if (Platform.isAndroid) {
|
||||||
width: MediaQuery.of(context).size.width,
|
return _buildAndroidView(context);
|
||||||
height: MediaQuery.of(context).size.width - 100,
|
} else {
|
||||||
// padding: EdgeInsetsGeometry.all(15),
|
return const Center(
|
||||||
color: Colors.red[100],
|
child: Text('不支持的平台', style: TextStyle(fontSize: 16)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 构建iOS Platform View
|
||||||
|
Widget _buildIOSView(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height - 100,
|
||||||
|
color: Colors.white,
|
||||||
child: UiKitView(
|
child: UiKitView(
|
||||||
viewType: 'NativeFirstPage', // 与原生端注册的标识一致
|
viewType: 'NativeFirstPage', // 与iOS原生端注册的标识一致
|
||||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{}.toSet(),
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{}.toSet(),
|
||||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||||
creationParamsCodec: const StandardMessageCodec(),
|
creationParamsCodec: const StandardMessageCodec(),
|
||||||
layoutDirection: TextDirection.ltr,
|
layoutDirection: TextDirection.ltr,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
return const Center(child: Text('not ios'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 构建Android Platform View
|
||||||
|
Widget _buildAndroidView(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height - 100,
|
||||||
|
color: Colors.white,
|
||||||
|
child: AndroidView(
|
||||||
|
viewType: 'NativeFirstPage', // 与Android原生端注册的标识一致
|
||||||
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{}.toSet(),
|
||||||
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||||
|
creationParamsCodec: const StandardMessageCodec(),
|
||||||
|
layoutDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 处理点击事件(如需要)
|
||||||
void _handleTap(BuildContext context) {
|
void _handleTap(BuildContext context) {
|
||||||
print("页面被点击");
|
if (kDebugMode) {
|
||||||
_showDialog(context, 'Tip', '点击了');
|
print("NativePage被点击");
|
||||||
|
}
|
||||||
|
_showDialog(context, '提示', '点击了原生地图页面');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 显示对话框
|
||||||
void _showDialog(BuildContext context, String title, String content) {
|
void _showDialog(BuildContext context, String title, String content) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -54,5 +79,4 @@ class NativePageIOS extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user