15 มกราคม 2556

[Android Code] การใช้ Listener กับ Marker ใน Google Maps Android API v2


* Google Maps Android API v2 ไม่สามารถรันทดสอบบน AVD ได้ *


คราวนี้ก็ขอต่อด้วยเรื่อง Marker เหมือนเดิม แต่คราวนี้เป็นเรื่อง Listener
ซึ่งเป็นการใช้ Listener ที่มีใน Marker ซึ่งก็คือ OnMarkerClickListener
ที่เป็น Event Listener ที่ทำงานเวลาที่ผู้ใช้กดเลือกที่ Marker นั่นเอง


คงไม่ต้องอธิบายอะไรกันมากกับ Listener กันแล้วมั้ง
ก็มาดูกันเลยดีกว่าว่า OnMarkerClickListener มีอะไรบ้าง
mMap.setOnMarkerClickListener(new OnMarkerClickListener() { public boolean onMarkerClick(Marker arg0) { .... return true; } });

สำหรับ OnMarkerClickListener เหมือน OnClickListener เป๊ะๆ
ฟังก์ชันจะมีแค่ onMarkerClick ที่ทำงานเมื่อ Click บน Marker
โดยจะมีตัวแปร arg0 (แล้วแต่จะกำหนด) เป็นคลาส Marker
ซึ่งก็คือผู้ใช้จิ้มเลือก Marker ตัวไหน arg0 ก็จะเป็น Marker ตัวนั้น

ทีนี้ก็ขอข้ามมาดูตัวอย่างบทความนี้เลยดีกว่า เพราะไม่ค่อยมีอะไร

Main.java



1. ประกาศใช้คลาส GoogleMap ไว้ข้างนอกฟังก์ชัน onCreate
เพราะจะมีการเรียกใช้ mMap ใน OnMapClickListener
(หรือจะใช้วิธีประกาศให้เป็น final ก็ได้เช่นกัน แล้วแต่สะดวก)

2. กำหนดให้ mMap เป็น R.id.map ที่ได้สร้างไว้ใน Layout

3. กำหนด Listener เป็น OnMapClickListener ให้กับ mMap

4. เวลาผู้ใช้จิ้มลงบนแผนที่ก็จะทำการปักหมุดลงบนตำแหน่งนั้นๆ
พร้อมกับกำหนดข้อความของ Marker เป็นพิกัดที่ทำการปัก Marker

5. กำหนด Listener เป็น OnMarkerClickListener ให้กับ mMap
ซึ่งจะเป็นการกำหนด Listener ให้กับ Marker ที่สร้างบน mMap

6. เมื่อผู้ใช้เลือกที่ Marker บนแผนที่ก็จะลบ Marker นั้นๆออก

7. แสดงข้อความผ่าน Toast ว่า Marker อันที่เท่าไรที่ถูกลบ

8. ส่งค่าจากฟังก์ชันเป็น True เพื่อเป็นการกำหนดให้โปรแกรมว่า
Listener นี้เกิด Event ขึ้น ในกรณีที่มี Listener อื่นซ้อนก็จะไม่ทำงาน
กรณีที่กำหนดเป็น False จะทำให้เกิด Event Listener อื่นๆซ้อนกันได้


พอลองทดสอบดูก็จะพบว่าเมื่อจิ้มลงบนแผนที่ก็จะเป็นการสร้าง Marker
และเมื่อกดที่ Marker อีกครั้งก็จะเป็นการลบ Marker นั้นๆออก
และกำหนดให้มีข้อความแสดง ID ของ Marker ผ่าน Toast



โดย Marker ตัวแรกจะเริ่ม ID จาก 0 และเรียงกันไปเรื่อยๆเหมือน Array
สมมติว่า Marker มี 5 อัน ก็จะเรียงตั้งแต่ 0 ถึง 4 ตามลำดับที่สร้างขึ้นมา



Main.java
package app.akexorcist.googlemapsv2markerlistener;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.widget.Toast;

public class Main extends FragmentActivity {
    GoogleMap mMap;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mMap = ((SupportMapFragment)getSupportFragmentManager()
                .findFragmentById(R.id.map)).getMap();
        
        mMap.setOnMapClickListener(new OnMapClickListener() {
            public void onMapClick(LatLng arg0) {
                mMap.addMarker(new MarkerOptions().position(arg0)
                        .title(String.valueOf(arg0.latitude)
                        + ", " + String.valueOf(arg0.longitude)));
            }
        });
        
        mMap.setOnMarkerClickListener(new OnMarkerClickListener() {
            public boolean onMarkerClick(Marker arg0) {
                arg0.remove();
                Toast.makeText(getApplicationContext()
                        , "Remove Marker " + String.valueOf(arg0.getId())
                        , Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }
}

main.xml
<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"  >

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment"/>
    
</RelativeLayout>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.akexorcist.googlemapsv2markerlistener"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />
    
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name=
            "com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name=
            "app.akexorcist.googlemapsv2markerlistener.permission.MAPS_RECEIVE"/>
      
    <permission 
        android:name=
            "app.akexorcist.googlemapsv2markerlistener.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>
    
    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="app.akexorcist.googlemapsv2markerlistener.Main"
            android:label="@string/app_name" android:configChanges="orientation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
           android:name="com.google.android.maps.v2.API_KEY"
           android:value="your_api_key"/>
    </application>
</manifest>

สำหรับผู้ที่หลงเข้ามาอ่านคนใดที่ต้องการไฟล์ตัวย่าง
สามารถดาวน์โหลดได้จาก Google Maps V2 Marker Listener

เมื่อดาวน์โหลดตัวอย่างไป Import แล้วให้ตรวจสอบตามนี้
• ใส่ API Key ที่ไปขอจาก Google API ลงใน AndroidManifest.xml
• เลือก Library ของ google-play-services_lib ให้ตรงกับเครื่อง

อาจจะมีปัญหาพอสมควรสำหรับผู้ที่ดาวน์โหลดไปทดสอบ
เพราะว่าการใช้ Google Maps นี้มีการขอ API Key และ Library
ดังนั้นจึงควรตรวจสอบให้แน่ใจว่าได้กำหนดไว้ถูกต้องแล้ว 
และก็อย่าลืมว่าทดสอบบน AVD หรือ Emulator ไม่ได้นะ
เพราะต้องมี Play Store ซึ่ง AVD ไม่มี ทำให้แอป Force Close




เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium