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);
    }
}

      

+3


source to share


2 answers


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();
    }
}

      

+2


source


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;

      

-1


source







All Articles