我正在尝试使用@react-native-mapbox-gl/maps库来实现 Geocoder,因为它是Mapbox 官方网站中对反应原生应用程序的建议。
我的地图完全可以使用,但是当谈到地理编码器时,我找不到合适的图书馆。尝试了一些反应库,但我遇到了一些错误,不知道去哪里。我已经尝试了很多,但无法让它工作。已经测试了库react-mapbox-gl-geocoder,@mapbox/mapbox-gl-geocoder和 react-mui-mapbox-geocoder (不能发布超过 8 个链接,所以只需删除空间:www.npmjs.com /package /react-mui-mapbox-geocoder)。甚至尝试了带有react-map-gl库的 react-map-gl-geocoder ,该库已被弃用,以查看是否可以使用,因为我已经看到了一些带有地理编码器的示例,但效果不佳。
这是我没有地理编码器库的代码:
import React, { Component, useState } from 'react';
import {
View,
Text,
StyleSheet,
PermissionsAndroid,
TextInput,
Keyboard,
} from 'react-native';
import Geolocation from "@react-native-community/geolocation";
import MapboxGL from '@react-native-mapbox-gl/maps';
import Colors from '../../styles/colors';
// Variáveis
granted = 1;
MapboxGL.setAccessToken('Mapbox token');
MapboxGL.setConnected(true);
async function requestLocationPermission() {
try {
granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'App',
message:
'Necessita de permissão da sua localização para mostrar o mapa.',
buttonNeutral: 'Perguntar mais tarde',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
} catch (err) {
console.warn(err);
}
}
export default function Home({ navigation }) {
const permissaoLocalizacao = requestLocationPermission()
const [position, setPosition] = useState({
latitude: 0,
longitude: 0
});
const [error, setError] = useState("");
const getPosition = () => {
Geolocation.getCurrentPosition(
pos => {
setError("");
setPosition({
latitude: pos.coords.latitude,
longitude: pos.coords.longitude
});
},
e => setError(e.message)
);
};
const onMapPress = (event) => {
}
if (permissaoLocalizacao) {
if (!position.longitude) {
getPosition();
}
if (error) {
console.log("error")
return (
<View style={styles.container}>
{/* alert('Sair do aplicativo'); */}
</View>
)
}
return (
<View style={styles.container}>
<MapboxGL.MapView
style={styles.map}
onPress={onMapPress}
>
<MapboxGL.Camera
zoomLevel={16}
centerCoordinate={[position.longitude, position.latitude]}
/>
<MapboxGL.PointAnnotation
id="PosicaoAtual"
coordinate={[position.longitude, position.latitude]}
>
<View style={styles.annotationContainer}>
<View style={styles.annotationFill} />
</View>
</MapboxGL.PointAnnotation>
</MapboxGL.MapView>
</View>
);
}else{
return(
<View style={styles.container}>
<Text>Necessário permissão da localização</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.white,
},
map: {
flex: 1,
},
annotationContainer: {
width: 30,
height: 30,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
borderRadius: 15,
},
annotationFill: {
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: Colors.primary,
transform: [{ scale: 0.8 }],
}
});
这是我的 package.json,它有点污染,因为我已经尝试了很多东西:
{
"name": "mapbox",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"@mapbox/mapbox-gl-geocoder": "^4.5.1",
"@react-native-community/geolocation": "^2.0.2",
"@react-native-community/masked-view": "^0.1.6",
"@react-native-mapbox-gl/maps": "^7.2.0",
"@react-navigation/bottom-tabs": "^5.4.2",
"@react-navigation/drawer": "^5.5.0",
"@react-navigation/native": "^5.0.6",
"@react-navigation/stack": "^5.0.6",
"react": "16.11.0",
"react-map-gl": "^5.2.5",
"react-map-gl-geocoder": "^2.0.11",
"react-mapbox-gl-geocoder": "^1.1.0",
"react-mui-mapbox-geocoder": "^1.1.1",
"react-native": "0.62.2",
"react-native-geolocation-service": "^4.0.0",
"react-native-gesture-handler": "^1.6.0",
"react-native-reanimated": "^1.7.0",
"react-native-safe-area-context": "^0.7.3",
"react-native-safe-area-view": "^1.1.0",
"react-native-screens": "^2.0.0-beta.10",
"react-native-vector-icons": "^6.6.0",
"react-navigation": "^4.1.1",
},
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/runtime": "^7.9.6",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^26.0.1",
"eslint": "^7.0.0",
"jest": "^26.0.1",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.11.0"
},
"jest": {
"preset": "react-native"
}
}
我的 android/build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
}
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.5.2")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url 'https://www.jitpack.io' }
}
}
我的 android/setting.gradle
rootProject.name = 'mapbox'
// MapBox
include ':@react-native-mapbox-gl_maps'
project(':@react-native-mapbox-gl_maps').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-mapbox-gl/maps/android/rctmgl')
// Vector Icons
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
我的 android/app/build.gradle
apply plugin: "com.android.application"
import com.android.build.OutputFile
/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
project.ext.react = [
enableHermes: false, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.mapbox"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
// React native screens
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
// MapBox
implementation project(':@react-native-mapbox-gl_maps')
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
compile 'com.android.support:multidex:1.0.1'
// Vector Icons
compile project(':react-native-vector-icons')
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
// Vector Icons
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
和 MainApplication;
package com.mapbox;
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import com.mapbox.rctmgl.RCTMGLPackage; // Mapbox
import com.oblador.vectoricons.VectorIconsPackage; // Vector Icons
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
//new VectorIconsPackage() // Vector Icons
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.mapbox.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
我不知道这个反应库是否可以工作,但这是我面临的错误:
-我将项目目录替换为更干净
-> 导入 react-mapbox-gl-geocoder:
- 首先是缺少“事件”和“http”库,然后我添加了它们,但无法解决这个问题。
error: Error: While trying to resolve module `http` from file `<projectfolder>\node_modules\react-mapbox-gl-geocoder\dist\index.js`, the package `<projectfolder>\node_modules\http\package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`<projectfolder>\node_modules\http\index`. Indeed, none of these files exist:
* <projectfolder>\node_modules\http\index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
* <projectfolder>\node_modules\http\index\index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
at ResolutionRequest.resolveDependency (<projectfolder>\node_modules\metro\src\node-haste\DependencyGraph\ResolutionRequest.js:65:15)
at DependencyGraph.resolveDependency (<projectfolder>\node_modules\metro\src\node-haste\DependencyGraph.js:287:16)
at Object.resolve (<projectfolder>\node_modules\metro\src\lib\transformHelpers.js:267:42)
at <projectfolder>\node_modules\metro\src\DeltaBundler\traverseDependencies.js:434:31
at Array.map (<anonymous>)
at resolveDependencies (<projectfolder>\node_modules\metro\src\DeltaBundler\traverseDependencies.js:431:18)
at <projectfolder>\node_modules\metro\src\DeltaBundler\traverseDependencies.js:275:33
at Generator.next (<anonymous>)
at asyncGeneratorStep (<projectfolder>\node_modules\metro\src\DeltaBundler\traverseDependencies.js:87:24)
at _next (<projectfolder>\node_modules\metro\src\DeltaBundler\traverseDependencies.js:107:9)
-> 导入@mapbox/mapbox-gl-geocoder:
这发生在构建中:
[Sat May 23 2020 21:41:54.544] WARN Require cycle: node_modules\@react-native-mapbox-gl\maps\javascript\index.js -> node_modules\@react-native-mapbox-gl\maps\javascript\components\annotations\Annotation.js -> node_modules\@react-native-mapbox-gl\maps\javascript\index.js
Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
这在应用程序中:
所以我添加了 'expo-random' 和 'nonoid' 库,但它要求我输入 '@unimodules/core',然后是 '@unimodules/react-native-adapter' 和另一个错误,所以我停止了。
-> 导入 react-mui-mapbox-geocoder
给我一个更新 Autosuggest 库的方法。
-> 使用 map-gl 导入 react-map-gl-geocoder
这发生在构建中:
[Sat May 23 2020 16:54:57.817] WARN Require cycle: node_modules\viewport-mercator-project\dist\es5\web-mercator-viewport.js -> node_modules\viewport-mercator-project\dist\es5\fit-bounds.js -> node_modules\viewport-mercator-project\dist\es5\web-mercator-viewport.js
Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
这在应用程序中。 应用程序错误
如果您发现其他问题或可能会更好,请告诉我。我仍在学习本机反应,我可能误解了一些东西。希望我们能找到解决方案,这有助于其他人。