实现 Google 在 jetpack compose android 中放置 autoComplete 文本字段实现

问题描述 投票:0回答:3

有人在jetpack compose项目中实现了谷歌自动完成建议文本字段或片段吗?如果是这样,请指导或分享代码片段,因为我在实现它时遇到困难。

更新

这是我触发打开全屏对话框的意图,但是当我开始在其中输入内容时,它会被关闭,而且我也无法弄清楚问题是什么,并且需要有关处理活动结果的线索读取此 compose 函数中的预测结果。

    Places.initialize(context, "sa")

    val fields = listOf(Place.Field.ID, Place.Field.NAME)

    val intent = Autocomplete.IntentBuilder(
        AutocompleteActivityMode.FULLSCREEN,fields).build(context)

        startActivityForResult(context as MainActivity,intent, AUTOCOMPLETE_REQUEST_CODE, Bundle.EMPTY)
                            
android android-jetpack-compose google-places placeautocompletefragment
3个回答
10
投票

我正在使用 MVVM 架构,这就是我的实现方式:

GooglePlacesApi

我创建了一个用于访问名为 GooglePlacesApi 的 google api 的 api
interface GooglePlacesApi {
    @GET("maps/api/place/autocomplete/json")
    suspend fun getPredictions(
        @Query("key") key: String = <GOOGLE_API_KEY>,
        @Query("types") types: String = "address",
        @Query("input") input: String
    ): GooglePredictionsResponse

    companion object{
        const val BASE_URL = "https://maps.googleapis.com/"
    }
}

@Query("types") 字段用于指定您在查询中查找什么,您可以查找机构等。 类型可以在这里

找到

型号

所以我为此实现创建了 3 个模型:
谷歌预测响应
如果您使用邮递员执行 GET 请求,则响应的方式如下:

Google Prediction Response

您可以看到我们有一个带有“预测”键的对象,所以这是我们的第一个模型。

data class GooglePredictionsResponse(
    val predictions: ArrayList<GooglePrediction>
)
谷歌预测术语
data class GooglePredictionTerm(
    val offset: Int,
    val value: String
)
谷歌预测
data class GooglePrediction(
    val description: String,
    val terms: List<GooglePredictionTerm>
)

我只需要这些信息,如果您需要其他信息,请随意修改模型或创建自己的模型。

Google 地点存储库

最后我们创建存储库来获取信息(我使用 hilt 来注入我的依赖项,如果不使用它,您可以忽略这些注释)
@ActivityScoped
class GooglePlacesRepository @Inject constructor(
    private val api: GooglePlacesApi,
){
    suspend fun getPredictions(input: String): Resource<GooglePredictionsResponse>{
        val response = try {
            api.getPredictions(input = input)
        } catch (e: Exception) {
            Log.d("Rently", "Exception: ${e}")
            return Resource.Error("Failed prediction")
        }

        return Resource.Success(response)
    }
}

这里我使用了一个我创建的额外类来处理响应,称为 Resource

sealed class Resource<T>(val data: T? = null, val message: String? = null){
    class Success<T>(data: T): Resource<T>(data)
    class Error<T>(message: String, data:T? = null): Resource<T>(data = data, message = message)
    class Loading<T>(data: T? = null): Resource<T>(data = data)
}

查看模型

我再次使用剑柄,因此如果不使用它,请忽略注释。
@HiltViewModel
class AddApartmentViewModel @Inject constructor(private val googleRepository: GooglePlacesRepository): ViewModel(){

    val isLoading = mutableStateOf(false)
    val predictions = mutableStateOf(ArrayList<GooglePrediction>())
    
    fun getPredictions(address: String) {
        viewModelScope.launch {
            isLoading.value = true
            val response = googleRepository.getPredictions(input = address)
            when(response){
                is Resource.Success -> {
                    predictions.value = response.data?.predictions!!
                }
            }

            isLoading.value = false
        }
    }

    fun onSearchAddressChange(address: String){
        getPredictions(address)
    }
}

如果您需要任何进一步的帮助,请告诉我

  • 我没有包含 UI 实现,因为我认为它是单独的,但这是更容易的部分;)

2
投票
@Composable
fun MyComponent() {
    val context = LocalContext.current

    val intentLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult()
    ) {
        when (it.resultCode) {
            Activity.RESULT_OK -> {
                it.data?.let {
                    val place = Autocomplete.getPlaceFromIntent(it)
                    Log.i("MAP_ACTIVITY", "Place: ${place.name}, ${place.id}")
                }
            }
            AutocompleteActivity.RESULT_ERROR -> {
                it.data?.let {
                    val status = Autocomplete.getStatusFromIntent(it)
                    Log.i("MAP_ACTIVITY", "Place: ${place.name}, ${place.id}")
                }
            }
            Activity.RESULT_CANCELED -> {
                // The user canceled the operation.
            }
        }
    }

    val launchMapInputOverlay = {
        Places.initialize(context, YOUR_API_KEY)
        val fields = listOf(Place.Field.ID, Place.Field.NAME)
        val intent = Autocomplete
            .IntentBuilder(AutocompleteActivityMode.OVERLAY, fields)
            .build(context)
        intentLauncher.launch(intent)
    }

    Column {
        Button(onClick = launchMapInputOverlay) {
            Text("Select Location")
        }
    }
}

0
投票

只需使用 Google Maps Places API 库

implementation("com.google.android.libraries.places:places:3.1.0")

在onCreate()中的.Application文件中初始化它

Places.initialize(applicationContext, "YOUR_API_KEY")

然后在每个文本字段输入上调用该函数

val client = Places.createClient(androidContext())

suspend fun getAddressPredictions(
    sessionToken: AutocompleteSessionToken = AutocompleteSessionToken.newInstance(),
    inputString: String,
    location: LatLng? = null
) = suspendCoroutine<List<AutocompletePrediction>> {

    placesClient.findAutocompletePredictions(
            FindAutocompletePredictionsRequest.builder()
                .setOrigin(location)
                // Call either setLocationBias() OR setLocationRestriction().
                // .setLocationBias(bounds)
                // .setLocationRestriction(bounds)
                .setCountries("US")
                .setTypesFilter(listOf(PlaceTypes.ADDRESS))
                .setSessionToken(sessionToken)
                .setQuery(inputString)
                .build()
    ).addOnCompleteListener { completedTask ->
        if (completedTask.exception != null) {
            Log.e([email protected](), completedTask.exception?.stackTraceToString().orEmpty())
            it.resume(listOf())
        } else {
            it.resume(completedTask.result.autocompletePredictions)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.