0

I need to access canvas I created from another class.

So I have a class which extends LinearLayout drawing arc.

Now from main activity I need to access this canvas it is drawn on and redraw it. Ideally only some parts of it.

Here are some codes stripped to main.

ArchProgressBar.java (the one with canvas)

public class ArchProgressBar extends LinearLayout {

    public ArchProgressBar(Context context, AttributeSet attrs) {

    private void init(Context context) {
        this.setWillNotDraw(false);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.arch_progress_bar, this, true);
        this.postInvalidate();
    }

    static void drawMeCircle(int aka) {

    }

    @Override
    public void onDraw(Canvas canvas) {

        int mPaintHex = 0xFFFFFFFF;
        int mPaintColor = Color.argb(100, Color.red(mPaintHex), Color.green(mPaintHex), Color.blue(mPaintHex));

        float left = 295;
        float top = 712;
        float right = 788;
        float bottom = 1208;

        Paint mPaintBackground = new Paint();
        mPaintBackground.setAntiAlias(true);
        mPaintBackground.setStyle(Paint.Style.STROKE);
        mPaintBackground.setStrokeWidth(13);
        mPaintBackground.setColor(mPaintColor);

        RectF mRectF = new RectF(left, top, right, bottom);

        // THIS IS BACKGROUND LINE! draw background line
        canvas.drawArc(mRectF, START_ANGLE, ARCH_LENGTH, false, mPaintBackground);

        int mHourHex = 0xFF00FF00;
        int mHourColor = Color.argb(255, Color.red(mHourHex), Color.green(mHourHex), Color.blue(mHourHex));

        Paint mPaintHours = new Paint();
        mPaintHours.setAntiAlias(true);
        mPaintHours.setStyle(Paint.Style.STROKE);
        mPaintHours.setStrokeWidth(13);
        mPaintHours.setColor(mHourColor);

        RectF mRectH = new RectF(left, top, right, bottom);

        // THIS IS HOUR LINE!draw hour line
        Calendar hCal = Calendar.getInstance();
        int hHour = hCal.get(Calendar.HOUR);
        if(hHour != 0) {
            for(int i=0; i<hHour-1; i++){
                canvas.drawArc(mRectH, START_ANGLE + ARCH_LENGTH + (i*30) +2, ARCH_LENGTH, false, mPaintHours);
            }
        }
    }

HomeActivity.java main activity for app (extends Activity)

public class HomeActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_TIME_TICK);
        mIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        mIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        registerReceiver(m_timeChangedReceiver, mIntentFilter);
    }
    //clock thing start
    private final BroadcastReceiver m_timeChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
                Calendar hCal = Calendar.getInstance();
                int hHour = hCal.get(Calendar.HOUR);
                ArchProgressBar.drawMeCircle(1);
        }
    };

    public void showApps(View v){
        Intent i = new Intent(this, AppsListActivity.class);
        startActivity(i);
    }
}

now When BroadcastRecieved is triggered I want to access ArchProgressBar's canvas, delete the hour line (or whole thing if not possible to delete just that part) and redraw something new on it.

if you are wandering whats with drawMeCircle. It is just something I was playing with. included to show how I think it must work.

CBeTJlu4ok
  • 1,072
  • 4
  • 18
  • 51
  • 1
    Where do you register the BroadcastReceiver? – Code-Apprentice Oct 24 '16 at 19:55
  • @Code-Apprentice I updated code – CBeTJlu4ok Oct 24 '16 at 20:14
  • 1
    Possible duplicate of [How to update UI in a BroadcastReceiver](http://stackoverflow.com/questions/14643385/how-to-update-ui-in-a-broadcastreceiver) – Code-Apprentice Oct 24 '16 at 20:15
  • 1
    See if any of the answers to the above question will help. – Code-Apprentice Oct 24 '16 at 20:16
  • @Code-Apprentice looks like I'm not explaining myself well. I just want to access `canvas` that is used in method `public void onDraw(Canvas canvas)` – CBeTJlu4ok Oct 24 '16 at 20:20
  • 2
    You can only access that variable safely during execution of `onDraw()`, including methods which it calls. After `onDraw()` has finished, however, you shouldn't access it outside of this time frame. Instead, you should implement a way to tell `ArchProgressBar` how it should draw itself. – Code-Apprentice Oct 24 '16 at 20:24
  • I see. Then this broadcast should probably go inside `ArchProgressBar` right? this way I'll be detecting time change event and handling it where canvas is located. – CBeTJlu4ok Oct 24 '16 at 20:26
  • 1
    Is the progress bar guaranteed to be visible whenever the receiver receives a broadcast? – Code-Apprentice Oct 24 '16 at 20:28
  • @Code-Apprentice well, no – CBeTJlu4ok Oct 24 '16 at 20:32
  • 1
    Then your above proposed solution is probably too simplistic. I suggest you read the link above in more detail. I agree that your situation is a bit more complex because you are doing this with a custom view. However, much of the answers should still apply. – Code-Apprentice Oct 24 '16 at 20:34

1 Answers1

1

You just need to change some value inside your view object and call invalidate() to get what you need. This will redraw the canvas as soon as it can. About your code I'd suggest to modify it in this way (let's suppose that your view has an id = @+id/arch_progress_bar)

HomeActivity

private final BroadcastReceiver m_timeChangedReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        Calendar hCal = Calendar.getInstance();
        int hHour = hCal.get(Calendar.HOUR);
        ArchProgressBar bar = (ArchProgressBar) findViewById(R.id.arch_progress_bar);
        if (bar != null) {
            bar.drawMeCircle(1);
        }
    }
};

// remember to unregister the broadcast receiver in your onDestroy()
// as further optimization, you can also move the findViewById inside your onCreate(), so you don't have to repeat it for every broadcast you get

ArchProgressBar

pubic void drawMeCircle(int aka) {
     // your business logic
     invalidate();
}   // Remove the static keyword, it's not necessary

Last consideration: you should take care of activity recreation because of display rotation. To manage this case, you should save the value you got from the broadcast receiver (1 in this example?) during onSaveInstanceState() activity callback, retrieve it via the bundle you get as onCreate parameter and set it again to your view.

Mimmo Grottoli
  • 5,758
  • 2
  • 17
  • 27
  • about last part, what if my app does not rotate. no problem right? because I did not understand much from it – CBeTJlu4ok Oct 28 '16 at 16:30