Smooth zoom in mapview - android

When I use MapController.setZoom(x) and, for instance, zoom from level 5 to 15 the zoom is perform very fast and often the map tiles of the new level are not loaded.
This does not look so good to the user. Any Maps build in function to change this to a more slow zoom so tiles can be loaded, or at least almost loaded, before level 15 is reached?
Best regards
P

A simpler way is to take advantage of the MapController.zoomIn() method that provides some simple animation for zooming a step level.
Here's some code:
// a Quick runnable to zoom in
int zoomLevel = mapView.getZoomLevel();
int targetZoomLevel = 18;
long delay = 0;
while (zoomLevel++ < targetZoomLevel) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
mapController.zoomIn();
}
}, delay);
delay += 350; // Change this to whatever is good on the device
}
What it does is create a sequence of delayed runnables each one of which will call zoomIn() 350ms after the previous one.
This assumes that you have a Handler attached to your main UI thread called 'handler'
:-)

There's no simple way to do this. However, I can help you out.
Firstly, here's a free gift of one of my personal utility classes, Tween.java:
import android.os.Handler;
public class Tween {
public static interface TweenCallback {
public void onTick(float time, long duration);
public void onFinished();
}
long start;
long duration;
Handler handler;
TweenCallback callback;
public Tween(TweenCallback callback) {
handler = new Handler();
this.callback = callback;
}
public void start(final int duration) {
start = android.os.SystemClock.uptimeMillis();
this.duration = duration;
tickRunnable.run();
}
public void stop() {
handler.removeCallbacks(tickRunnable);
}
Runnable tickRunnable= new Runnable() {
public void run() {
long now = android.os.SystemClock.uptimeMillis();
float time = now - start;
boolean finished = (time >= duration);
if (finished) {
time = duration;
}
callback.onTick(time, duration);
if (!finished) {
handler.post(tickRunnable);
}
else {
callback.onFinished();
}
}
};
//
// Tweening functions. The 4 parameters are :
//
// t - time, ranges from 0 to d
// b - begin, i.e. the initial value for the quantity being changed over time
// c - change, the amount b will be changed by at the end
// d - duration, of the transition, normally in milliseconds.
//
// All were adapted from http://jstween.sourceforge.net/Tween.js
//
public static float strongEaseInOut(float t, float b, float c, float d) {
t/=d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
}
public static float regularEaseIn(float t, float b, float c, float d) {
return c*(t/=d)*t + b;
}
public static float strongEaseIn(float t, float b, float c, float d) {
return c*(t/=d)*t*t*t*t + b;
}
}
What I recommend you do is use MapController.zoomToSpan() in conjunction with a Tween... here's some completely untested code that should work, maybe with a tweak or two, you just pass it the target lat & lon spans. :
public void slowZoom(int latE6spanTarget, int lonE6spanTarget) {
final float initialLatE6span = mapView.getLatitudeSpan();
final float initialLonE6span = mapView.getLongitudeSpan();
final float latSpanChange = (float)(latE6spanTarget - initialLatE6span);
final float lonSpanChange = (float)(lonE6spanTarget - initialLonE6span);
Tween tween = new Tween(new Tween.TweenCallback() {
public void onTick(float time, long duration) {
float latSpan = Tween.strongEaseIn(time, initialLatE6span, latSpanChange, duration);
float lonSpan = Tween.strongEaseIn(time, initialLonE6span, lonSpanChange, duration);
mapView.getController().zoomToSpan((int)latSpan, (int)lonSpan);
}
public void onFinished() {
}
});
tween.start(5000);
}

Related

spinningwheel animation not accurate

