2016年10月16日 星期日

Google map api demo II : CircleDemoActivity 和 SplitStreetViewPanoramaAndMapDemoActivity



public class CircleDemoActivity extends AppCompatActivity implements OnSeekBarChangeListener,
        OnMarkerDragListener, OnMapLongClickListener, OnMapReadyCallback {}

先看   onCreate()


@Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.circle_demo);

    mColorBar = (SeekBar) findViewById(R.id.hueSeekBar);
    mColorBar.setMax(HUE_MAX);
    mColorBar.setProgress(0);

    mAlphaBar = (SeekBar) findViewById(R.id.alphaSeekBar);
    mAlphaBar.setMax(ALPHA_MAX);
    mAlphaBar.setProgress(127);

    mWidthBar = (SeekBar) findViewById(R.id.widthSeekBar);
    mWidthBar.setMax(WIDTH_MAX);
    mWidthBar.setProgress(10);

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

    mClickabilityCheckbox = (CheckBox) findViewById(R.id.toggleClickability);
}

有三個   colorBar...  和一個CheckBox....

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">

    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_horizontal"        android:text="@string/properties_circle" />

    <TableLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:stretchColumns="1">// 只有一欄

        <TableRow            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_vertical">

            <TextView android:text="@string/fill_hue" />

            <SeekBar android:id="@+id/hueSeekBar" />
        </TableRow>

        <TableRow            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_vertical">

            <TextView android:text="@string/fill_alpha" />

            <SeekBar android:id="@+id/alphaSeekBar" />
        </TableRow>

        <TableRow            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_vertical">

            <TextView android:text="@string/stroke_width" />

            <SeekBar android:id="@+id/widthSeekBar" />
        </TableRow>

        <TableRow            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_vertical">

            <CheckBox                android:id="@+id/toggleClickability"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:checked="true"                android:onClick="toggleClickability"                android:text="@string/clickable"/>
        </TableRow>

    </TableLayout>

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

</LinearLayout>


先看  onMapReady()



@Overridepublic void onMapReady(GoogleMap map) {
    mMap = map;

    // Override the default content description on the view, for accessibility mode.    map.setContentDescription(getString(R.string.map_circle_description));

    mColorBar.setOnSeekBarChangeListener(this);
    mAlphaBar.setOnSeekBarChangeListener(this);
    mWidthBar.setOnSeekBarChangeListener(this);
    mMap.setOnMarkerDragListener(this);
    mMap.setOnMapLongClickListener(this);

    mFillColor = Color.HSVToColor(
            mAlphaBar.getProgress(), new float[]{mColorBar.getProgress(), 1, 1});
    mStrokeColor = Color.BLACK;

    DraggableCircle circle =
            new DraggableCircle(SYDNEY, DEFAULT_RADIUS, mClickabilityCheckbox.isChecked());
    mCircles.add(circle);

    // Move the map so that it is centered on the initial circle    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 4.0f));
    // Set up the click listener for the circle.    map.setOnCircleClickListener(new OnCircleClickListener() {
        @Override        public void onCircleClick(Circle circle) {
            // Flip the r, g and b components of the circle's stroke color.            int strokeColor = circle.getStrokeColor() ^ 0x00ffffff;
            circle.setStrokeColor(strokeColor);
        }
    });
}


private class DraggableCircle {
    private final Marker centerMarker;
    private final Marker radiusMarker;
    private final Circle circle;
    private double radius;
    public DraggableCircle(LatLng center, double radius, boolean clickable) {
        this.radius = radius;
        centerMarker = mMap.addMarker(new MarkerOptions()
                .position(center)
                .draggable(true));
        radiusMarker = mMap.addMarker(new MarkerOptions()
                .position(toRadiusLatLng(center, radius))
                .draggable(true)
                .icon(BitmapDescriptorFactory.defaultMarker(
                        BitmapDescriptorFactory.HUE_AZURE)));
        circle = mMap.addCircle(new CircleOptions()
                .center(center)
                .radius(radius)
                .strokeWidth(mWidthBar.getProgress())
                .strokeColor(mStrokeColor)
                .fillColor(mFillColor)
                .clickable(clickable));
    }

