I have a Service that can draw a Canvas on top of all applications using a SYSTEM_ALERT_WINDOW which contains a custom View.
I am attempting to animate the Canvas object using a Thread which calls Canvas.draw(...) and postInvalidate() - I was hoping this would "move" the shape across the screen. It does not work.
I tried putting my custom View inside a ViewGroup container and added this to the WindowManager object - based on the following posts:
Animate system alert type view
WindowManager with Animation (is it possible?)
The Canvas object position does not change - what am I doing wrong?
Here is my code...
CursorService.java
public class CursorService extends Service {
private WindowManager windowManager;
private ViewGroup cursorContainer;
private Cursor cursor;
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
super.onCreate();
go();
}
public void go(){
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT
);
cursor = new Cursor(this);
cursorContainer = new LinearLayout(this);
cursorContainer.addView(cursor);
windowManager.addView(cursorContainer, params);
new Thread(new Runnable() {
@Override
public void run() {
cursor.x+=1;
cursor.y+=1;
cursor.radius=100;
}
}).start();
}
public void onDestroy() {
super.onDestroy();
if (cursorContainer!=null) windowManager.removeView(cursorContainer);
}
}
Cursor.java
public class Cursor extends View {
public float x;
public float y;
public float radius;
public Paint paint;
public Cursor(Context context) {
super(context);
x=0;
y=0;
radius=0;
paint=new Paint();
paint.setColor(Color.RED);
new Thread(new Runnable() {
public void run() {
while (true){
try{
Thread.sleep(100);
postInvalidate();
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}).start();
}
@Override
protected void onDraw(Canvas canvas){
canvas.drawCircle(x, y, radius, paint);
}
}
First of all you need smth like while(true){} cycle in your runnable because in your code postInvalidate() method would be called just once.
But would be much better to call invalidate() method in onDraw and calculate your circle position by using the current time.
public class Cursor extends View {
public Cursor(Context context) {
super(context);
startTime = System.currentTimeMills();
}
@Override
protected void onDraw(Canvas canvas){
long delta = System.currentTimeMills() - startTime;
// ... calculate x and y using delta
canvas.drawCircle(x, y, radius, paint);
invalidate();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With