To gain experience in android I'm making a decisionmaking app. I'm trying to add a spinning wheel (wheel of fortune like). I have an animation that works fine (just need some little tweaking but fine for now). The problem I'm having is to detect where the wheel has stopped. If I look at the rotation and match it to precalculated values it makes sense, but visually it seems off.
For example:
Begin state is always like this. I tap it and it starts to rotate.
It stops rotating at red (visually), but in the model it says 51, hence my model detects it stopped rotating at yellow:
Cur pos and Prev pos is not currently implemented. Rnd pos is the relative number of degrees it needs to rotate (relative to 0). Rnd rot is number of extra rotations it has to make before stopping. True pos is the absolute number of degrees it has to rotate. Total time: the time the animation takes. Corner: number of degrees one piece has.
SpinWheel method in activity:
private void spinWheel() {
Roulette r = Roulette.getInstance();
r.init(rouletteItemsDEBUG);
r.spinRoulette();
final int truePos = r.getTruePosition();
final long totalTime = r.getTotalTime();
final ObjectAnimator anim = ObjectAnimator.ofFloat(imgSpinningWheel, "rotation", 0, truePos);
anim.setDuration(totalTime);
anim.setInterpolator(new DecelerateInterpolator());
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
imgSpinningWheel.setEnabled(false);
}
#Override
public void onAnimationEnd(Animator animation) {
imgSpinningWheel.setEnabled(true);
txtResult.setText(Roulette.getInstance().getSelectedItem().getValue());
Log.d(TAG, Roulette.getInstance().toString());
Log.d(TAG, imgSpinningWheel.getRotation() + "");
Log.d(TAG, imgSpinningWheel.getRotationX() + "");
Log.d(TAG, imgSpinningWheel.getRotationY() + "");
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
anim.start();
}
Roulette.java:
public class Roulette {
private static Roulette instance;
private static final long TIME_IN_WHEEL = 1000; //time in one rotation (speed of rotation)
private static final int MIN_ROT = 5;
private static final int MAX_ROT = 6;
private static final Random rnd = new Random();
private RouletteItem currentItem;
private RouletteItem[] rouletteItems;
private NavigableMap<Integer, RouletteItem> navigableMap;
private int randomRotation;
private int randomPosition;
private int truePosition;
private int corner;
private long totalTime;
private Roulette() {
}
public void init(RouletteItem[] rouletteItems) {
this.rouletteItems = rouletteItems;
navigableMap = new TreeMap<>();
for (int i = 0; i < getNumberOfItems(); i++) {
navigableMap.put(i * 51, rouletteItems[i]);
}
}
public void spinRoulette() {
if (rouletteItems == null || rouletteItems.length < 2) {
throw new RouletteException("You need at least 2 rouletteItems added to the wheel!");
}
calculateCorner();
calculateRandomPosition();
calculateRandomRotation();
calculateTruePosition();
calculateTotalTime();
}
/**
* Pinpoint random position in the wheel
*/
private void calculateRandomPosition() {
randomPosition = corner * rnd.nextInt(getNumberOfItems());
}
/**
* Calculates the points one RouletteItem has
*/
private void calculateCorner() {
corner = 360 / getNumberOfItems();
}
/**
* Calculates the time needed to spin to the chosen random position
*/
private void calculateTotalTime() {
totalTime = (TIME_IN_WHEEL * randomRotation + (TIME_IN_WHEEL / 360) * randomPosition);
}
/**
* Calculates random rotation
*/
private void calculateRandomRotation() {
randomRotation = MIN_ROT + rnd.nextInt(MAX_ROT - MIN_ROT);
}
/**
* Calculates the true position
*/
private void calculateTruePosition() {
truePosition = (randomRotation * 360 + randomPosition);
}
//getters and to string omitted
}
The map is used to map rouletteItems to a range of degrees.
My guess is that the animation takes too long or something like that. But I don't really see how to fix it. Anyone who does?
Thanks in advance!
Um, doesn't Java implement rotation in radians rather than degrees?
That could lead to a offset between the visual rotation graphic and the number from the maths. Perhaps check by replacing all the assumed degree calculations (ie x/360) with radian calcs (ie. x/(2*pi))?

Why cant I use shake listener in ontouch event?