    public DraggableCircle(LatLng center, LatLng radiusLatLng, boolean clickable) {
        this.radius = toRadiusMeters(center, radiusLatLng);
        centerMarker = mMap.addMarker(new MarkerOptions()
                .position(center)
                .draggable(true));
        radiusMarker = mMap.addMarker(new MarkerOptions()
                .position(radiusLatLng)
                .draggable(true)
                .icon(BitmapDescriptorFactory.defaultMarker(
                        BitmapDescriptorFactory.HUE_AZURE)));
        circle = mMap.addCircle(new CircleOptions()
                .center(center)
                .radius(radius)
                .strokeWidth(mWidthBar.getProgress())
                .strokeColor(mStrokeColor)
                .fillColor(mFillColor)
                .clickable(clickable));
    }

    public boolean onMarkerMoved(Marker marker) {
        if (marker.equals(centerMarker)) {
            circle.setCenter(marker.getPosition());
            radiusMarker.setPosition(toRadiusLatLng(marker.getPosition(), radius));
            return true;
        }
        if (marker.equals(radiusMarker)) {
            radius = toRadiusMeters(centerMarker.getPosition(), radiusMarker.getPosition());
            circle.setRadius(radius);
            return true;
        }
        return false;
    }

    public void onStyleChange() {
        circle.setStrokeWidth(mWidthBar.getProgress());
        circle.setFillColor(mFillColor);
        circle.setStrokeColor(mStrokeColor);
    }

    public void setClickable(boolean clickable) {
        circle.setClickable(clickable);
    }
}




當常按時...新增一個circle.....

@Overridepublic void onMapLongClick(LatLng point) {
    // We know the center, let's place the outline at a point 3/4 along the view.    View view = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
            .getView();
    LatLng radiusLatLng = mMap.getProjection().fromScreenLocation(new Point(
            view.getHeight() * 3 / 4, view.getWidth() * 3 / 4));

    // ok create it    DraggableCircle circle =
            new DraggableCircle(point, radiusLatLng, mClickabilityCheckbox.isChecked());
    mCircles.add(circle);   //  新增一個  circles
}


//  當按下   checkbox  -> toggleClickability

public void toggleClickability(View view) {
    boolean clickable = ((CheckBox) view).isChecked();
    // Set each of the circles to be clickable or not, based on the    // state of the checkbox.    for (DraggableCircle draggableCircle : mCircles) {
        draggableCircle.setClickable(clickable);
    }
}



@Overridepublic void onMarkerDragStart(Marker marker) {
    onMarkerMoved(marker);
}

@Overridepublic void onMarkerDragEnd(Marker marker) {
    onMarkerMoved(marker);
}

@Overridepublic void onMarkerDrag(Marker marker) {
    onMarkerMoved(marker);
}

private void onMarkerMoved(Marker marker) {
    for (DraggableCircle draggableCircle : mCircles) {
        if (draggableCircle.onMarkerMoved(marker)) {
            break;
        }
    }
}


=======================================================================================================

public class SplitStreetViewPanoramaAndMapDemoActivity extends AppCompatActivity
        implements OnMarkerDragListener, OnStreetViewPanoramaChangeListener {}

@Overrideprotected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.split_street_view_panorama_and_map_demo);

    final LatLng markerPosition;
    if (savedInstanceState == null) {
        markerPosition = SYDNEY;
    } else {
        markerPosition = savedInstanceState.getParcelable(MARKER_POSITION_KEY);
    }

    SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
            (SupportStreetViewPanoramaFragment)
                    getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
    streetViewPanoramaFragment.getStreetViewPanoramaAsync(
            new OnStreetViewPanoramaReadyCallback() {
                @Override                public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
                    mStreetViewPanorama = panorama;
                    mStreetViewPanorama.setOnStreetViewPanoramaChangeListener(
                            SplitStreetViewPanoramaAndMapDemoActivity.this);
                    // Only need to set the position once as the streetview fragment will maintain                    // its state.                    if (savedInstanceState == null) {
                        mStreetViewPanorama.setPosition(SYDNEY);
                    }
                }
            });

    SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(new OnMapReadyCallback() {
        @Override        public void onMapReady(GoogleMap map) {
            map.setOnMarkerDragListener(SplitStreetViewPanoramaAndMapDemoActivity.this);
            // Creates a draggable marker. Long press to drag.            mMarker = map.addMarker(new MarkerOptions()
                    .position(markerPosition)
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.pegman))
                    .draggable(true));
        }
    });
}















Google map api demo I

Ref :  https://github.com/googlemaps/android-samples/tree/master/ApiDemos


Ref : https://github.com/googlemaps/android-samples/issues



先看MainActivity


