Hi, What "underlying bitmap" are you referring to? In the onDraw() method, the Canvas is used to draw onto your application's window buffer.
On Mon, Feb 14, 2011 at 7:55 PM, Mikey <[email protected]> wrote: > Here's my problem. I finally figured out how to get my custom view > working, but discovered that "canvas.drawCircle(..)" draws based on > the screens dimensions and not the underlying bitmap (I may be > misusing some terms/concepts here, still a little iffy on the whole > custom view). > > Basically, I have a bitmap of a map image, and I want to be able to > draw based on the bitmap's pixel dimensions, and to the bitmap if > possible, so that when it's panned/zoomed, it stays in its respective > place. Here is the code for my custom view. I x'd out my latitude and > longitude. The touch handling is code adapted from a Hello, Android > (3e) excerpt. > > package mikey.gps.NAV; > > import java.util.Vector; > > import android.content.Context; > import android.graphics.Bitmap; > import android.graphics.BitmapFactory; > import android.graphics.Canvas; > import android.graphics.Matrix; > import android.graphics.Paint; > import android.graphics.PointF; > import android.util.AttributeSet; > import android.util.FloatMath; > import android.view.MotionEvent; > import android.view.View; > > public class CustomView extends View { > private int mMode; > private double curLat, curLng; > public static final int MAP = 0; > public static final int NAV = 1; > private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); > Vector<LocationNode> mPath = new Vector<LocationNode>(); > Bitmap map; > > //Geographical information for translating to pixels > private double XZero = xxxxxx; > private double YZero = yyyyyyy; > private double XWidth = 0.01388333333334; > private double YWidth = 0.00693333333334; > //Image dimensions > private double IWidth = 1389; > private double IHeight = 971; > > > //Matrices for scaling the image > public Matrix matrix = new Matrix(); > Matrix savedMatrix = new Matrix(); > > static final int NONE = 0; > static final int DRAG = 1; > static final int ZOOM = 2; > int mode = NONE; > > PointF start = new PointF(); > PointF mid = new PointF(); > float oldDist = 1f; > > public CustomView(Context context, AttributeSet attrs) { > super(context, attrs); > init(); > } > > public CustomView(Context context, AttributeSet attrs, int defStyle) > { > super(context, attrs, defStyle); > // TODO Auto-generated constructor stub > } > > public CustomView(Context context) { > super(context); > init(); > } > private void init() { > map = > BitmapFactory.decodeResource(getContext().getResources(), > R.drawable.campus); > //mPaint.setFilterBitmap(true); > matrix.setTranslate(1f, 1f); > invalidate(); > } > > /* When the view is invalidated, onDraw does different actions > * depending on its mode. If it is the map display, it simply > * draws a circle on the current location. If it is on navigate, > * it draws a circle on the start and goal nodes, then lines to > * form the path. > * > * (non-Javadoc) > * @see android.view.View#onDraw(android.graphics.Canvas) > */ > @Override > protected void onDraw(Canvas canvas) { > // TODO Auto-generated method stub > super.onDraw(canvas); > canvas.drawBitmap(map, matrix, mPaint); > if(mMode == NAV) { > > canvas.drawCircle(translateX(mPath.lastElement().lat), > translateY(mPath.lastElement().lng), > 10, mPaint); > > canvas.drawCircle(translateX(mPath.firstElement().lat), > > translateY(mPath.firstElement().lng), 10, mPaint); > for(int i = 0; i < mPath.size()- 1; i++) { > LocationNode startNode = mPath.elementAt(i); > LocationNode stopNode = > mPath.elementAt(i+1); > float startX = translateX(startNode.lat); > float startY = translateY(startNode.lng); > float stopX = translateX(stopNode.lat); > float stopY = translateY(stopNode.lng); > canvas.drawLine(startX, startY, stopX, > stopY, mPaint); > } > } > else if (mMode == MAP) { > canvas.drawCircle(translateX(curLat), > translateY(curLng), 10, mPaint); > } > } > > @Override > public boolean onTouchEvent(MotionEvent e) { > // TODO Auto-generated method stub > WrapMotionEvent event = WrapMotionEvent.wrap(e); > switch (event.getAction() & MotionEvent.ACTION_MASK) { > case MotionEvent.ACTION_DOWN: > savedMatrix.set(matrix); > start.set(event.getX(), event.getY()); > mode = DRAG; > break; > case MotionEvent.ACTION_POINTER_DOWN: > oldDist = spacing(event); > if (oldDist > 10f) { > savedMatrix.set(matrix); > midPoint(mid, event); > mode = ZOOM; > } > break; > case MotionEvent.ACTION_UP: > case MotionEvent.ACTION_POINTER_UP: > mode = NONE; > break; > case MotionEvent.ACTION_MOVE: > if (mode == DRAG) { > // ... > matrix.set(savedMatrix); > matrix.postTranslate(event.getX() - start.x, > event.getY() - start.y); > } > else if (mode == ZOOM) { > float newDist = spacing(event); > if (newDist > 10f) { > matrix.set(savedMatrix); > float scale = newDist / oldDist; > matrix.postScale(scale, scale, mid.x, mid.y); > } > } > break; > } > invalidate(); > return true; > } > > > > /* Handler method for touch events. The event > * is passed in from the overlying activity. > */ > public void setMatrix(WrapMotionEvent event) { > // Handle touch events here... > switch (event.getAction() & MotionEvent.ACTION_MASK) { > case MotionEvent.ACTION_DOWN: > savedMatrix.set(matrix); > start.set(event.getX(), event.getY()); > mode = DRAG; > break; > case MotionEvent.ACTION_POINTER_DOWN: > oldDist = spacing(event); > if (oldDist > 10f) { > savedMatrix.set(matrix); > midPoint(mid, event); > mode = ZOOM; > } > break; > case MotionEvent.ACTION_UP: > case MotionEvent.ACTION_POINTER_UP: > mode = NONE; > break; > case MotionEvent.ACTION_MOVE: > if (mode == DRAG) { > // ... > matrix.set(savedMatrix); > matrix.postTranslate(event.getX() - start.x, > event.getY() - start.y); > } > else if (mode == ZOOM) { > float newDist = spacing(event); > if (newDist > 10f) { > matrix.set(savedMatrix); > float scale = newDist / oldDist; > matrix.postScale(scale, scale, mid.x, mid.y); > } > } > break; > } > } > > /** Determine the space between the first two fingers */ > private float spacing(WrapMotionEvent event) { > // ... > float x = event.getX(0) - event.getX(1); > float y = event.getY(0) - event.getY(1); > return FloatMath.sqrt(x * x + y * y); > } > > /** Calculate the mid point of the first two fingers */ > private void midPoint(PointF point, WrapMotionEvent event) { > // ... > float x = event.getX(0) + event.getX(1); > float y = event.getY(0) + event.getY(1); > point.set(x / 2, y / 2); > } > /* Translates the latitude coordinate into a pixel coordinate */ > public float translateX(double x) { > float newX = (float) (IWidth * ((x - XZero) / XWidth)); > return newX; > } > /* Translates the longitude coordinate into a pixel coordinate */ > public float translateY(double y) { > float newY = (float) (IHeight * ((YZero - y) / > YWidth)); > return newY; > } > /* Called by the navigator to enable drawing the route */ > public void setPath(Vector<LocationNode> path) { > mPath.clear(); > mPath = new Vector<LocationNode>(path); > } > /* Called by the map display to enable drawing the > * current location */ > public void setCurLocation(double lat, double lng) { > curLat = lat; > curLng = lng; > } > public void setMode(int mode) { > mMode = mode; > } > } > > I'm currently working with "MAP" mode, but it will also come into > play for NAV. But I basically need to draw to the bitmap, which is > scaled and manipulated through the canvas(?) so that the current > location dot will stay in the same spot when the bitmap is panned or > zoomed, instead of staying in a static location based on the screen's > dimensions. Any advice? > > -Mike > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en > -- Romain Guy Android framework engineer [email protected] Note: please don't send private questions to me, as I don't have time to provide private support. All such questions should be posted on public forums, where I and others can see and answer them -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

