15 มกราคม 2556

[Android Code] การควบคุมมุมกล้องและการกำหนดค่าสำหรับแผนที่ใน Google Maps Android API v2


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


ลืมเขียนบทความเรื่องนี้ก่อนซะงั้น ดันไปเขียน Marker ก่อน
สำหรับบทความนี้ก็จะเป็นพื้นฐานในการควบคุมมุมกล้อง
และการกำหนดค่าเบื้องต้นสำหรับแผนที่ GMapsV2


สำหรับการควบคุมมุมกล้องแผนที่ก็ไม่มีอะไรมากนัก
จะเรียกว่าต่อจากเรื่อง Animate ก็ได้ เพราะใช้ Animate
คราวนี้ก็จะเป็นการใช้คำสั่ง scrollBy, zoomIn และ zoomOut
โดยเจ้าของบล็อกขอเริ่มอธิบายจาก  scrollBy ก่อนละกัน

GoogleMap mMap = ((SupportMapFragment)getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); mMap.animateCamera(CameraUpdateFactory.scrollBy(x, y));
สำหรับคำสั่ง scrollBy จะกำหนดพิกเซล x และ y ว่าจะเลื่อนเท่าไร
โดยตัวแปร x และ y เป็นตัวแปรแบบ Float มีค่าได้ทั้ง + และ - เช่น
mMap.animateCamera(CameraUpdateFactory.scrollBy(50, -200));
จากคำสั่งนี้คือการเลื่อนมุมกล้องไปข้างบน 200 Pixels
และเลื่อนมุมกล้องไปทางขวามืออีก 50 Pixels



ต่อมาก็คือ zoomIn และ zoomOut ตรงๆตัวเลยก็คือซูมเข้าออก
สำหรับคำสั่งซูมทั้งสองคำสั่งนี้คือการซูมทีละหนึ่งระดับ
mMap.animateCamera(CameraUpdateFactory.zoomOut()); mMap.animateCamera(CameraUpdateFactory.zoomIn());

และนอกจากนี้ก็ยังมีคำสั่งซูมอีกคำสั่งหนึ่งคือ zoomBy
ใช้สำหรับกำหนดค่าว่าจะให้ซูมเข้าหรือซูมออกกี่ระดับ
mMap.animateCamera(CameraUpdateFactory.zoomBy(level));
โดยที่ค่าเป็น + คือซูมเข้า ค่าเป็น - คือซูมออก ส่วน 0 คือไม่ซูม

ต่อมาก็คือเรื่องการกำหนดค่าสำหรับแผนที่เบื้องต้น
สำหรับ GMapsV2 จะมีคลาส UISettings สำหรับกำหนดค่า
UiSettings uis = mMap.getUiSettings(); uis.setZoomControlsEnabled(state); uis.setZoomGesturesEnabled(state); uis.setRotateGesturesEnabled(state); uis.setCompassEnabled(state); uis.setTiltGesturesEnabled(state); uis.setScrollGesturesEnabled(state); uis.setMyLocationButtonEnabled(state);

setZoomControlsEnabled - เปิดปิดปุ่มซูมเข้า-ออก



setZoomGesturesEnabled - เปิดปิดการซูมด้วยสองนิ้ว

setRotateGesturesEnabled - เปิดปิดการหมุนกล้องด้วยสองนิ้ว

setCompassEnabled - เปิดปิดการแสดงเข็มทิศ (แสดงเมื่อหมุนกล้อง)



setTiltGesturesEnabled - เปิดปิดการเอียงแผนที่ (ลากสองนิ้วลงล่าง)

setScrollGesturesEnabled - เปิดปิดการซูมด้วยการ Scroll
(แตะจอสองครั้ง ครั้งที่สองแตะค้างแล้วลากขึ้นลงเพื่อซูม)

setMyLocationButtonEnabled - เปิดปิดปุ่มแสดงสถานที่ปัจจุบัน
จะแสดงก็ต่อเมื่อเรียกใช้คำสั่งแสดงตำแหน่งเครื่องบนแผนที่
mMap.setMyLocationEnabled(true);


อันนั้นเป็นวีดีโอตัวอย่างการควบคุมมุมกล้องเบื้องต้นใน GMapsV2



สำหรับการกำหนดค่ามุมกล้องพื้นฐานเหล่านี้กำหนดเป็น Boolean
โดยที่ True คือการเปิดใช้งานและ False คือการปิดใช้งาน