I have a problem when I am running my android app.
The shake listener cannot be called when I touch down.
My logic is "Send message when I am shaking and touch down button at the same time. But it seems that cannot work for my listener part.
But the android studio cant tell me where is the error or code wrongly.
Here is my button code.
shakeitBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Toast.makeText(getBaseContext(), "Shake!", Toast.LENGTH_SHORT).show();
mShakeDetector = new ShakeDetector(new ShakeDetector.OnShakeListener() {
public void onShake() {
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(300);
status = RELEASE_TO_SEND;
}
});
break;
case MotionEvent.ACTION_UP:
if (status == RELEASE_TO_CANCEL) {
Toast.makeText(getBaseContext(), "Shake canceled", Toast.LENGTH_SHORT).show();
} else {
if (status == RELEASE_TO_SEND) {
DatabaseReference childRoot = rootRoomName.push();
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", userName);
map.put("message", "I AM BUSY!!!".toString());
childRoot.updateChildren(map);
}
else{}
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getY() < 0) {
status = RELEASE_TO_CANCEL;
} else {
}
break;
default:
break;
}
return true;
}
});
#Override
public void onResume() {
chat_room.super.onResume();
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onPause() {
mSensorManager.unregisterListener(mShakeDetector);
chat_room.super.onPause();
}
Here is my share detector code
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
public class ShakeDetector implements SensorEventListener {
// Minimum acceleration needed to count as a shake movement
private static final int MIN_SHAKE_ACCELERATION = 5;
// Minimum number of movements to register a shake
private static final int MIN_MOVEMENTS = 2;
// Maximum time (in milliseconds) for the whole shake to occur
private static final int MAX_SHAKE_DURATION = 500;
// Arrays to store gravity and linear acceleration values
private float[] mGravity = {0.0f, 0.0f, 0.0f};
private float[] mLinearAcceleration = {0.0f, 0.0f, 0.0f};
// Indexes for x, y, and z values
private static final int X = 0;
private static final int Y = 1;
private static final int Z = 2;
// OnShakeListener that will be notified when the shake is detected
private OnShakeListener mShakeListener;
// Start time for the shake detection
long startTime = 0;
// Counter for shake movements
int moveCount = 0;
// Constructor that sets the shake listener
public ShakeDetector(OnShakeListener shakeListener) {
mShakeListener = shakeListener;
}
#Override
public void onSensorChanged(SensorEvent event) {
// This method will be called when the accelerometer detects a change.
// Call a helper method that wraps code from the Android developer site
setCurrentAcceleration(event);
// Get the max linear acceleration in any direction
float maxLinearAcceleration = getMaxCurrentLinearAcceleration();
// Check if the acceleration is greater than our minimum threshold
if (maxLinearAcceleration > MIN_SHAKE_ACCELERATION) {
long now = System.currentTimeMillis();
// Set the startTime if it was reset to zero
if (startTime == 0) {
startTime = now;
}
long elapsedTime = now - startTime;
// Check if we're still in the shake window we defined
if (elapsedTime > MAX_SHAKE_DURATION) {
// Too much time has passed. Start over!
resetShakeDetection();
} else {
// Keep track of all the movements
moveCount++;
// Check if enough movements have been made to qualify as a shake
if (moveCount > MIN_MOVEMENTS) {
// It's a shake! Notify the listener.
mShakeListener.onShake();
// Reset for the next one!
resetShakeDetection();
}
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Intentionally blank
}
private void setCurrentAcceleration(SensorEvent event) {
/*
* BEGIN SECTION from Android developer site. This code accounts for
* gravity using a high-pass filter
*/
// alpha is calculated as t / (t + dT)
// with t, the low-pass filter's time-constant
// and dT, the event delivery rate
final float alpha = 0.8f;
// Gravity components of x, y, and z acceleration
mGravity[X] = alpha * mGravity[X] + (1 - alpha) * event.values[X];
mGravity[Y] = alpha * mGravity[Y] + (1 - alpha) * event.values[Y];
mGravity[Z] = alpha * mGravity[Z] + (1 - alpha) * event.values[Z];
// Linear acceleration along the x, y, and z axes (gravity effects removed)
mLinearAcceleration[X] = event.values[X] - mGravity[X];
mLinearAcceleration[Y] = event.values[Y] - mGravity[Y];
mLinearAcceleration[Z] = event.values[Z] - mGravity[Z];
/*
* END SECTION from Android developer site
*/
}
private float getMaxCurrentLinearAcceleration() {
// Start by setting the value to the x value
float maxLinearAcceleration = mLinearAcceleration[X];
// Check if the y value is greater
if (mLinearAcceleration[Y] > maxLinearAcceleration) {
maxLinearAcceleration = mLinearAcceleration[Y];
}
// Check if the z value is greater
if (mLinearAcceleration[Z] > maxLinearAcceleration) {
maxLinearAcceleration = mLinearAcceleration[Z];
}
// Return the greatest value
return maxLinearAcceleration;
}
private void resetShakeDetection() {
startTime = 0;
moveCount = 0;
}
// (I'd normally put this definition in it's own .java file)
public interface OnShakeListener {
public void onShake();
}
}
As you said the ShakeDetector works if you start it before the onTouch() I suggest the following:
1) Create a parameter in your Activity/Fragment:
bool vibrateOnShake = false;
2) Init your ShakeDetector outside the onTouch():
mShakeDetector = new ShakeDetector(new ShakeDetector.OnShakeListener() {
public void onShake() {
if (vibrateOnShake) {
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(300);
status = RELEASE_TO_SEND;
}
}
});
3) Update your onTouch():
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
vibrateOnShake = true;
...
break;
...
}
}

How to move images from bottom to top continuously?

