有人在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)
我正在使用 MVVM 架构,这就是我的实现方式:
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") 字段用于指定您在查询中查找什么,您可以查找机构等。 类型可以在这里
找到您可以看到我们有一个带有“预测”键的对象,所以这是我们的第一个模型。
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>
)
我只需要这些信息,如果您需要其他信息,请随意修改模型或创建自己的模型。
@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)
}
}
如果您需要任何进一步的帮助,请告诉我
@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")
}
}
}
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)
}
}
}