public final class MainActivity extends AppCompatActivity
        implements AdapterView.OnItemClickListener{}


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView list = (ListView) findViewById(R.id.list);
ListAdapter adapter = new CustomArrayAdapter(this, DemoDetailsList.DEMOS);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
list.setEmptyView(findViewById(R.id.empty));
}

他的主畫面一進去就是一個 listview....把所有的  demp sample 列出來

然後設定 onItemClickListener...

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DemoDetails demo = (DemoDetails) parent.getAdapter().getItem(position);
startActivity(new Intent(this, demo.activityClass));
}

得道要啟動的  DemoDetails  物件,  然後  startActivity....


至於甚麼是 CustomArrayAdapter 物件

private static class CustomArrayAdapter extends ArrayAdapter<DemoDetails> {

    /**     * @param demos An array containing the details of the demos to be displayed.     */    public CustomArrayAdapter(Context context, DemoDetails[] demos) {
        super(context, R.layout.feature, R.id.title, demos);
    }

    @Override    public View getView(int position, View convertView, ViewGroup parent) {
        FeatureView featureView;
        if (convertView instanceof FeatureView) {
            featureView = (FeatureView) convertView;
        } else {
            featureView = new FeatureView(getContext());
        }

        DemoDetails demo = getItem(position);

        featureView.setTitleId(demo.titleId);
        featureView.setDescriptionId(demo.descriptionId);

        Resources resources = getContext().getResources();
        String title = resources.getString(demo.titleId);
        String description = resources.getString(demo.descriptionId);
        featureView.setContentDescription(title + ". " + description);

        return featureView;
    }
}


至於甚麼是 DemoDetails

public class DemoDetails {
    /**     * The resource id of the title of the demo.     */    public final int titleId;

    /**     * The resources id of the description of the demo.     */    public final int descriptionId;

    /**     * The demo activity's class.     */    public final Class<? extends AppCompatActivity> activityClass;

    public DemoDetails(
            int titleId, int descriptionId, Class<? extends AppCompatActivity> activityClass) {
        this.titleId = titleId;
        this.descriptionId = descriptionId;
        this.activityClass = activityClass;
    }
}


裡面的成員變數就是

public final int titleId;

/** * The resources id of the description of the demo. */public final int descriptionId;

/** * The demo activity's class. */public final Class<? extends AppCompatActivity> activityClass;


其實就是新增一個物件...然後把這三個東西存到這個物件


至於在那裏初始化這些 calss name

重點就在這一行

ListAdapter adapter = new CustomArrayAdapter(this, DemoDetailsList.DEMOS);


他用了 static 這個關鍵字...也就是說不需要去新增她....他就已經存在程式裡面


public final class DemoDetailsList {

    /** This class should not be instantiated. */    private DemoDetailsList() {
    }