I've been working on the example from http://obviam.net/index.php/a-very-basic-the-game-loop-for-android/ In this I want to make few changes.
Speed.java
public class Speed {
public static final int DIRECTION_RIGHT = 1;
public static final int DIRECTION_LEFT = -1;
public static final int DIRECTION_UP = -1;
public static final int DIRECTION_DOWN = 1;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
Using this, the image moves in all directions. Now I just want to limit this movement from bottom to top. And the functionality for onclick is that, we can click and drag the image to required position. I want to replace that with just make the image to disappear or go to another activity. Please help me in making changes to this code. Thanks in advance.
if you have used SurfaceView then in onDraw(Canvas canvas) method the code is for moving image from bottom to top is something like this.
canvas.drawBitmap(bitmap,xPoint,yPoint,paint);
where bitmap is an image(Bitmap which you want to move),xPoint is the x coordinate,yPoint is the y coordinate and paint is a Paint which is also can be null.
and for bottom to top movement just update
yPoint = yPoint - 1;
in any thread before onDraw() call.
May this help you.

Duration problem in a set of TranslateAnimation in Android

I have to animate an image as per (x,y) from one point to another point, then that point to another point and so on. I have around 300 points. For that I am using the following code.
/** code starts **/
public class CircleAnimation extends Activity implements OnPreparedListener {
/** Called when the activity is first created. */
ImageView imv1;
int totalAnimTime = 0;
double[][] points = {{258.8505,143.2875,67},
{259.642, 143.3665,120},
{260.429, 142.992,240},
{259.257, 139.3575,180},
......................
......................
{255.1335,146.8135,67},
{255.1395,146.794,67},
{255.0635,146.7785,67},
{254.9045,146.797,1200}
};
int j=0;
double loc[] = new double[2];
double x1 = 0,y1 = 0,x2 = 0,y2 = 0,anim_end=0, xstart=258.8505, ystart=143.2875, xnow, ynow;
protected boolean _active = true;
protected int _animTime = 66;
int k=1;
double xFactor = 1.779167, yFactor = 1.5;
private int displayWidth, displayHeight;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imv1 = (ImageView)findViewById(R.id.imv1);
try{
LaunchInAnimation();
}catch(Exception e){
e.printStackTrace();
}
}
class LocalAnimationListener implements AnimationListener {
public void onAnimationEnd(Animation animation){
imv1.post(mLaunchSecondAnimation);
k = k ++;
}
public void onAnimationRepeat(Animation animation)
{
}
public void onAnimationStart(Animation animation)
{
}
};
private Runnable mLaunchSecondAnimation = new Runnable(){
public void run(){
LaunchInAnimation();
}
};
LocalAnimationListener MyAnimationListener = new LocalAnimationListener();
public void LaunchInAnimation() {
//animation
if(k<points.length) {
if(k==0) {
x1 = xstart;
y1 = ystart;
anim_end=1;
} else {
x1 = points[k-1][0];
y1 = points[k-1][1];
}
x2 = points[k][0];
y2 = points[k][1];
_animTime = (int) (points[k][2]);
TranslateAnimation translateAnimation = new TranslateAnimation((float)x1, (float)x2, (float)y1, (float)y2);
translateAnimation.setDuration(_animTime);
translateAnimation.setFillBefore(true);
translateAnimation.setFillAfter(true);
translateAnimation.setAnimationListener(MyAnimationListener);
imv1.startAnimation(translateAnimation);
totalAnimTime += _animTime;
}
}
}
/** code ends **/
To complete all the animations it should take totalAnimTime, but it is taking less time to complete. Moreover this time is varying from one device to another device. For this, I facing problem to synchronize other event. What is the problem in this code? Is there any other better way to control this type animation.
I was messing with this variance in performance myself, and then I switched to OpenGL to do all my rendering and have since found everything much smoother and simpler once you understand what you're doing.
If you feel OpenGL/SurfaceView is a little too dense for what you're asking for, try using Canvas?
Should be much easier with one of those because they're more stable from device to device. XML animations are simply tricking you into thinking they're animations, their actual X/Y don't ever really change. They have to "flicker" from their original X/Y to the "next step X/Y" right before drawn if I'm correct....

Problem with View Invalidate() and Handler

