Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

New MapPinDrawable dedicated to MapViews

  • Loading branch information...
commit 1fbbe494140c69402baef9356ff1c220234753cc 1 parent b64b0b5
@cyrilmottier authored
View
8 .gitignore
@@ -1,4 +1,10 @@
+## Exclude file used by compilators, interpreters, etc.
*/bin/*
*/gen/*
+*.pyc
+
+## Exclude Mac OS X files
*.DS_Store
-*.pyc
+
+## The following files contain private values
+*/res/values/p_*.xml
View
1  GDCatalog/.classpath
@@ -3,6 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="src" path="GreenDroid-GoogleAPIs_src"/>
<classpathentry kind="src" path="GreenDroid_src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
5 GDCatalog/.project
@@ -32,6 +32,11 @@
</natures>
<linkedResources>
<link>
+ <name>GreenDroid-GoogleAPIs_src</name>
+ <type>2</type>
+ <locationURI>_android_GreenDroid_GoogleAPIs_f97e4c86/src</locationURI>
+ </link>
+ <link>
<name>GreenDroid_src</name>
<type>2</type>
<locationURI>_android_GreenDroid_612cb559/src</locationURI>
View
4 GDCatalog/AndroidManifest.xml
@@ -32,6 +32,8 @@
android:theme="@style/Theme.GDCatalog"
android:name=".CatalogApplication">
+ <uses-library android:name="com.google.android.maps" />
+
<activity android:name=".CatalogActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -61,6 +63,8 @@
<activity android:name=".QuickActionActivity" />
<activity android:name=".SimpleAsyncImageViewActivity" />
<activity android:name=".AsyncImageViewListActivity" />
+
+ <activity android:name=".MapPinMapActivity" />
</application>
View
4 GDCatalog/default.properties
@@ -10,5 +10,5 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
-target=android-4
-android.library.reference.1=../GreenDroid
+target=Google Inc.:Google APIs:4
+android.library.reference.1=../GreenDroid-GoogleAPIs
View
25 GDCatalog/res/layout/map_pin.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<com.google.android.maps.MapView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/map_view"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:clickable="true"
+ android:apiKey="@string/google_map_api_key_debug" />
View
1  GDCatalog/res/values-en/strings.xml
@@ -34,6 +34,7 @@
<string name="quick_action_label">QuickAction</string>
<string name="simple_async_image_view_label">Simple AsyncImageView</string>
<string name="async_image_view_list_view_label">AsyncImageView in ListView</string>
+ <string name="map_pin_drawable_label">MapPinDrawable</string>
<string name="about">About</string>
<string name="license">License</string>
View
1  GDCatalog/res/values-fr/strings.xml
@@ -33,6 +33,7 @@
<string name="quick_action_label">Démo QuickAction</string>
<string name="simple_async_image_view_label">AsyncImageView simple</string>
<string name="async_image_view_list_view_label">AsyncImageView dans une ListView</string>
+ <string name="map_pin_drawable_label">MapPinDrawable</string>
<string name="about">A propos</string>
<string name="license">Licence</string>
View
6 GDCatalog/res/values/strings.xml
@@ -18,7 +18,10 @@
-->
<resources>
-
+
+ <!-- Release key is in the p_strings.xml file ignored by Git -->
+ <string name="google_map_api_key_debug">0IgVgWFseCoAyOOEFSXlrEhfjQE99UGBY_sh2CA</string>
+
<string name="app_name">GDCatalog</string>
<string name="app_url">http://github.com/cyrilmottier/GreenDroid</string>
@@ -34,6 +37,7 @@
<string name="quick_action_label">QuickAction</string>
<string name="simple_async_image_view_label">Simple AsyncImageView</string>
<string name="async_image_view_list_view_label">AsyncImageView in ListView</string>
+ <string name="map_pin_drawable_label">MapPinDrawable</string>
<string name="about">About</string>
<string name="license">License</string>
View
1  GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogActivity.java
@@ -41,6 +41,7 @@ protected void onCreate(Bundle savedInstanceState) {
adapter.add(createTextItem(R.string.quick_action_label, QuickActionActivity.class));
adapter.add(createTextItem(R.string.simple_async_image_view_label, SimpleAsyncImageViewActivity.class));
adapter.add(createTextItem(R.string.async_image_view_list_view_label, AsyncImageViewListActivity.class));
+ adapter.add(createTextItem(R.string.map_pin_drawable_label, MapPinMapActivity.class));
setListAdapter(adapter);
View
187 GDCatalog/src/com/cyrilmottier/android/gdcatalog/MapPinMapActivity.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDMapActivity;
+import greendroid.graphics.drawable.DrawableStateSet;
+import greendroid.graphics.drawable.MapPinDrawable;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+
+import com.google.android.maps.GeoPoint;
+import com.google.android.maps.ItemizedOverlay;
+import com.google.android.maps.MapView;
+import com.google.android.maps.OverlayItem;
+
+public class MapPinMapActivity extends GDMapActivity {
+
+ private static Random sRandom = new Random();
+
+ private static final int[] PRESSED_STATE = {
+ android.R.attr.state_pressed
+ };
+
+ //@formatter:off
+ private static final OverlayItem[] sFrance = {
+ new OverlayItem(new GeoPoint(48635600, -1510600), "Mont Saint Michel", null),
+ new OverlayItem(new GeoPoint(48856700, 2351000), "Paris", null),
+ new OverlayItem(new GeoPoint(44837400, -576100), "Bordeaux", null),
+ new OverlayItem(new GeoPoint(48593100, -647500), "Domfront", null)
+ };
+
+ private static final OverlayItem[] sEurope = {
+ new OverlayItem(new GeoPoint(55755800, 37617600), "Moscow", null),
+ new OverlayItem(new GeoPoint(59332800, 18064500), "Stockholm", null),
+ new OverlayItem(new GeoPoint(59939000, 30315800), "Saint Petersburg", null),
+ new OverlayItem(new GeoPoint(60169800, 24938200), "Helsinki", null),
+ new OverlayItem(new GeoPoint(60451400, 22268700), "Turku", null),
+ new OverlayItem(new GeoPoint(65584200, 22154700), "LuleŒ", null),
+ new OverlayItem(new GeoPoint(59438900, 24754500), "Talinn", null),
+ new OverlayItem(new GeoPoint(66498700, 25721100), "Rovaniemi", null)
+ };
+
+ private static final OverlayItem[] sUSAEastCoast = {
+ new OverlayItem(new GeoPoint(40714400, -74006000), "New York City", null),
+ new OverlayItem(new GeoPoint(39952300, -75163800), "Philadelphia", null),
+ new OverlayItem(new GeoPoint(38895100, -77036400), "Washington", null),
+ new OverlayItem(new GeoPoint(41374800, -83651300), "Bowling Green", null),
+ new OverlayItem(new GeoPoint(42331400, -83045800), "Detroit", null)
+ };
+
+ private static final OverlayItem[] sUSAWestCoast = {
+ new OverlayItem(new GeoPoint(37774900, -122419400), "San Francisco", null),
+ new OverlayItem(new GeoPoint(37770600, -119510800), "Yosemite National Park", null),
+ new OverlayItem(new GeoPoint(36878200, -121947300), "Monteray Bay", null),
+ new OverlayItem(new GeoPoint(35365800, -120849900), "Morro Bay", null),
+ new OverlayItem(new GeoPoint(34420800, -119698200), "Santa Barbara", null),
+ new OverlayItem(new GeoPoint(34052200, -118243700), "Los Angeles", null),
+ new OverlayItem(new GeoPoint(32715300, -117157300), "San Diego", null),
+ new OverlayItem(new GeoPoint(36114600, -115172800), "Las Vegas", null),
+ new OverlayItem(new GeoPoint(36220100, -116881700), "Death Valley", null),
+ new OverlayItem(new GeoPoint(36355200, -112661200), "Grand Canyon", null),
+ new OverlayItem(new GeoPoint(37289900, -113048900), "Zion National Park", null),
+ new OverlayItem(new GeoPoint(37628300, -112167700), "Bryce Canyon", null),
+ new OverlayItem(new GeoPoint(36936900, -111483800), "Lake Powell", null),
+ };
+
+ private static final OverlayItem[][] sAreas = {
+ sFrance, sEurope, sUSAEastCoast, sUSAWestCoast
+ };
+ //@formatter:on
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setActionBarContentView(R.layout.map_pin);
+
+ final MapView mapView = (MapView) findViewById(R.id.map_view);
+ mapView.setBuiltInZoomControls(true);
+
+ final Resources r = getResources();
+
+ for (int i = 0; i < sAreas.length; i++) {
+ final OverlayItem[] items = sAreas[i];
+
+ ColorStateList pinCsl = createRandomColorStateList();
+ ColorStateList dotCsl = createRandomColorStateList();
+ BasicItemizedOverlay itemizedOverlay = new BasicItemizedOverlay(new MapPinDrawable(r, pinCsl, dotCsl));
+
+ for (int j = 0; j < items.length; j++) {
+ itemizedOverlay.addOverlay(items[j]);
+ }
+
+ mapView.getOverlays().add(itemizedOverlay);
+ }
+ }
+
+ @Override
+ protected boolean isRouteDisplayed() {
+ return false;
+ }
+
+ private class BasicItemizedOverlay extends ItemizedOverlay<OverlayItem> {
+
+ private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
+
+ public BasicItemizedOverlay(Drawable defaultMarker) {
+ super(boundCenterBottom(defaultMarker));
+ }
+
+ public void addOverlay(OverlayItem overlay) {
+ mOverlays.add(overlay);
+ populate();
+ }
+
+ @Override
+ protected OverlayItem createItem(int i) {
+ return mOverlays.get(i);
+ }
+
+ @Override
+ public int size() {
+ return mOverlays.size();
+ }
+
+ @Override
+ protected boolean onTap(int index) {
+ return true;
+ }
+
+ }
+
+ private ColorStateList createRandomColorStateList() {
+
+ int[][] states = new int[2][];
+ int[] colors = new int[2];
+
+ final int randomColor = randomColor();
+
+ states[0] = PRESSED_STATE;
+ colors[0] = addRGB(randomColor, -50);
+
+ states[1] = DrawableStateSet.EMPTY_STATE_SET;
+ colors[1] = randomColor;
+
+ return new ColorStateList(states, colors);
+ }
+
+ private static final int randomColor() {
+ int r = sRandom.nextInt(256);
+ int g = sRandom.nextInt(256);
+ int b = sRandom.nextInt(256);
+ return Color.rgb(r, g, b);
+ }
+
+ private static int addRGB(int color, int amount) {
+ int r = constrain(Color.red(color) + amount, 0, 255);
+ int g = constrain(Color.green(color) + amount, 0, 255);
+ int b = constrain(Color.blue(color) + amount, 0, 255);
+ return Color.rgb(r, g, b);
+ }
+
+ public static int constrain(int amount, int low, int high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+}
View
BIN  GreenDroid-GoogleAPIs/res/drawable-hdpi/gd_map_pin_base.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  GreenDroid-GoogleAPIs/res/drawable-hdpi/gd_map_pin_dot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  GreenDroid-GoogleAPIs/res/drawable-hdpi/gd_map_pin_pin.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
217 GreenDroid-GoogleAPIs/src/greendroid/graphics/drawable/MapPinDrawable.java
@@ -0,0 +1,217 @@
+package greendroid.graphics.drawable;
+
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.LightingColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.Drawable;
+
+import com.cyrilmottier.android.greendroid.R;
+import com.google.android.maps.MapView;
+
+/**
+ * A {@link Drawable} dedicated to {@link MapView}s. A {@link MapPinDrawable}
+ * displays a rounded pin with a dot in the middle. This class lets you easily
+ * change the color of the pin as well as the dot in the center of the pin.
+ *
+ * @author Cyril Mottier
+ */
+public class MapPinDrawable extends Drawable {
+
+ private static final int COLOR_MODE_UNKNOWN = -1;
+ private static final int COLOR_MODE_COLOR = 1;
+ private static final int COLOR_MODE_COLOR_STATE_LIST = 2;
+
+ private static final Paint sClearerPaint;
+
+ static {
+ sClearerPaint = new Paint();
+ sClearerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ }
+
+ private int mColorMode = COLOR_MODE_UNKNOWN;
+ private int mPinColor;
+ private int mDotColor;
+ private ColorStateList mPinColorStateList;
+ private ColorStateList mDotColorStateList;
+
+ private int mCurrentPinColor;
+ private int mCurrentDotColor;
+
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private Paint mMapPinPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ private Bitmap mBase;
+ private Bitmap mPin;
+ private Bitmap mDot;
+ private Bitmap mMapPin;
+
+ private boolean mNeedRebuild;
+
+ /**
+ * Create a new {@link MapPinDrawable} that has a single color.
+ *
+ * @param res The application resources
+ * @param color The color of the pin/dot
+ */
+ public MapPinDrawable(Resources res, int color) {
+ this(res, color, color);
+ }
+
+ /**
+ * Create a new {@link MapPinDrawable}.
+ *
+ * @param res The application resources
+ * @param pinClor The color of the pin
+ * @param dotColor The color of the dot
+ */
+ public MapPinDrawable(Resources res, int pinColor, int dotColor) {
+ initBitmaps(res);
+ setColors(pinColor, dotColor);
+ }
+
+ /**
+ * Create a new {@link MapPinDrawable} that may change color depending on
+ * its current state.
+ *
+ * @param res The application resources
+ * @param color A {@link ColorStateList} object giving a set of colors
+ * changing depending on the current {@link Drawable}'s state
+ */
+ public MapPinDrawable(Resources res, ColorStateList color) {
+ this(res, color, color);
+ }
+
+ /**
+ * Create a new {@link MapPinDrawable} that may change color depending on
+ * its current state.
+ *
+ * @param res The application resources
+ * @param pinColor A {@link ColorStateList} object giving a set of colors
+ * for the pin changing depending on the current {@link Drawable}
+ * 's state
+ * @param dotColor A {@link ColorStateList} object giving a set of colors
+ * for the dot changing depending on the current {@link Drawable}
+ * 's state
+ */
+ public MapPinDrawable(Resources res, ColorStateList pinColor, ColorStateList dotColor) {
+ initBitmaps(res);
+ setColors(pinColor, dotColor);
+ }
+
+ private void initBitmaps(Resources res) {
+ // TODO Cyril: Share those Bitmaps between all instances of
+ // MapPinDrawable in order to save memory
+ mBase = BitmapFactory.decodeResource(res, R.drawable.gd_map_pin_base);
+ mPin = BitmapFactory.decodeResource(res, R.drawable.gd_map_pin_pin);
+ mDot = BitmapFactory.decodeResource(res, R.drawable.gd_map_pin_dot);
+ }
+
+ /**
+ * Set the color for the pin/dot
+ *
+ * @param pinClor The color of the pin
+ * @param dotColor The color of the dot
+ */
+ public void setColors(int pinColor, int dotColor) {
+ if (mColorMode != COLOR_MODE_COLOR || mPinColor != pinColor || mDotColor != dotColor) {
+ mColorMode = COLOR_MODE_COLOR;
+ mPinColor = mCurrentPinColor = pinColor;
+ mDotColor = mCurrentDotColor = dotColor;
+ mNeedRebuild = true;
+ }
+ }
+
+ /**
+ * Set the color for the pin/dot
+ *
+ * @param pinClor The color of the pin
+ * @param dotColor The color of the dot
+ */
+ public void setColors(ColorStateList pinColor, ColorStateList dotColor) {
+ if (mColorMode != COLOR_MODE_COLOR_STATE_LIST || mPinColorStateList != pinColor || mDotColorStateList != dotColor) {
+ mColorMode = COLOR_MODE_COLOR_STATE_LIST;
+ mPinColorStateList = pinColor;
+ mDotColorStateList = dotColor;
+ mNeedRebuild = true;
+ }
+ }
+
+ @Override
+ public boolean isStateful() {
+ return true;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return (mBase != null) ? mBase.getWidth() : -1;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return (mBase != null) ? mBase.getHeight() : -1;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] stateSet) {
+ if (mColorMode == COLOR_MODE_COLOR_STATE_LIST) {
+ int pinColor = (mPinColorStateList != null) ? mPinColorStateList.getColorForState(stateSet, Color.BLACK) : Color.BLACK;
+ int dotColor = (mDotColorStateList != null) ? mDotColorStateList.getColorForState(stateSet, Color.BLACK) : Color.BLACK;
+ if (mCurrentPinColor != pinColor || mCurrentDotColor != dotColor) {
+ mCurrentPinColor = pinColor;
+ mCurrentDotColor = dotColor;
+ mNeedRebuild = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mNeedRebuild) {
+
+ if (mMapPin == null) {
+ mMapPin = Bitmap.createBitmap(mBase.getWidth(), mBase.getHeight(), Bitmap.Config.ARGB_8888);
+ }
+ Canvas c = new Canvas(mMapPin);
+ c.drawRect(0, 0, mMapPin.getWidth(), mMapPin.getHeight(), sClearerPaint);
+
+ // 1 - Draw the base
+ c.drawBitmap(mBase, 0, 0, null);
+ // 2 - Draw the pin on top of it
+ mPaint.setColorFilter(new LightingColorFilter(Color.BLACK, mCurrentPinColor));
+ c.drawBitmap(mPin, 0, 0, mPaint);
+ // 3 - Draw the dot on top of everything
+ mPaint.setColorFilter(new LightingColorFilter(Color.BLACK, mCurrentDotColor));
+ c.drawBitmap(mDot, 0, 0, mPaint);
+
+ mNeedRebuild = false;
+ }
+
+ canvas.drawBitmap(mMapPin, null, getBounds(), mMapPinPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mMapPinPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mMapPinPaint.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.