Membuat Overlay Marker Animation Map menggunakan Android

Google Map memungkinkan seseorang menemukan dan menentukan lokasi tertentu dengan mudah berdasarkan kategori seperti: perusahaan, tempat menarik, lokasi geografis, dan lainnya, hanya memalui smartphone atau melalui komputer untuk sebuah lokasi yang diinginkan.

Tutorial ini membuat overlay marker animation dimana marker hanya diposisi tengah dari Activity dan tidak bisa digerakan dari posisinya tersebut, jadi untuk menentukan Latitude dan Longitude dari koordinat lokasi dengan menggerakan bagian area Map.

Marker juga disertai dengan animation progress untuk mengambil koordinat lokasi dan menentukan jarak dari lokasi tersebut.

Sebelum Anda mulai membuat proyek, Anda membutuhkan API keys supaya aplikasi dapat berjalan dengan Google Maps, untuk membuat Google Maps API key disini.

Menyiapkan Proyek

Langkah pertama masukan dependencies dibagian file build gradle

implementation 'com.google.android.gms:play-services-maps:16.1.0'

Langkah Membuat Proyek

Bagian Manifests Masukan Api Keys dibagain value dari metadata.

.....
<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="YOU HERE KEYS" />
.....

Bagian res -> value -> dimens.xml tambahkan resource dimen.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="circle_radius">48dp</dimen>
    <dimen name="line_width">4dp</dimen>
    <dimen name="line_height">40dp</dimen>
    <dimen name="stroke_width">3dp</dimen>
    <dimen name="text_size">10sp</dimen>
    <dimen name="inner_circle_radius">40dp</dimen>
    <dimen name="inner_circle_margin">4dp</dimen>
    <dimen name="line_top_margin">20dp</dimen>
</resources>

Membuat design lingkaran, buat dibagian drawable berikan nama circle_background.xml.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@android:color/white" />
    <stroke
        android:width="@dimen/stroke_width"
        android:color="@android:color/holo_red_light" />
    <size
        android:width="@dimen/circle_radius"
        android:height="@dimen/circle_radius" />
</shape>

Langkah yang sama tambahkan lagi dibagian drawable berikan nama circle_background_moving.xml.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
    <solid android:color="@android:color/white"/>
    <size android:width="@dimen/circle_radius" android:height="@dimen/circle_radius"/>
</shape>

Terakhir dibagian drawable tambahkan garis secara horizontal sebagai penunjuk marker berikan nama line_background.xml.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="@android:color/holo_red_light"/>
    <size android:width="@dimen/line_width" android:height="@dimen/line_height"/>
</shape>

Membuat design activity untuk menampilkan map dan menampilkan posisi dari marker.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MapsActivity"/>

    <FrameLayout
        android:id="@+id/pin_view_line"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="@dimen/line_top_margin"
        android:background="@drawable/line_background"/>

    <FrameLayout
        android:id="@+id/pin_view_circle"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/circle_background_moving">

        <TextView
            android:id="@+id/textView"
            android:layout_margin="@dimen/inner_circle_margin"
            android:layout_width="@dimen/inner_circle_radius"
            android:layout_height="@dimen/inner_circle_radius"
            android:layout_gravity="top|center_horizontal"
            android:gravity="center"
            android:text="3 min"
            android:textSize="@dimen/text_size"
            android:textColor="@android:color/black"/>

        <ProgressBar
            android:id="@+id/profile_loader"
            android:layout_margin="@dimen/inner_circle_margin"
            android:layout_width="@dimen/inner_circle_radius"
            android:layout_height="@dimen/inner_circle_radius"
            android:indeterminate="true"
            android:layout_gravity="top|center_horizontal"
            android:visibility="gone"
            android:contentDescription="@null"/>

    </FrameLayout>
</FrameLayout>

Selanjutnnya anda masuk dibagian java class anda harus menambahkan method prosedure untuk mengubah ukuran dari layout lingkaran.

private void resizeLayout(boolean backToNormalSize) {
    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) circleFrameLayout.getLayoutParams();

    ViewTreeObserver vto = circleFrameLayout.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            circleFrameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            circleRadius = circleFrameLayout.getMeasuredWidth();
        }
    });

    if (backToNormalSize) {
        params.width = WRAP_CONTENT;
        params.height = WRAP_CONTENT;
        params.topMargin = 0;
    } else {
        params.topMargin = (int) (circleRadius * 0.3);
        params.height = circleRadius - circleRadius / 3;
        params.width = circleRadius - circleRadius / 3;
    }

    circleFrameLayout.setLayoutParams(params);
}

Membuat method untuk memindahkan map camera