    public static final DemoDetails[] DEMOS = {
            new DemoDetails(R.string.basic_map_demo_label,
                    R.string.basic_map_demo_description,
                    BasicMapDemoActivity.class),
            new DemoDetails(R.string.camera_demo_label,
                    R.string.camera_demo_description,
                    CameraDemoActivity.class),
            new DemoDetails(R.string.camera_clamping_demo_label,
                    R.string.camera_clamping_demo_description,
                    CameraClampingDemoActivity.class),
            new DemoDetails(R.string.circle_demo_label,
                    R.string.circle_demo_description,
                    CircleDemoActivity.class),
            new DemoDetails(R.string.events_demo_label,
                    R.string.events_demo_description,
                    EventsDemoActivity.class),
            new DemoDetails(R.string.ground_overlay_demo_label,
                    R.string.ground_overlay_demo_description,
                    GroundOverlayDemoActivity.class),
            new DemoDetails(R.string.indoor_demo_label,
                    R.string.indoor_demo_description,
                    IndoorDemoActivity.class),
            new DemoDetails(R.string.layers_demo_label,
                    R.string.layers_demo_description,
                    LayersDemoActivity.class),
            new DemoDetails(R.string.lite_demo_label,
                    R.string.lite_demo_description,
                    LiteDemoActivity.class),
            new DemoDetails(R.string.lite_list_demo_label,
                    R.string.lite_list_demo_description,
                    LiteListDemoActivity.class),
            new DemoDetails(R.string.location_source_demo_label,
                    R.string.location_source_demo_description,
                    LocationSourceDemoActivity.class),
            new DemoDetails(R.string.map_in_pager_demo_label,
                    R.string.map_in_pager_demo_description,
                    MapInPagerDemoActivity.class),
            new DemoDetails(R.string.marker_demo_label,
                    R.string.marker_demo_description,
                    MarkerDemoActivity.class),
            new DemoDetails(R.string.multi_map_demo_label,
                    R.string.multi_map_demo_description,
                    MultiMapDemoActivity.class),
            new DemoDetails(R.string.my_location_demo_label,
                    R.string.my_location_demo_description,
                    MyLocationDemoActivity.class),
            new DemoDetails(R.string.options_demo_label,
                    R.string.options_demo_description,
                    OptionsDemoActivity.class),
            new DemoDetails(R.string.polygon_demo_label,
                    R.string.polygon_demo_description,
                    PolygonDemoActivity.class),
            new DemoDetails(R.string.polyline_demo_label,
                    R.string.polyline_demo_description,
                    PolylineDemoActivity.class),
            new DemoDetails(R.string.programmatic_demo_label,
                    R.string.programmatic_demo_description,
                    ProgrammaticDemoActivity.class),
            new DemoDetails(R.string.raw_map_view_demo_label,
                    R.string.raw_map_view_demo_description,
                    RawMapViewDemoActivity.class),
            new DemoDetails(R.string.retain_map_demo_label,
                    R.string.retain_map_demo_description,
                    RetainMapDemoActivity.class),
            new DemoDetails(R.string.save_state_demo_label,
                    R.string.save_state_demo_description,
                    SaveStateDemoActivity.class),
            new DemoDetails(R.string.snapshot_demo_label,
                    R.string.snapshot_demo_description,
                    SnapshotDemoActivity.class),
            new DemoDetails(R.string.split_street_view_panorama_and_map_demo_label,
                    R.string.split_street_view_panorama_and_map_demo_description,
                    SplitStreetViewPanoramaAndMapDemoActivity.class),
            new DemoDetails(R.string.street_view_panorama_basic_demo_label,
                    R.string.street_view_panorama_basic_demo_description,
                    StreetViewPanoramaBasicDemoActivity.class),
            new DemoDetails(R.string.street_view_panorama_events_demo_label,
                    R.string.street_view_panorama_events_demo_description,
                    StreetViewPanoramaEventsDemoActivity.class),
            new DemoDetails(R.string.street_view_panorama_navigation_demo_label,
                    R.string.street_view_panorama_navigation_demo_description,
                    StreetViewPanoramaNavigationDemoActivity.class),
            new DemoDetails(R.string.street_view_panorama_options_demo_label,
                    R.string.street_view_panorama_options_demo_description,
                    StreetViewPanoramaOptionsDemoActivity.class),
            new DemoDetails(R.string.street_view_panorama_view_demo_label,
                    R.string.street_view_panorama_view_demo_description,
                    StreetViewPanoramaViewDemoActivity.class),
            new DemoDetails(R.string.styled_map_demo_label,
                    R.string.styled_map_demo_description,
                    StyledMapDemoActivity.class),
            new DemoDetails(R.string.tile_coordinate_demo_label,
                    R.string.tile_coordinate_demo_description,
                    TileCoordinateDemoActivity.class),
            new DemoDetails(R.string.tile_overlay_demo_label,
                    R.string.tile_overlay_demo_description,
                    TileOverlayDemoActivity.class),
            new DemoDetails(R.string.ui_settings_demo_label,
                    R.string.ui_settings_demo_description,
                    UiSettingsDemoActivity.class),
            new DemoDetails(R.string.visible_region_demo_label,
                    R.string.visible_region_demo_description,
                    VisibleRegionDemoActivity.class),
    };
}


接下來看最簡單的BasicMapDemo

其實重點就是


public class BasicMapDemoActivity extends AppCompatActivity implements OnMapReadyCallback {

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

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

    /**     * This is where we can add markers or lines, add listeners or move the camera. In this case,     * we     * just add a marker near Africa.     */    @Override    public void onMapReady(GoogleMap map) {
        map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }
}


先看 basic_demo.xml   

裡面就是一個 fragment..   class 為  com.google.android.gms.maps.SupportMapFragment

<fragment xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/map"    android:layout_width="match_parent"    android:layout_height="match_parent"    class="com.google.android.gms.maps.SupportMapFragment" />


然後繼承了 OnMapReadyCallback   interface....

實作   onMapReady


新增一個  (0,0) 的經緯度的 Marker ....

 @Override    public void onMapReady(GoogleMap map) {
        map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }



