Android: stream to update
I have Service
one that can draw Canvas
on top of all applications using SYSTEM_ALERT_WINDOW
that contains a custom one View
.
I am trying to animate an object Canvas
using Thread
which calls Canvas.draw(...)
and postInvalidate()
- I was hoping this would "move" the form around the screen. This does not work.
I tried to put my custom View
in a container ViewGroup
and add it to an object WindowManager
- based on the following posts:
Animate a system alert type view
WindowManager with animation (is it possible?)
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);
}
}
source to share
First of all you will need the smth loop like while(true){}
in your runnable, because in your code the postInvalidate()
method will only be called once.
But it would be much better to call the method invalidate()
in onDraw
and calculate the position of your circle 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();
}
}
source to share
Since you are changing x
, y
and radius
from a separate thread, you must make them unstable. Otherwise, the changes you make to these variables (from the background thread) will not be visible to your view (on the UI thread).
public volatile float x;
public volatile float y;
public volatile float radius;
source to share