i'm trying to fix this problem for more than 2 days now and have become quite desperate.
I want to write a 'Checkers-like' board game for android. The game engine itself is kinda complete but i have problems with updating the views.
I wrote a little example class to demonstrate my problem:
public class GameEngineView extends View {
private static final String TAG = GameEngineView.class.getSimpleName();
private int px;
private int py;
private int cx;
private int cy;
private boolean players_move;
private int clickx;
private int clicky;
Random rgen;
private RefreshHandler mRedrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
#Override
public void handleMessage(Message msg) {
GameEngineView.this.update();
GameEngineView.this.invalidate();
Log.d(TAG, "invalidate()");
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
public GameEngineView(Context context) {
super(context);
setFocusable(true);
players_move = true;
rgen = new Random();
}
public void update() {
updateGame();
Log.d(TAG, "update -> sleep handler");
mRedrawHandler.sleep(100);
}
public void updateGame() {
if(players_move) {
px = clickx;
py = clicky;
} else {
calcAIMove();
switchMove();
}
}
public void switchMove() {
players_move = !players_move;
}
public void calcAIMove() {
for(int i = 0; i < 20000; i++) {
cx = rgen.nextInt(getWidth());
cy = rgen.nextInt(getHeight());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "event");
int eventaction = event.getAction();
if(eventaction == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
clickx = (int) event.getX();
clicky = (int) event.getY();
switchMove();
update();
}
return super.onTouchEvent(event);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint green = new Paint();
green.setColor(Color.GREEN);
Paint red = new Paint();
red.setColor(Color.RED);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(px, py, 25, green);
canvas.drawCircle(cx, cy, 25, red);
}
}
The function calcAIMove() just burns time to simulate a real evaluation of the position in a board game.
Now my Problem is: If the player clicks(makes a move) the green ball is first drawn when the ai move calculation has been complete. So both moves are drawn at the same time.
I wonder HOW to accomplish this:
-Player clicks
-green Ball is drawn
-AI calculates
-red ball is drawn
-and so on..
When searching the web i found a lot of game loop examples but they all need a Thread with constant polling.. it should be possible without this since the whole program runs sequentially .. right?
Hoping for advice.
thanks,
Dave
Here is how your game could work:
user makes a move
game view is updated
game switches to CPU's turn
sleep to simulate CPU player thinking (if move computation is trivial)
compute CPU's move
game view is updated
game switches to player's turn
There is no need for constant polling in a turn-based game like this. The only place you should have sleep is in step 4, so you can remove it from the other areas (no need for the old update() method which is just a delayed call to updateGame()).
One way to implement this is to simply delay the call to calcAIMove() and switchMove() by putting it into a Runnable and using Handler.postDelayed() or similar.
I don't see how you are disabling touch events when it is the CPU's turn, which can lead to a host of other problems if switchMove() and update() are still being called...
In your game loop you can use a instance of TimerTask to ensure certain delay between greenBall and some other drawing task. Game tutorials like Snake and LunarLander are great references on when and if you need to invalidate your View. Hope this helps a little!
ok so the answer provided by antonyt helped me solve this.. I provide the corrected code for other interested ones.
public class GameEngineView extends View {
private static final String TAG = GameEngineView.class.getSimpleName();
private int px;
private int py;
private int cx;
private int cy;
private boolean players_move;
private int clickx;
private int clicky;
Random rgen;
/**
* Create a simple handler that we can use to cause animation to happen. We
* set ourselves as a target and we can use the sleep()
* function to cause an update/invalidate to occur at a later date.
*/
private RefreshHandler mRedrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
#Override
public void handleMessage(Message msg) {
GameEngineView.this.update();
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
public GameEngineView(Context context) {
super(context);
setFocusable(true);
players_move = true;
rgen = new Random();
}
public void update() {
if(players_move) {
Log.d(TAG, "new player x");
px = clickx;
py = clicky;
GameEngineView.this.invalidate();
switchMove();
mRedrawHandler.sleep(100);
} else {
Log.d(TAG, "new ai x");
calcAIMove();
GameEngineView.this.invalidate();
switchMove();
}
Log.d(TAG, "update -> sleep handler");
}
public void switchMove() {
players_move = !players_move;
}
public void calcAIMove() {
for(int i = 0; i < 100000; i++) {
cx = rgen.nextInt(getWidth());
cy = rgen.nextInt(getHeight());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "event");
int eventaction = event.getAction();
if(players_move && eventaction == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
clickx = (int) event.getX();
clicky = (int) event.getY();
update();
}
return super.onTouchEvent(event);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
Paint green = new Paint();
green.setColor(Color.GREEN);
Paint red = new Paint();
red.setColor(Color.RED);
canvas.drawCircle(px, py, 25, green);
canvas.drawCircle(cx, cy, 25, red);
}
}

Categories

Resources