น่าจะเข้าใจได้ไม่ยากมากนัก ทีนี้ก็มาดูตัวอย่างกันเลยดีกว่า

Main.java



1. ประกาศ mMap และ coordinates ไว้นอกฟังก์ชัน onCreate
เพื่อให้เรียกใช้ใน Listener ของ Button ได้ (กำหนดเป็น final ก็ได้)

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

3. กำหนดให้แสดงตำแหน่งของเครื่อง ณ ปัจจุบันบนแผนที่ด้วย

4. ทำการตั้งค่าเบื้องต้นให้กับแผนที่ โดยทุกอย่างเปิดหมดยกเว้นปุ่มซูม

5. กำหนด Listener เป็น OnClickListener ให้กับ buttonUp

6. เมื่อผู้ใช้กดปุ่มให้เลื่อนมุมกล้องขึ้นไปข้างบน 200 Pixels

7. เมื่อผู้ใช้กดปุ่มให้เลื่อนมุมกล้องขึ้นไปข้างล่าง 200 Pixels

8. เมื่อผู้ใช้กดปุ่มให้เลื่อนมุมกล้องขึ้นไปทางขวามือ 200 Pixels

9. เมื่อผู้ใช้กดปุ่มให้เลื่อนมุมกล้องขึ้นไปทางซ้ายมือ 200 Pixels

10. เมื่อผู้ใช้กดปุ่มให้ซูมเข้า 1 ระดับ (คำสั่งทั้งสองบรรทัดทำงานเหมือนกัน)

11. เมื่อผู้ใช้กดปุ่มให้ซูมออก 1 ระดับ (คำสั่งทั้งสองบรรทัดทำงานเหมือนกัน)


เมื่อลองทดสอบดูก็ให้ลองควบคุมมุมกล้องด้วยปุ่มต่างๆดู



Main.java
package app.akexorcist.googlemapsv2cameracontrol;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

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.setMyLocationEnabled(true);
        
        UiSettings uis = mMap.getUiSettings();
        uis.setZoomControlsEnabled(false);
        uis.setZoomGesturesEnabled(true);
        uis.setRotateGesturesEnabled(true);
        uis.setCompassEnabled(true);
        uis.setTiltGesturesEnabled(true);
        uis.setScrollGesturesEnabled(true);
        uis.setMyLocationButtonEnabled(true);

        Button buttonUp = (Button)findViewById(R.id.buttonUp);
        buttonUp.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.scrollBy(0, -200));
            }
        });
        
        Button buttonDown = (Button)findViewById(R.id.buttonDown);
        buttonDown.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.scrollBy(0, 200));
            }
        });
        
        Button buttonLeft = (Button)findViewById(R.id.buttonLeft);
        buttonLeft.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.scrollBy(-200, 0));
            }
        });
        
        Button buttonRight = (Button)findViewById(R.id.buttonRight);
        buttonRight.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.scrollBy(200, 0));
            }
        });
        
        Button buttonZoomIn = (Button)findViewById(R.id.buttonZoomIn);
        buttonZoomIn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.zoomIn());
                // mMap.animateCamera(CameraUpdateFactory.zoomBy(1));
            }
        });
        
        Button buttonZoomOut = (Button)findViewById(R.id.buttonZoomOut);
        buttonZoomOut.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mMap.animateCamera(CameraUpdateFactory.zoomOut());
                // mMap.animateCamera(CameraUpdateFactory.zoomBy(-1));
            }
        });
    }
}

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"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:orientation="vertical"
        android:layout_margin="10dp" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal" >

            <Button
                android:id="@+id/buttonUp"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:text="U" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal" >

            <Button
                android:id="@+id/buttonLeft"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginRight="20dp"
                android:text="L" />

            <Button
                android:id="@+id/buttonRight"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="20dp"
                android:text="R" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal" >

            <Button
                android:id="@+id/buttonDown"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:text="D" />

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        android:layout_margin="10dp" >

        <Button
            android:id="@+id/buttonZoomIn"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:text="+" />

        <Button
            android:id="@+id/buttonZoomOut"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:text="-" />
    </LinearLayout>
</RelativeLayout>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.akexorcist.googlemapsv2cameracontrol"
    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.googlemapsv2cameracontrol.permission.MAPS_RECEIVE"/>
      
    <permission 
        android:name=
            "app.akexorcist.googlemapsv2cameracontrol.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.googlemapsv2cameracontrol.Main"
            android:label="@string/app_name">
            <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 Camera Control

เมื่อดาวน์โหลดตัวอย่างไป 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