I am using MapViewCompassDemo sample from
\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo\
for rotating map view based on user direction.This is working
perfectly if the map is without overlays.But if i add overlays to map the ontap not working exactly
on marker while rotating.can any one help me regarding this.
in this sample it only rotate dispatchDraw method only.Along with dispatchDraw rotate
dispatchTouchEvent also.find below code to rotate toouch events also
#Override
public void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.rotate(getRotation(), getWidth() / 2, getHeight() / 2);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
float[] coords = new float[] {
event.getX(), event.getY()
};
adjustCoords(coords, getRotation());
MotionEvent evt = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), event
.getAction(), coords[0], coords[1], event.getPressure(), event.getSize(), event
.getMetaState(), event.getXPrecision(), event.getYPrecision(), event.getDeviceId(),
event.getEdgeFlags());
return super.dispatchTouchEvent(evt);
}
protected void adjustCoords(float[] coords, float deg) {
float x = coords[0];
float y = coords[1];
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
// convert to radians
float rad = (float) ((deg * Math.PI) / 180F);
float s = (float) Math.sin(rad);
float c = (float) Math.cos(rad);
// translate point back to origin:
x -= centerX;
y -= centerY;
// apply rotation
float tmpX = x * c - y * s;
float tmpY = x * s + y * c;
x = tmpX;
y = tmpY;
// translate point back:
x += centerX;
y += centerY;
coords[0] = x;
coords[1] = y;
}
See this below link
http://evancharlton.com/thoughts/android-rotating-touch-events/
Related
#Override
public void onDraw(Canvas canvas) {
/*canvas.drawLine(0, 0, 20, 20, paint);
canvas.drawLine(200, 0, 0, 200, paint);*/
/*canvas.drawLine(downxpos, downypos, upxpos, upypos, paint);*/
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint);
}
}
example image
I Would like to draw the line like the image I show in canvas. I can draw the line but don't know how to add arrows to it.
Use these Methods to draw Arrow on both sides.
private void drawArrow1(Canvas canvas, Paint paint) {
double degree = calculateDegree(x, x1, y, y1);
float endX1 = (float) (x1 + ((10) * Math.cos(Math.toRadians((degree-30)+90))));
float endY1 = (float) (y1 + ((10) * Math.sin(Math.toRadians(((degree-30)+90)))));
float endX2 = (float) (x1 + ((10) * Math.cos(Math.toRadians((degree-60)+180))));
float endY2 = (float) (y1 + ((10) * Math.sin(Math.toRadians(((degree-60)+180)))));
canvas.drawLine(x1,y1,endX1,endY1,paint);
canvas.drawLine(x1, y1, endX2,endY2,paint);
}
private void drawArrow(Canvas canvas, Paint paint) {
double degree1 = calculateDegree(x1, x, y1, y);
float endX11 = (float) (x + ((10) * Math.cos(Math.toRadians((degree1-30)+90))));
float endY11 = (float) (y + ((10) * Math.sin(Math.toRadians(((degree1-30)+90)))));
float endX22 = (float) (x + ((10) * Math.cos(Math.toRadians((degree1-60)+180))));
float endY22 = (float) (y + ((10) * Math.sin(Math.toRadians(((degree1-60)+180)))));
canvas.drawLine(x,y,endX11,endY11,paint);
canvas.drawLine(x,y,endX22,endY22,paint);
}
public double calculateDegree(float x1, float x2, float y1, float y2) {
float startRadians = (float) Math.atan((y2 - y1) / (x2 - x1));
System.out.println("radian=====" + Math.toDegrees(startRadians));
startRadians += ((x2 >= x1) ? 90 : -90) * Math.PI / 180;
return Math.toDegrees(startRadians);
}
Where x,y is starting point and x1,y1 is ending point.
I have 2 circles, one that i move and the other in the center of the screen. What I want to do is that the circles do not overlap when I move one over another. I managed to do something similar but it's horrible, I wanted to know if there is a more efficient way to do it.
public class Juego extends SurfaceView implements View.OnTouchListener{
private Paint paint;
int x = 100, y = 100, radio = 100, otroX, otroY;
public Juego(Context context, AttributeSet attrs) {
super(context, attrs);
this.setOnTouchListener(this);
setFocusable(true);
paint = new Paint();
}
public void onDraw(Canvas canvas) {
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
paint.setColor(Color.BLACK);
canvas.drawCircle(x, y, radio, paint);
otroX = canvas.getWidth() / 2;
otroY = canvas.getHeight() / 2;
canvas.drawCircle(otroX, otroY, radio, paint);
invalidate();
}
#Override
public boolean onTouch(View view,MotionEvent motionEvent){
x = (int)motionEvent.getX();
y = (int)motionEvent.getY();
double dist = Math.sqrt(Math.pow((x - otroX), 2) + Math.pow((y - otroY), 2));
if (dist <= radio + radio) {
if (x < otroX) {
x = otroX - radio - (radio / 2);
}
if (x > otroX) {
x = otroX + radio + (radio / 2);
}
if (y < otroY) {
y = otroY - radio - (radio / 2);
}
if (y > otroY) {
y = otroY + radio + (radio / 2);
}
}
invalidate();
return true;
}
}
This is what i have: https://mega.nz/#!HZsVhR4L!v6AhTWgJ27U8vV1rYJ_BuO8O2TxgKJV113m58P6ANek
and this is what i want: https://mega.nz/#!PJFHmDYR!auzX-L-TBTNCZuD8vX8ugUeZmi-HhtWLqs6mUilfW_M
To solve the issue, when the moving circle is too close, we need to move it at the expected minimum distance, on the line defined by the two circles centres:
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
x = (int) motionEvent.getX();
y = (int) motionEvent.getY();
double dist = Math.sqrt(Math.pow((x - otroX), 2) + Math.pow((y - otroY), 2));
if (dist <= radius * 2) {
// This calculate the displacement of a the distance 'radius*2' on the line between the two circles centers.
double angle = Math.atan2(y - otroY, x - otroX);
int moveX = (int) ((radius * 2) * Math.cos(angle));
int moveY = (int) ((radius * 2) * Math.sin(angle));
// Then we need to add the displacement to the coordinates of the origin to have the new position.
x = otroX + moveX;
y = otroY + moveY;
}
invalidate();
return true;
}
This code is based on KazenoZ answer.
I am able to plot bar graph using canvas and drawing rectangle in the view. But the onTouch interaction works for the whole view and hence I am not able to interact with each bar separately.I am not looking for using any library for plotting graphs. Any suggestions would be helpful. Thanks!
protected void onDraw(Canvas canvas) {
float border = 20;
float horstart = border * 2;
float height = getHeight();
float width = getWidth() - 1;
float max = getMax();
float min = getMin();
float diff = max - min;
float graphheight = height - (2 * border);
float graphwidth = width - (2 * border);
paint.setTextAlign(Align.LEFT);
int vers = verlabels.length - 1;
for (int i = 0; i < verlabels.length; i++) {
paint.setColor(Color.BLUE);
float y = ((graphheight / vers) * i) + border;
//canvas.drawLine(horstart, y, width, y, paint);
paint.setColor(Color.BLUE);
canvas.drawText(verlabels[i], 0, y, paint);
}
int hors = horlabels.length - 1;
for (int i = 0; i < horlabels.length; i++) {
paint.setColor(Color.BLUE);
float x = ((graphwidth / hors) * i) + horstart;
//canvas.drawLine(x, height - border, x, border, paint);
paint.setTextAlign(Align.CENTER);
if (i == horlabels.length - 1)
paint.setTextAlign(Align.RIGHT);
if (i == 0)
paint.setTextAlign(Align.LEFT);
paint.setColor(Color.BLUE);
canvas.drawText(horlabels[i], x, height - 4, paint);
}
paint.setTextAlign(Align.CENTER);
canvas.drawText(title, (graphwidth / 2) + horstart, border - 4, paint);
if (max != min) {
paint.setColor(Color.BLUE);
if (type == BAR) {
float datalength = values.length;
float colwidth = (graphwidth / hors);
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
float h = graphheight * rat;
canvas.drawRect((i * colwidth) + horstart, (border - h)
+ graphheight+curY, ((i * colwidth) + horstart)
+ (colwidth - 1), height - (border - 1), paint);
}
} else {
float datalength = values.length;
float colwidth = (width - (2 * border)) / datalength;
float halfcol = colwidth / 2;
float lasth = 0;
float h = 0;
for (int i = 0;i<values.length;i++)
canvas.drawLine(((i - 1) * colwidth) + (horstart + 1)
+ halfcol, (border - lasth) + graphheight+curY,
(i * colwidth) + (horstart + 1) + halfcol,
(border - h) + graphheight, paint);
lasth = h;
}
}
}
onTouch method for the view :
public boolean onTouch(View v, MotionEvent event)
{
boolean result=false;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
case MotionEvent.ACTION_MOVE:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
case MotionEvent.ACTION_UP:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
}
if (result) invalidate();
return result;
}
Whenever an user touches that view, it causes the onTouch method gets called. Once it's getting called, you're given two float numbers: x and y indicating where user's finger touches your view relative to the view coordination system.
As you might grasped the idea, you should get those numbers and internally in your custom view (i.e. bar chart) calculate which bar is affected. Then, you can for example apply a hover effect or do something else.
Note: For updating appearance of your view, you should store changes in data models of your chart view and then issue invalidate(). Subsequently, as a result, your onDraw is invoked and in which you can re-draw your chart. (i.e. You should each time, re-draw your whole chart again)
I have to modify some one's project . getTheta is a method in that project which i didn't understand but it help to rotate view rotate like a knob (not fully 360 but less on b/s)
private float getTheta(float x, float y)
{
float sx = x - (float)getWidth() / 2.0F;
float sy = y - (float)getHeight() / 2.0F;
float length = (float)Math.sqrt(sx * sx + sy * sy);
float nx = sx / length;
float theta = 57.29578F * (float)Math.atan2(sy / length, nx);
if (theta < 0.0F)
{
theta += 360F;
}
return theta;
}
What i find method of getting theta is
private float getMyTheta(float x, float y) {
float sx = x - (getWidth() / 2.0f);
float sy = y - (getHeight() / 2.0f);
float length = (float) Math.sqrt(sx * sx + sy * sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float) Math.atan2(ny, nx);
final float rad2deg = (float) (180.0 / Math.PI);
float theta2 = theta * rad2deg;
return (theta2 < 0) ? theta2 + 360.0f : theta2;
}
Can someone explain me what is doing in getTheta(float x,float y);
Thanks in Advance...
I am working on a tile based game which should be scrollable but only inside the boundaries of the world. So I set up the pan() method as several examples/tutorials suggest but it is not always working properly. Sometimes it is jumping back to the starting point of the last gesture or is only moving very slow. Additionally the borders are not working either. Maybe somebody can point out the mistakes I made.
public void pan(float x, float y, float deltaX, float deltaY) {
moveCamera(x, y);
}
private void moveCamera(float x, float y) {
Vector3 new_position = getNewCameraPosition((int) x, (int)y);
if(!cameraOutOfLimit(new_position))
this.getViewport().getCamera().translate(new_position.sub(this.getViewport().getCamera().position));
lastTouchDown.set(x, y, 0);
}
private Vector3 getNewCameraPosition(int x, int y) {
Vector3 newPosition = lastTouchDown;
newPosition.sub(x, y, 0);
newPosition.y = -newPosition.y;
newPosition.add(this.getViewport().getCamera().position);
return newPosition;
}
private boolean cameraOutOfLimit( Vector3 position ) {
int x_left_limit = (int) (Global.SCREEN_WIDTH / 2);
int x_right_limit = (int) (Global.COLS_OF_TILES * Global.TILE_WIDTH - (Global.SCREEN_WIDTH / 2));
int y_bottom_limit = (int) (Global.SCREEN_HEIGHT / 2);
int y_top_limit = (int) (Global.ROWS_OF_TILES * Global.TILE_HEIGHT - Global.SCREEN_HEIGHT / 2);
if( position.x < x_left_limit || position.x > x_right_limit )
return true;
else if( position.y < y_bottom_limit || position.y > y_top_limit )
return true;
else
return false;
}
The code above seems convoluted to me, and I don't really understandwhy you modify a vector called lastTouchPosition in ways that have nothing to do with touch position.
I would do something like this. These methods clamp your target X and Y positions whenever you want to move your camera.
float clampCamTargetX(float x) {
x = Math.max(x, (int) (Global.SCREEN_WIDTH / 2));
x = Math.min(x, (int) (Global.COLS_OF_TILES * Global.TILE_WIDTH - (Global.SCREEN_WIDTH / 2)));
return x;
}
float clampCamTargetY (float y){
y = Math.max(y,(int)(Global.SCREEN_HEIGHT/2));
y = Math.min(y,(int)(Global.ROWS_OF_TILES*Global.TILE_HEIGHT-Global.SCREEN_HEIGHT/2));
return y;
}
Then if you want to pan it, you would do something like this:
void panCamera(float deltaX, float deltaY) {
Camera camera = this.getViewport().getCamera();
Vector3 camPosition = camera.position;
camPosition.x = clampCamTargetX(camPosition.x + deltaX);
camPosition.y = clampCamTargetY(camPosition.y + deltaY);
camera.update();
}
Or if you want a complete solution for smoothly moving the camera to the last position touched, try this:
float startXCam, startYCam, targetXCam, targetYCam;
float elapsedTimeCam;
boolean panningCam = false;
static final float CAM_PAN_DURATION = 0.4f;
public void render (){
//...
panCameraToTouchPoint(Gdx.graphics.getDeltaTime());
//...
}
void panCameraToTouchPoint (float deltaTime){
Camera camera = getViewport().getCamera();
Vector3 camPosition = camera.position;
if (Gdx.input.justTouched()) {
startXCam = camPosition.x;
startYCam = camPosition.y;
targetXCam = clampCamTargetX(Gdx.input.getX());
targetYCam = clampCamTargetY(Gdx.input.getY());
elapsedTimeCam = 0;
panningCam = true;
}
if (panningCam){
elapsedTimeCam += deltaTime;
float alpha = elapsedTimeCam / CAM_PAN_DURATION;
if (alpha >= 1){
alpha = 1;
panningCam = false;
}
camPosition.x = Interpolation.pow2Out.apply(startXCam, targetXCam, alpha);
camPosition.y = Interpolation.pow2Out.apply(startYCam, targetYCam, alpha);
camera.update();
}
}