Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why onDraw() calling constantly?

I've a small application which uses customized LinearLayout, called LinearlayoutOutlined. I want to draw different sized and coloured boxes in it. It has also two text labels indicating time intervals. The layout has to be redraw after some user action. Therefore I do refresh the layout as is

slotPanel.setDayBoundariesInMinutes( db, dw );
TimeSlot[] tSlots = nextDaysSlots.getGaps( dayOfWeek );
slotPanel.setItems( tSlots );
slotPanel.invalidate();  

where slotpanel is the LinearLayoutOutlined instance.

I detected that the onDraw method is called constantly. It is not stops calling after particular number of cycles.

Here is the whole LinearLayoutOutlined class:

package com.widgets;

public class LinearLayoutOutlined extends LinearLayout {
    private int workingTimeBeginsInMinutes;
    private int workingTimeFinishesInMinutes;
    private TimeSlot[] items;
    private Rect outline;
    private Paint strokePaint = new Paint();
    SimpleDateFormat formatter;
    public LinearLayoutOutlined( Context context ) {
        super( context );
        setWillNotDraw( false );
    }
    public LinearLayoutOutlined( Context context, AttributeSet attrs ) {
        super( context, attrs );
        setWillNotDraw( false );
    }
    public void setWorkingTimeBeginsInMinutes( int m ) {
        this.workingTimeBeginsInMinutes = m;
    }
    public void setWorkingTimeFinishesInMinutes( int m ) {
        this.workingTimeFinishesInMinutes = m;
    }
    public void setDayWidthInMinutes( int dayWidthInMinutes ) {
        this.workingTimeFinishesInMinutes = this.workingTimeBeginsInMinutes +  dayWidthInMinutes;
    }
    public void setDayBoundariesInMinutes( int daybeginInMinutes, int dayWidthInMinutes ) {
        setWorkingTimeBeginsInMinutes( daybeginInMinutes );
        setDayWidthInMinutes( dayWidthInMinutes );
    }
    private int getWorkingTimeBeginsInMinutes() {
        return workingTimeBeginsInMinutes;
    }
    public int getWorkingTimeFinishesInMinutes() {
        return workingTimeFinishesInMinutes;
    }
    public void setItems( TimeSlot[] items ) {
        this.items = items;
    }
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw( Canvas canvas ) {
        if( items == null ) return;
        // time labels
        TextView tvFrom = ( TextView )findViewById( R.id.lblStartingTime ), tvTo = ( TextView )findViewById( R.id.lblFinishingTime );
        formatter = new SimpleDateFormat( "HH:mm", Locale.getDefault() );
        tvFrom.setText( formatter.format( new Date( getWorkingTimeBeginsInMinutes() * 60000L ) ) );
        tvTo.setText( formatter.format( new Date( getWorkingTimeFinishesInMinutes() * 60000L ) ) );
        strokePaint.setStyle( Paint.Style.STROKE );
        strokePaint.setStrokeWidth( 1 );
        strokePaint.setStyle( Style.FILL );
        outline = canvas.getClipBounds();
        Convert.setDayBoundaries( getWorkingTimeBeginsInMinutes(), getWorkingTimeFinishesInMinutes(), outline );
        for( TimeSlot slotItem: items ) {
            RectTouchable rect = Convert.ToRect( slotItem );
            if( slotItem.isFree() )
                strokePaint.setARGB( 255, 0, 255, 0 );
            else
                strokePaint.setARGB( 255, 255, 0, 0 );
            canvas.drawRect( rect.getRect(), strokePaint );
        }
    }
}

Please give me some idea, what should I do? Thanx in advance


I don't understand why I cannot add comment to my own question?!?

@Romain Guy: Thank you! OK I understand. But I have to setText() together with drawin boxes. The textlabels are overlayed, they are the topmost. What should I do?

like image 256
Franziee Avatar asked Jan 15 '23 05:01

Franziee


1 Answers

Every time you call setText() on a TextView the UI toolkit needs to relayout and repaint the UI. Since you are doing this every time onDraw() is called you've basically created an infinite drawing loop.

There are other issues in your draw method as well: you should not do a findViewById() every time, you should not create a new SimpleDateFormat every time, you should not create new Date objects every time, etc.

like image 66
Romain Guy Avatar answered Jan 21 '23 10:01

Romain Guy