Implementing Google Places AutoComplete TextField in Jetpack Compose
This article guides you through implementing Google Places AutoComplete functionality in your Jetpack Compose Android application.
1. Project Setup
Before diving into the implementation, ensure your project has the necessary dependencies:
- Google Places SDK for Android: Add the following dependency to your
build.gradle
(Module:app) file:
implementation "com.google.android.libraries.maps:maps-compose:3.0.0" // Replace with your desired version
- Jetpack Compose UI: Make sure you’re using the latest Jetpack Compose version. Refer to the official documentation for installation instructions.
2. Obtain API Keys
- Google Maps Platform: Visit https://cloud.google.com/maps-platform and create a project if you don’t have one.
- Enable APIs: Enable the “Google Maps Places API” and “Google Maps SDK for Android” from the “APIs & Services” section of your project.
- API Key: Generate an API key for your project. Keep this key secure. Store it in a separate file or environment variable for security reasons.
3. Implement the AutoComplete TextField
Let’s create the basic structure of the composable function responsible for displaying and managing the Google Places AutoComplete:
@Composable fun GooglePlacesAutoCompleteTextField( onPlaceSelected: (Place) -> Unit, initialQuery: String = "" ) { val context = LocalContext.current val placesClient = remember { Places.createClient(context) } val state = remember { AutoCompleteState(placesClient, initialQuery) } TextField( value = state.query, onValueChange = { query -> state.setQuery(query) }, label = { Text("Enter a location") }, modifier = Modifier.fillMaxWidth() ) LaunchedEffect(key1 = state.query) { if (state.query.isNotBlank()) { state.predictions = state.placesClient.findAutocompletePredictions( FindAutocompletePredictionsRequest.newInstance(state.query, state.bounds) ).await() } } // Display suggestions/predictions if (state.predictions.isNotEmpty()) { Column { state.predictions.forEach { prediction -> Text( text = prediction.place.name, modifier = Modifier .fillMaxWidth() .clickable { onPlaceSelected(prediction.place) // Reset query state.setQuery("") } .padding(vertical = 8.dp) ) } } } } @Composable fun AutoCompleteState(placesClient: PlacesClient, initialQuery: String) { var query by remember { mutableStateOf(initialQuery) } var predictions by remember { mutableStateOf>(emptyList()) } var bounds by remember { mutableStateOf
(LatLngBounds.builder().build()) } fun setQuery(newQuery: String) { query = newQuery } // Update bounds based on location or user's search // Example: Update bounds on user's location if (state.location != null) { val southwest = LatLng(state.location.latitude - 0.5, state.location.longitude - 0.5) val northeast = LatLng(state.location.latitude + 0.5, state.location.longitude + 0.5) bounds = LatLngBounds.builder() .include(southwest) .include(northeast) .build() } }
4. Explanations
Let’s break down the key elements of this composable function:
placesClient
: This object is created using the Google Places API client and is used for making API requests.state
: This represents the state of the AutoComplete component, including the current query, predictions, and other relevant data.TextField
: We use Jetpack Compose’sTextField
composable to display the input field where the user can type their location.LaunchedEffect
: When the user starts typing, this block triggers an API call to fetch autocomplete predictions based on the current query.predictions
: This variable holds the list of autocomplete predictions returned by the API.Column
: A column is used to display the list of predictions below the input field.Text
: Each prediction is displayed as a text item, making it clickable.onPlaceSelected
: When the user selects a prediction, this callback function is executed with the selected Place object.
5. Integrating the AutoComplete TextField
Now, you can easily integrate the GooglePlacesAutoCompleteTextField
composable into your UI:
@Composable fun HomeScreen() { var selectedPlace by remember { mutableStateOf(null) } Column(modifier = Modifier.padding(16.dp)) { GooglePlacesAutoCompleteTextField( onPlaceSelected = { place -> selectedPlace = place }, initialQuery = "Initial location" // Optional: Set an initial query ) if (selectedPlace != null) { Text("Selected Place: ${selectedPlace?.name}") } } }
6. Handling Permissions
Ensure your application requests necessary permissions:
- AndroidManifest.xml: Add the following permissions in your app’s
AndroidManifest.xml
file:
7. Considerations
- Location Services: To enhance the accuracy of suggestions, consider enabling location services and requesting the user’s location.
- Error Handling: Implement robust error handling mechanisms to gracefully handle network issues or API errors.
- Performance: Be mindful of the number of predictions displayed and the potential impact on UI responsiveness.
- Customization: Explore options to further customize the styling of the AutoComplete TextField and predictions. Use Jetpack Compose modifiers to achieve the desired appearance.