2013年4月25日 星期四
[Android] ScalableImageView
/*
* Stan 2013/04/25
* ver 2.0.8
*/
package com.stan.libs.imageview.scalable;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
/*
* @author: Stan
*/
public class StanScalableImageView extends ImageView {
private Matrix matrix = new Matrix();
// mode can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
private static final int CLICK = 3;
// Remember some things
private PointF last = new PointF();
private PointF start = new PointF();
private float minScale = 1f;// default
private float maxScale = 3f;// default
private float minScaleTemp;// measure
private float maxScaleTemp;// measure
private float[] m;
private float redundantXSpace, redundantYSpace;
private float width, height;
private float nowScale = 1f;
private float origWidth, origHeight, imageWidth, imageHeight,
redundantWidth, redundantHeight;
private boolean fit = false;
private ScaleGestureDetector mScaleDetector;
public StanScalableImageView(Context context) {
super(context);
initStanScalableImageView(context);
}
public StanScalableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
initStanScalableImageView(context);
}
public StanScalableImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
initStanScalableImageView(context);
}
private void initStanScalableImageView(Context context) {
super.setScaleType(ScaleType.CENTER);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new DragListener());
}
@Override
public void setImageBitmap(Bitmap bitmap) {
super.setImageBitmap(bitmap);
imageWidth = bitmap.getWidth();
imageHeight = bitmap.getHeight();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
imageWidth = drawable.getIntrinsicWidth();
imageHeight = drawable.getIntrinsicHeight();
}
@Override
public void setImageResource(int resourceID) {
super.setImageResource(resourceID);
imageWidth = getResources().getDrawable(resourceID).getIntrinsicWidth();
imageHeight = getResources().getDrawable(resourceID)
.getIntrinsicHeight();
}
public void setMaxZoom(float x) {
this.maxScale = x;
}
public void setMinZoom(float x) {
this.minScale = x;
}
public void setFit(boolean fit) {
this.fit = fit;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
float scale;
if (fit) {
float scaleX = (float) width / (float) imageWidth;
float scaleY = (float) height / (float) imageHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
} else {
scale = 1;
}
minScaleTemp = minScale * scale;
maxScaleTemp = maxScale * scale;
setImageMatrix(matrix);
nowScale = scale;
// Center the image
redundantHeight = (scale * (float) imageHeight);
redundantWidth = (scale * (float) imageWidth);
redundantYSpace = (float) height - (scale * (float) imageHeight);
redundantXSpace = (float) width - redundantWidth;
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
matrix.postTranslate(redundantXSpace - x, redundantYSpace - y);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
setImageMatrix(matrix);
}
private class DragListener implements OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
if (nowScale * imageWidth > width * 1.05
|| nowScale * imageHeight > height * 1.05) {
mode = DRAG;
}
break;
case MotionEvent.ACTION_MOVE:
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
if (mode == DRAG) {
float scaleWidth = Math.round(imageWidth * nowScale);
float scaleHeight = Math.round(imageHeight * nowScale);
// x
if (scaleWidth < width) {
deltaX = redundantXSpace - x
- (imageWidth * nowScale - redundantWidth) / 2;
} else {
if (deltaX > 0 && x + deltaX > 0) {
deltaX = -x;
} else if (deltaX < 0
&& x + deltaX + scaleWidth < width) {
deltaX = width - x - scaleWidth;
}
}
// y
if (scaleHeight < height) {
deltaY = redundantYSpace - y
- (imageHeight * nowScale - redundantHeight)
/ 2;
} else {
if (deltaY > 0 && y + deltaY > 0) {
deltaY = -y;
} else if (deltaY < 0
&& y + deltaY + scaleHeight < height) {
deltaY = height - y - scaleHeight;
}
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true;
}
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
last.set(detector.getFocusX(), detector.getFocusY());
start.set(last);
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = nowScale;
nowScale *= mScaleFactor;
if (nowScale > maxScaleTemp) {
nowScale = maxScaleTemp;
mScaleFactor = maxScaleTemp / origScale;
} else if (nowScale < minScaleTemp) {
nowScale = minScaleTemp;
mScaleFactor = minScaleTemp / origScale;
}
if (origWidth * nowScale <= width
|| origHeight * nowScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2,
height / 2);
} else {
matrix.postScale(mScaleFactor, mScaleFactor,
detector.getFocusX(), detector.getFocusY());
}
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
float scaleWidth = Math.round(imageWidth * nowScale);
float scaleHeight = Math.round(imageHeight * nowScale);
if (nowScale < origScale) {
if (x > 0 && x + scaleWidth > width) {
matrix.postTranslate(-x, 0);
} else if (x < 0 && x + scaleWidth < width) {
matrix.postTranslate(width - x - scaleWidth, 0);
} else if (x > 0 && x + scaleWidth < width) {
matrix.postTranslate((width - scaleWidth) / 2 - x, 0);
}
if (y > 0 && y + scaleHeight > height) {
matrix.postTranslate(0, -y);
} else if (y < 0 && y + scaleHeight < height) {
matrix.postTranslate(0, height - y - scaleHeight);
} else if (y > 0 && y + scaleHeight < height) {
matrix.postTranslate(0, (height - scaleHeight) / 2 - y);
}
}
PointF curr = new PointF(detector.getFocusX(), detector.getFocusY());
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
last.set(curr.x, curr.y);
// x
if (scaleWidth < width) {
deltaX = redundantXSpace - x
- (imageWidth * nowScale - redundantWidth) / 2;
return true;
} else {
if (deltaX > 0 && x + deltaX > 0) {
deltaX = -x;
} else if (deltaX < 0 && x + deltaX + scaleWidth < width) {
deltaX = width - x - scaleWidth;
}
}
// y
if (scaleHeight < height) {
deltaY = redundantYSpace - y
- (imageHeight * nowScale - redundantHeight) / 2;
return true;
} else {
if (deltaY > 0 && y + deltaY > 0) {
deltaY = -y;
} else if (deltaY < 0 && y + deltaY + scaleHeight < height) {
deltaY = height - y - scaleHeight;
}
}
matrix.postTranslate(deltaX, deltaY);
return true;
}
}
}
2013年4月24日 星期三
[Android]支援雙指手勢放大縮小移動的ImageView
/* * Stan 2013/04/25 * ver 2.0.8 */ package com.stan.libs.imageview.scalable; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.widget.ImageView; /* * @author: Stan */ public class StanScalableImageView extends ImageView { private Matrix matrix = new Matrix(); // mode can be in one of these 3 states private static final int NONE = 0; private static final int DRAG = 1; private static final int ZOOM = 2; private int mode = NONE; private static final int CLICK = 3; // Remember some things private PointF last = new PointF(); private PointF start = new PointF(); private float minScale = 1f;// default private float maxScale = 3f;// default private float minScaleTemp;// measure private float maxScaleTemp;// measure private float[] m; private float redundantXSpace, redundantYSpace; private float width, height; private float nowScale = 1f; private float origWidth, origHeight, imageWidth, imageHeight, redundantWidth, redundantHeight; private boolean fit = false; private ScaleGestureDetector mScaleDetector; public StanScalableImageView(Context context) { super(context); initStanScalableImageView(context); } public StanScalableImageView(Context context, AttributeSet attrs) { super(context, attrs); initStanScalableImageView(context); } public StanScalableImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initStanScalableImageView(context); } private void initStanScalableImageView(Context context) { super.setScaleType(ScaleType.CENTER); mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); matrix.setTranslate(1f, 1f); m = new float[9]; setImageMatrix(matrix); setScaleType(ScaleType.MATRIX); setOnTouchListener(new DragListener()); } @Override public void setImageBitmap(Bitmap bitmap) { super.setImageBitmap(bitmap); imageWidth = bitmap.getWidth(); imageHeight = bitmap.getHeight(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); imageWidth = drawable.getIntrinsicWidth(); imageHeight = drawable.getIntrinsicHeight(); } @Override public void setImageResource(int resourceID) { super.setImageResource(resourceID); imageWidth = getResources().getDrawable(resourceID).getIntrinsicWidth(); imageHeight = getResources().getDrawable(resourceID) .getIntrinsicHeight(); } public void setMaxZoom(float x) { this.maxScale = x; } public void setMinZoom(float x) { this.minScale = x; } public void setFit(boolean fit) { this.fit = fit; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); float scale; if (fit) { float scaleX = (float) width / (float) imageWidth; float scaleY = (float) height / (float) imageHeight; scale = Math.min(scaleX, scaleY); matrix.setScale(scale, scale); } else { scale = 1; } minScaleTemp = minScale * scale; maxScaleTemp = maxScale * scale; setImageMatrix(matrix); nowScale = scale; // Center the image redundantHeight = (scale * (float) imageHeight); redundantWidth = (scale * (float) imageWidth); redundantYSpace = (float) height - (scale * (float) imageHeight); redundantXSpace = (float) width - redundantWidth; redundantYSpace /= (float) 2; redundantXSpace /= (float) 2; matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; matrix.postTranslate(redundantXSpace - x, redundantYSpace - y); origWidth = width - 2 * redundantXSpace; origHeight = height - 2 * redundantYSpace; setImageMatrix(matrix); } private class DragListener implements OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { mScaleDetector.onTouchEvent(event); matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; PointF curr = new PointF(event.getX(), event.getY()); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: last.set(event.getX(), event.getY()); start.set(last); if (nowScale * imageWidth > width * 1.05 || nowScale * imageHeight > height * 1.05) { mode = DRAG; } break; case MotionEvent.ACTION_MOVE: float deltaX = curr.x - last.x; float deltaY = curr.y - last.y; if (mode == DRAG) { float scaleWidth = Math.round(imageWidth * nowScale); float scaleHeight = Math.round(imageHeight * nowScale); // x if (scaleWidth < width) {// 不超過邊框時置中 deltaX = redundantXSpace - x - (imageWidth * nowScale - redundantWidth) / 2; } else { if (deltaX > 0 && x + deltaX > 0) {// 往右拉&&左邊拉過頭 deltaX = -x; } else if (deltaX < 0 && x + deltaX + scaleWidth < width) {// 往左拉&&右邊拉過頭 deltaX = width - x - scaleWidth; } } // y if (scaleHeight < height) {// 不超過邊框時置中 deltaY = redundantYSpace - y - (imageHeight * nowScale - redundantHeight) / 2; } else { if (deltaY > 0 && y + deltaY > 0) {// 往下拉&&上邊拉過頭 deltaY = -y; } else if (deltaY < 0 && y + deltaY + scaleHeight < height) {// 往上拉&&下邊拉過頭 deltaY = height - y - scaleHeight; } } matrix.postTranslate(deltaX, deltaY); last.set(curr.x, curr.y); } break; case MotionEvent.ACTION_UP: mode = NONE; int xDiff = (int) Math.abs(curr.x - start.x); int yDiff = (int) Math.abs(curr.y - start.y); if (xDiff < CLICK && yDiff < CLICK) performClick(); break; case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; } setImageMatrix(matrix); invalidate(); return true; } } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { mode = ZOOM; last.set(detector.getFocusX(), detector.getFocusY()); start.set(last); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { float mScaleFactor = detector.getScaleFactor(); float origScale = nowScale; nowScale *= mScaleFactor; if (nowScale > maxScaleTemp) { nowScale = maxScaleTemp; mScaleFactor = maxScaleTemp / origScale; } else if (nowScale < minScaleTemp) { nowScale = minScaleTemp; mScaleFactor = minScaleTemp / origScale; } if (origWidth * nowScale <= width || origHeight * nowScale <= height) { matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); } else { matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); } matrix.getValues(m); float x = m[Matrix.MTRANS_X]; float y = m[Matrix.MTRANS_Y]; float scaleWidth = Math.round(imageWidth * nowScale); float scaleHeight = Math.round(imageHeight * nowScale); if (nowScale < origScale) {// 縮小時置中 if (x > 0 && x + scaleWidth > width) {// 只有左邊有空隙 matrix.postTranslate(-x, 0); } else if (x < 0 && x + scaleWidth < width) {// 只有右邊有空隙 matrix.postTranslate(width - x - scaleWidth, 0); } else if (x > 0 && x + scaleWidth < width) {// 兩邊都有空隙 matrix.postTranslate((width - scaleWidth) / 2 - x, 0); } if (y > 0 && y + scaleHeight > height) {// 只有上邊有空隙 matrix.postTranslate(0, -y); } else if (y < 0 && y + scaleHeight < height) {// 只有下邊有空隙 matrix.postTranslate(0, height - y - scaleHeight); } else if (y > 0 && y + scaleHeight < height) {// 兩邊都有空隙 matrix.postTranslate(0, (height - scaleHeight) / 2 - y); } } PointF curr = new PointF(detector.getFocusX(), detector.getFocusY()); float deltaX = curr.x - last.x; float deltaY = curr.y - last.y; last.set(curr.x, curr.y); // x if (scaleWidth < width) {// 不超過邊框時置中 deltaX = redundantXSpace - x - (imageWidth * nowScale - redundantWidth) / 2; return true;// 縮放這邊已經置中過了,跳調 } else { if (deltaX > 0 && x + deltaX > 0) {// 往右拉&&左邊拉過頭 deltaX = -x; } else if (deltaX < 0 && x + deltaX + scaleWidth < width) {// 往左拉&&右邊拉過頭 deltaX = width - x - scaleWidth; } } // y if (scaleHeight < height) {// 不超過邊框時置中 deltaY = redundantYSpace - y - (imageHeight * nowScale - redundantHeight) / 2; return true;// 縮放這邊已經置中過了,跳調 } else { if (deltaY > 0 && y + deltaY > 0) {// 往下拉&&上邊拉過頭 deltaY = -y; } else if (deltaY < 0 && y + deltaY + scaleHeight < height) {// 往上拉&&下邊拉過頭 deltaY = height - y - scaleHeight; } } matrix.postTranslate(deltaX, deltaY); return true; } } }
2013年4月23日 星期二
[Android] Gallery Scroll One Image At A Time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class ScrollOneImageAtATimeGallery extends Gallery { public ScrollOneImageAtATimeGallery(Context context) { super(context); } public ScrollOneImageAtATimeGallery(Context context, AttributeSet attrs) { super(context, attrs); } public ScrollOneImageAtATimeGallery(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) { return e2.getX() > e1.getX(); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int kEvent; if (isScrollingLeft(e1, e2)) { // Check if scrolling left kEvent = KeyEvent.KEYCODE_DPAD_LEFT; } else { // Otherwise scrolling right kEvent = KeyEvent.KEYCODE_DPAD_RIGHT; } onKeyDown(kEvent, null); return true; } } |
[Android] Gallery一次只滑動一張
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class ScrollOneImageAtATimeGallery extends Gallery { public ScrollOneImageAtATimeGallery(Context context) { super(context); } public ScrollOneImageAtATimeGallery(Context context, AttributeSet attrs) { super(context, attrs); } public ScrollOneImageAtATimeGallery(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) { return e2.getX() > e1.getX(); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int kEvent; if (isScrollingLeft(e1, e2)) { // Check if scrolling left kEvent = KeyEvent.KEYCODE_DPAD_LEFT; } else { // Otherwise scrolling right kEvent = KeyEvent.KEYCODE_DPAD_RIGHT; } onKeyDown(kEvent, null); return true; } } |
2013年4月22日 星期一
[iOS] iOS Google Map SDK and route(Google Maps API v3)
iOS Google Map SDK
Official Website:
https://developers.google.com/maps/documentation/ios/
At first, go to https://developers.google.com/maps/documentation/ios/start download latest version iOS Google Map SDK and build a google map view according to the official teaching.
Rember u need to register to get KEY.
Then we use native code to get the route path and draw on the Google Map
Please come to https://developers.google.com/maps/documentation/javascript/tutorial to get Google Maps API v3 permissions,and prepared your JSON parser(You can find a JSON parser from http://code.google.com/p/json-framework/ witch i used.).
Don't forget to check the API parameter at here https://developers.google.com/maps/documentation/javascript/reference
This is a sample:
NSString *encodedStringFrom = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef) @"25,120", NULL, NULL, kCFStringEncodingUTF8);
NSString *encodedStringTo = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef) @"26,121" NULL, NULL, kCFStringEncodingUTF8);
NSString * url = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&sensor=false&mode=walking",from,to];
[encodedStringFrom release];
[encodedStringTo release];
Use any HTTP GET you liked to send url and get NSString *response to parser:
Please come to https://developers.google.com/maps/documentation/javascript/tutorial to get Google Maps API v3 permissions,and prepared your JSON parser(You can find a JSON parser from http://code.google.com/p/json-framework/ witch i used.).
Don't forget to check the API parameter at here https://developers.google.com/maps/documentation/javascript/reference
This is a sample:
NSString *encodedStringFrom = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef) @"25,120", NULL, NULL, kCFStringEncodingUTF8);
NSString *encodedStringTo = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef) @"26,121" NULL, NULL, kCFStringEncodingUTF8);
NSString * url = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&sensor=false&mode=walking",from,to];
[encodedStringFrom release];
[encodedStringTo release];
Use any HTTP GET you liked to send url and get NSString *response to parser:
id JSONValue = [response JSONValue];
if (JSONValue) {
NSDictionary *dictionary = (NSDictionary *)JSONValue;
if ([[dictionary objectForKey:@"status"]isEqual:@"OK"]) {
NSArray *routes = [dictionary objectForKey:@"routes"];
for (int i = 0; i < [routes count]; i++) {
NSDictionary *rout = [routes objectAtIndex:i];
NSDictionary *overview_polyline = [rout objectForKey:@"overview_polyline"];
NSString *points = [overview_polyline objectForKey:@"points"];
if (polyline) {
[polyline remove];//remove old route on map
}
GMSPolylineOptions *polylineOptions = [GMSPolylineOptions options];
polylineOptions.path = [self polylineWithEncodedString:points];
polylineOptions.color = [UIColor greenColor];
polylineOptions.width = 10.f;
polylineOptions.geodesic = YES;
if (polylineOptions.path != NULL) {
self.polyline = [mapViewRoot addPolylineWithOptions:polylineOptions];
didGetPath = TRUE;
}
}
}
}
polylineWithEncodedString:
- (GMSMutablePath *)polylineWithEncodedString:(NSString *)encodedString {
const char *bytes = [encodedString UTF8String];
NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger idx = 0;
GMSMutablePath *path = [GMSMutablePath path];
float latitude = 0;
float longitude = 0;
while (idx < length) {
char byte = 0;
int res = 0;
char shift = 0;
do {
byte = bytes[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
latitude += deltaLat;
shift = 0;
res = 0;
do {
byte = bytes[idx++] - 0x3F;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
longitude += deltaLon;
float finalLat = latitude * 1E-5;
float finalLon = longitude * 1E-5;
[path addCoordinate:CLLocationCoordinate2DMake(finalLat, finalLon)];
}
return path;
}
remember declare below at .h
id<GMSPolyline> polyline //route
GMSMapView *mapViewRoot //google map
訂閱:
文章 (Atom)