接下來看 Camera Demo 的範例


public class CameraDemoActivity extends AppCompatActivity implements        OnCameraMoveStartedListener,
        OnCameraMoveListener,
        OnCameraMoveCanceledListener,
        OnCameraIdleListener,
        OnMapReadyCallback {


}


首先先看  CameraDemoActivity..   他繼承了很多  interface...


@Overridepublic void onMapReady(GoogleMap map) {
    mMap = map;

    mMap.setOnCameraIdleListener(this);
    mMap.setOnCameraMoveStartedListener(this);
    mMap.setOnCameraMoveListener(this);
    mMap.setOnCameraMoveCanceledListener(this);

    // We will provide our own zoom controls.    mMap.getUiSettings().setZoomControlsEnabled(false);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);

    // Show Sydney    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
}


先來看 onCreate()

@Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_demo);

    mAnimateToggle = (CompoundButton) findViewById(R.id.animate);
    mCustomDurationToggle = (CompoundButton) findViewById(R.id.duration_toggle);
    mCustomDurationBar = (SeekBar) findViewById(R.id.duration_bar);

    updateEnabledState();

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

再來看layout....   camera_demo.xml





<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">

    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"> //   水平排列

        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:orientation="vertical">

            <Button                android:id="@+id/stop_animation"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:onClick="onStopAnimation"                android:text="@string/stop_animation" />

            <ToggleButton                android:id="@+id/animate"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:checked="true"                android:onClick="onToggleAnimate"                android:textOn="@string/animate"                android:textOff="@string/animate" />
        </LinearLayout>

        <RelativeLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:gravity="center_horizontal"            android:layout_weight="1">

            <Button                android:id="@+id/scroll_left"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onScrollLeft"                android:layout_alignParentLeft="true"                android:layout_centerVertical="true"                android:text="@string/left_arrow" />

            <Button                android:id="@+id/scroll_up"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onScrollUp"                android:layout_alignParentTop="true"                android:layout_toRightOf="@id/scroll_left"                android:text="@string/up_arrow" />

            <Button                android:id="@+id/scroll_down"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onScrollDown"                android:layout_below="@id/scroll_up"                android:layout_toRightOf="@id/scroll_left"                android:text="@string/down_arrow" />

            <Button                android:id="@+id/scroll_right"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onScrollRight"                android:layout_centerVertical="true"                android:layout_toRightOf="@id/scroll_down"                android:text="@string/right_arrow" />
        </RelativeLayout>

        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_gravity="right"            android:orientation="vertical">

            <Button                android:id="@+id/zoom_in"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onZoomIn"                android:text="@string/zoom_in" />

            <Button                android:id="@+id/zoom_out"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:onClick="onZoomOut"                android:text="@string/zoom_out" />
        </LinearLayout>

        <LinearLayout            android:orientation="vertical"            android:layout_width="wrap_content"            android:layout_height="fill_parent"            android:layout_gravity="right">

            <Button                android:id="@+id/tilt_more"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:text="@string/tilt_more"                android:onClick="onTiltMore" />

            <Button                android:id="@+id/tilt_less"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:minWidth="48dp"                android:text="@string/tilt_less"                android:onClick="onTiltLess" />
        </LinearLayout>
    </LinearLayout>

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

        <CheckBox            android:id="@+id/duration_toggle"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="onToggleCustomDuration"            android:text="@string/duration" />

        <SeekBar            android:id="@+id/duration_bar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"            android:max="5000" />
    </LinearLayout>

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

        <Button            android:id="@+id/sydney"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:onClick="onGoToSydney"            android:layout_weight="0.5"            android:text="@string/go_to_sydney" />

        <Button            android:id="@+id/bondi"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:onClick="onGoToBondi"            android:layout_weight="0.5"            android:text="@string/go_to_bondi" />
    </LinearLayout>

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



重點已經用紅色的字標起來了


先來看 onGoToBondi

/** * Called when the Go To Bondi button is clicked. */public void onGoToBondi(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.newCameraPosition(BONDI));
}

其實就是把鏡頭移到 BONDI  這個 position...

BONDI \和   SYDNEY 這兩個  CameraPosition  的定義如下:




public static final CameraPosition BONDI =
        new CameraPosition.Builder().target(new LatLng(-33.891614, 151.276417))
                .zoom(15.5f)
                .bearing(300)
                .tilt(50)
                .build();