private void moveMapCamera() {
    if (mGoogleMap == null) {
        return;
    }

    CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(-8.594277, 116.113241));
    CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);

    mGoogleMap.moveCamera(center);
    mGoogleMap.animateCamera(zoom);
}

Proses dimana pengguna mulai memindahkan map

mGoogleMap.setOnCameraMoveStartedListener(i -> {
    isMoving = true;
    textView.setVisibility(View.GONE);
    progress.setVisibility(View.GONE);
    Drawable mDrawable;
    if (Build.VERSION.SDK_INT >= 21)
        mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving, null);
    else
        mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving);

    circleFrameLayout.setBackground(mDrawable);
    resizeLayout(false);
});

Proses dimana pengguna berhenti memindahkan map

mGoogleMap.setOnCameraIdleListener(() -> {
    isMoving = false;
    textView.setVisibility(View.INVISIBLE);
    progress.setVisibility(View.VISIBLE);
    resizeLayout(true);

    / * ini hanya contoh yang mensimulasikan pemuatan data
        Anda harus menggantinya dengan logika Anda
    * /
    new Handler().postDelayed(() -> {
    Drawable mDrawable;
        if (Build.VERSION.SDK_INT >= 21)
            mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background, null);
        else
            mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background);

            if (!isMoving) {
                circleFrameLayout.setBackground(mDrawable);
                textView.setVisibility(View.VISIBLE);
                progress.setVisibility(View.GONE);
            }
    }, 1500);
});

Jika langkah-langkah diatas sudah diikuti dengan benar untuk source code lengkapnya seperti dibawah

package com.kodetr.googlemap;

import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.LatLng;

import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;
    private FrameLayout frameLayout, circleFrameLayout;
    private ProgressBar progress;
    private TextView textView;
    private int circleRadius;
    private boolean isMoving = false;
    private SupportMapFragment mapFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        initViews();
    }

    private void initViews() {
        frameLayout = findViewById(R.id.map_container);

        circleFrameLayout = frameLayout.findViewById(R.id.pin_view_circle);
        textView = circleFrameLayout.findViewById(R.id.textView);
        progress = circleFrameLayout.findViewById(R.id.profile_loader);

        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

    }

    private void moveMapCamera() {
        if (mGoogleMap == null) {
            return;
        }

        CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(-8.594277, 116.113241));
        CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);

        mGoogleMap.moveCamera(center);
        mGoogleMap.animateCamera(zoom);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        
        mGoogleMap.setOnCameraMoveStartedListener(i -> {
            isMoving = true;
            textView.setVisibility(View.GONE);
            progress.setVisibility(View.GONE);
            Drawable mDrawable;
            if (Build.VERSION.SDK_INT >= 21)
                mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving, null);
            else
                mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving);

            circleFrameLayout.setBackground(mDrawable);
            resizeLayout(false);
        });
        
        mGoogleMap.setOnCameraIdleListener(() -> {

            isMoving = false;
            textView.setVisibility(View.INVISIBLE);
            progress.setVisibility(View.VISIBLE);
            resizeLayout(true);
            
            new Handler().postDelayed(() -> {

                Drawable mDrawable;
                if (Build.VERSION.SDK_INT >= 21)
                    mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background, null);
                else
                    mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background);

                if (!isMoving) {
                    circleFrameLayout.setBackground(mDrawable);
                    textView.setVisibility(View.VISIBLE);
                    progress.setVisibility(View.GONE);
                }
            }, 1500);
        });

        MapsInitializer.initialize(this);
        moveMapCamera();
    }
 
    private void resizeLayout(boolean backToNormalSize) {
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) circleFrameLayout.getLayoutParams();

        ViewTreeObserver vto = circleFrameLayout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                circleFrameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                circleRadius = circleFrameLayout.getMeasuredWidth();
            }
        });

        if (backToNormalSize) {
            params.width = WRAP_CONTENT;
            params.height = WRAP_CONTENT;
            params.topMargin = 0;

        } else {
            params.topMargin = (int) (circleRadius * 0.3);
            params.height = circleRadius - circleRadius / 3;
            params.width = circleRadius - circleRadius / 3;
        }

        circleFrameLayout.setLayoutParams(params);
    }
}

Hasil Output

Hasil akhirnya anda bisa lihat gambar dibawah dengan marker posisi tengah dengan menentukan posisi kordinat dengan cara menggeser area pada map.

Demikian yang dapat saya sampaikan dari artikel ini semoga bermanfaat, jika anda mengalami kesulitan anda bisa melihat vidio yang sudah disediakan atau melalui komentar dibawah, selamat mencoba.

Share Comments
comments powered by Disqus