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?
source to share
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.
source to share