Why is the onDraw () call constantly?

I have a small application that uses a custom LinearLayout called LinearlayoutOutlined. I want to draw different sized and colored rectangles in it. It also has two text labels indicating time intervals. After some user action, the layout should be redrawn. So I update the layout like

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

      

where slotpanel is a LinearLayoutOutlined instance.

I found that the onDraw method gets called all the time. This does not stop the call after a certain number of cycles.

Here's the whole LinearLayoutOutlined class:

com.widgets package;

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 let me know what should I do? Thank you in advance


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

@Romain Guy: Thanks! OK I understood. But I have to setText () along with drawin box. The text labels overlap, they are the topmost. What should I do?

+3


source to share


2 answers


Every time you call setText()

on TextView

, the UI toolkit has to relay and redraw the interface. Since you do this every time you call onDraw()

, you basically created an infinite paint loop.



There are other problems with the drawing method: you don't have to do findViewById()

every time, you should SimpleDateFormat

n't create a new Date

one every time , you shouldn't create new objects every time, etc.

+8


source


You can avoid an infinite loop if you call setText in onDraw () only if the text has changed. Use this method instead of setText:



void setTextIfChanged(TextView tv, CharSequence text) {
    if (!text.equals(tv.getText()))
        tv.setText(text);
}

      

0


source







All Articles