为什么onDraw()不断调用?

时间:2013-02-13 19:17:35

标签: android android-linearlayout

我有一个使用自定义LinearLayout的小应用程序,名为LinearlayoutOutlined。我想在其中绘制不同大小和彩色的盒子。它还有两个指示时间间隔的文本标签。在进行一些用户操作后,必须重新绘制布局。因此我按原样刷新布局

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

其中 slotpanel LinearLayoutOutlined 实例。

我检测到onDraw方法被不断调用。在特定的循环次数之后,它不会停止调用。

以下是整个LinearLayoutOutlined类:

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

请给我一些想法,我该怎么办? Thanx提前


我不明白为什么我不能在自己的问题上添加评论?!

@Romain Guy: 谢谢!好的,我明白了。但我必须将setText()与drawin框一起使用。文本标签被覆盖,它们是最顶层的。我该怎么办?

2 个答案:

答案 0 :(得分:8)

每次在setText()上调用TextView时,UI工具包都需要重新布局并重新绘制UI。由于每次调用onDraw()时都会这样做,所以你基本上创建了一个无限的绘图循环。

您的绘制方法中还存在其他问题:您不应每次都执行findViewById(),每次都不应创建新SimpleDateFormat,不应创建新的Date每次都有对象,等等。

答案 1 :(得分:0)

如果只在文本发生变化时调用onDraw()中的setText,则可以避免无限循环。 而不是setText使用此方法:

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