public static final CameraPosition SYDNEY =
        new CameraPosition.Builder().target(new LatLng(-33.87365, 151.20689))
                .zoom(15.5f)
                .bearing(0)
                .tilt(25)
                .build();


接下來看 onGoToSydney()

把作標點改成  SYDNEY.   然後加入新的   CancelableCallback   interface

/** * Called when the Animate To Sydney button is clicked. */public void onGoToSydney(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.newCameraPosition(SYDNEY), new CancelableCallback() {
        @Override        public void onFinish() {
            Toast.makeText(getBaseContext(), "Animation to Sydney complete", Toast.LENGTH_SHORT)
                    .show();
        }

        @Override        public void onCancel() {
            Toast.makeText(getBaseContext(), "Animation to Sydney canceled", Toast.LENGTH_SHORT)
                    .show();
        }
    });
}


接下來看 上下左右四個function

onScrollLeft ()  , onScrollDown(), onScrollUp(),  onScrollRight()



public void onScrollLeft(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.scrollBy(-SCROLL_BY_PX, 0));
}

public void onScrollRight(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.scrollBy(SCROLL_BY_PX, 0));
}

public void onScrollUp(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.scrollBy(0, -SCROLL_BY_PX));
}

/** * Called when the down arrow button is clicked. This causes the camera to move down. */public void onScrollDown(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.scrollBy(0, SCROLL_BY_PX));
}


private static final int SCROLL_BY_PX = 100;


changeCamera() 的實作如下:

private void changeCamera(CameraUpdate update) {
    changeCamera(update, null);
}


private void changeCamera(CameraUpdate update, CancelableCallback callback) {
    if (mAnimateToggle.isChecked()) {  // 看有沒有打開   animate 的 option
        if (mCustomDurationToggle.isChecked()) {
            int duration = mCustomDurationBar.getProgress();
            // The duration must be strictly positive so we make it at least 1.            mMap.animateCamera(update, Math.max(duration, 1), callback);
        } else {
            mMap.animateCamera(update, callback);
        }
    } else {
        mMap.moveCamera(update);
    }
}


 
接下來再來看  onZoomIn() 和  onZoomOut()


public void onZoomIn(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.zoomIn());
}

/** * Called when the zoom out button (the one with the -) is clicked. */public void onZoomOut(View view) {
    if (!checkReady()) {
        return;
    }

    changeCamera(CameraUpdateFactory.zoomOut());
}


接下來看    onTiltMore()  和  onTiltLess()




/** * Called when the tilt more button (the one with the /) is clicked. */public void onTiltMore(View view) {
    if (!checkReady()) {
        return;
    }

    CameraPosition currentCameraPosition = mMap.getCameraPosition();
    float currentTilt = currentCameraPosition.tilt;
    float newTilt = currentTilt + 10;

    newTilt = (newTilt > 90) ? 90 : newTilt;

    CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition)
            .tilt(newTilt).build();

    changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

/** * Called when the tilt less button (the one with the \) is clicked. */public void onTiltLess(View view) {
    if (!checkReady()) {
        return;
    }

    CameraPosition currentCameraPosition = mMap.getCameraPosition();

    float currentTilt = currentCameraPosition.tilt;

    float newTilt = currentTilt - 10;
    newTilt = (newTilt > 0) ? newTilt : 0;

    CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition)
            .tilt(newTilt).build();

    changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}


首先呼叫 mMap.getCameraPosition()  來得到   currentCameraPosition  (類別型態為 CameraPosition )   

然後抓出     currentCameraPosition.currentTilt

然後去改變他
 float newTilt = currentTilt - 10;
    newTilt = (newTilt > 0) ? newTilt : 0;

然後重新去新建一個  CameraPosition....在呼叫  changeCamera()


 CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition)
            .tilt(newTilt).build();

 changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));




接下來看跟 animate 有關的

             "onStopAnimation"             "onToggleAnimate"



/** * Called when the animate button is toggled */public void onToggleAnimate(View view) {
    updateEnabledState();
}

/** * Update the enabled state of the custom duration controls. */private void updateEnabledState() {
    mCustomDurationToggle.setEnabled(mAnimateToggle.isChecked());
    mCustomDurationBar            .setEnabled(mAnimateToggle.isChecked() && mCustomDurationToggle.isChecked());
}

/** * Called when the stop button is clicked. */public void onStopAnimation(View view) {
    if (!checkReady()) {
        return;
    }

    mMap.stopAnimation(); //  直接呼叫  stopAnimation()
}