Sử dụng PlaceAutocompleteFragment để xây dựng 1 ứng dụng tìm kiếm địa điểm đơn giản
Bài đăng này đã không được cập nhật trong 3 năm
1. Khởi tạo project
Cách đơn giản nhất là các bạn khởi tạo 1 project với sử dụng template Google Maps Activity.
Để lấy key cho ứng dụng các bạn cần làm những bước sau
- Vào https://console.developers.google.com/iam-admin/projects khởi tạo 1 project
- Vào https://console.developers.google.com/apis/library?project=my-location-android click Google Maps Android API và Google Places API for Android chọn ENABLE để cho phép key của bạn được phép sử dụng 2 dịch vụ này của google.
(các bạn có thể tham khảo cách tạo key cho ứng dụng ở đây https://developers.google.com/maps/documentation/android-api/signup). Sau khi lấy dc key cho ứng dụng các bạn điền key cho Project vào thẻ <meta-data> trong file AndroidManifest
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="enter_your_key_here"/>
trong build.gradle các bạn thêm thư viện
compile 'com.google.android.gms:play-services:10.0.1'
Các bạn thiết kế lại layout_main.xml 1 chút:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lap.myapplication.MapsActivity"
>
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<fragment
android:id="@+id/place_autocomplete_fragment"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
Quay lại file MainAcvity
public class MainActivity extends FragmentActivity
implements OnMapReadyCallback, PlaceSelectionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
PlaceAutocompleteFragment autocompleteFragment =
(PlaceAutocompleteFragment) getFragmentManager().findFragmentById(
R.id.place_autocomplete_fragment);
autocompleteFragment.setOnPlaceSelectedListener(this);
}
// Callback được gợi sau khi Map đã sẵn sàng
@Override
public void onMapReady(GoogleMap googleMap) {
// do something
}
// Callback khi bạn click vào item
@Override
public void onPlaceSelected(Place place) {
// do something
}
@Override
public void onError(Status status) {
}
}
tới đây các bạn có thể chạy để xem kết quả ban đầu rồi. Nhưng mà hiện tại khi các bạn chạy ứng dụng thì mới chỉ lên được map và có thanh tìm kiếm hiện lên màn hình.
Để cho thanh tìm kiếm đẹp đẽ hơn các bạn có thể thêm
android:background="@drawable/bg_search"
trong file bg_search
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff"/>
<corners
android:radius="4dp"/>
</shape>
2. Set my location
Để lấy vị trí hiện tại bạn đang đứng mình khuyên các bạn sử dụng GoogleApiClient. Các bạn khởi tạo 2 biến GoogleApiClient, GoogleMap và implements thêm 2 Callback.
public class MainActivity extends FragmentActivity
implements OnMapReadyCallback, PlaceSelectionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient googleApiClient;
private GoogleMap googleMap;
...
@Override
public void onConnected(@Nullable Bundle bundle) {
// do something
}
@Override
public void onConnectionSuspended(int i) {
// do something when Connection Error
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
// do something when Connection Failed
}
Bây giở quay lại hàm onMapReady
(các bạn chú ý là chú ta chỉ làm mọi thứ khi map đã sẵn sàng nhé).
@Override
public void onMapReady(GoogleMap googleMap) {
// Add permission in Manifests
// <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
// <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
// Request permission if SDK > 23
buildGoogleApiClient();
this.googleMap = googleMap;
// Add icon my location
this.googleMap.setMyLocationEnabled(true);
}
...
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.build();
googleApiClient.connect();
}
Trong Callback onConnected khi GoogleApiClient kết nối thành công
@Override
public void onConnected(@Nullable Bundle bundle) {
// Check permission
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
LatLng myLatLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder().target(
myLatLng) // Sets the center of the map to Mountain View
.zoom(17) // Sets the zoom
.bearing(0) // Sets the orientation of the camera to east
.tilt(0) // Sets the tilt of the camera
.build();
googleMap.addMarker(new MarkerOptions().position(myLatLng).title("My Place"));
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
Bây giờ run
app thì sẽ được di chuyển về vị trí hiện tại của bạn.
3. Setup PlaceAutocompleteFragment
Ở phần đầu mình có set callback cho sự kiện khi click vào item của Autocomplete.
Trong Callback onPlaceSelected
private Marker marker;
...
@Override
public void onPlaceSelected(Place place) {
// remove old marker when add new marker
if (marker != null) marker.remove();
LatLng myLatLng = place.getLatLng();
marker = googleMap.addMarker(
new MarkerOptions().position(myLatLng).title(String.valueOf(place.getName())));
googleMap.animateCamera(CameraUpdateFactory.newLatLng(myLatLng));
}
PlaceAutocompleteFragment còn có nhiều lựa chọn cho gợi ý được tốt hơn:
- setBoundsBias(LatLngBounds latLngBounds);
- setFilter(AutocompleteFilter typeFilter);
setBoundsBias
nhận vào 1 LatLngBounds(LatLng southwest, LatLng northeast) cho biết giới hạn của địa điểm gợi ý.
setFilter
nhận vào 1 AutocompleteFilter để set bộ lọc cho các gợi ý được hiển thị.
// ví dụ gợi ý chỉ hiển thị các địa điểm ở Việt Nam
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setCountry("VN") // This should be a ISO 3166-1 Alpha-2 country code
.build();
autocompleteFragment.setFilter(typeFilter);
các bạn có thể thao khảo chuẩn ISO 3166-1 Alpha-2 tại đây.
Vậy là đã xong, bây giờ bạn có thể run
ứng dụng để xem kết quả, rất đơn giản có phải không nào.
Các bạn có thể tham khảo Source code tại đây
All rights reserved