Android invalidate(Rect)使整个区域无效

时间:2012-05-02 23:14:30

标签: android graphics invalidation

我不明白为什么invalidate(Rect)使整个区域无效。 该区域分为5个部分,每个部分都绘制了一个折线图。每个部分包含100个点。当数据到达时间tn到tn + 100时,我调用invalidate(新的Rect(左,上,右下)),其中top是屏幕顶部的高度(但是数值低于bottom)。这将调用onDraw()方法。绘制从tn到tn + 100的区域,但是区域tn-100到tn中先前绘制的段被擦除。它永远地继续下去。每个无效区域仅绘制该区域(因为这是我拥有的唯一数据),这是正确的,但所有先前绘制的数据都将被删除。所以我得到一个行进部分!

换句话说,如果我调用invalidate()或invalidate(Rect),我会得到相同的行为。

我假设Rect()的参数是像素,并且根据正在绘制它的AlertDialog窗口的高度和宽度来获取值。

希望最终减少'Rect()'的区域,这样我就可以模拟实时绘图,只会使时间步t变为t + 1而不是区域。

我必须做些蠢事。

我希望它在AlertDialog中完成的事实不是问题。

这部分是为了帮助'android开发者'帮助像我这样的菜鸟做对了。 首先是一系列事件:
1.数据通过蓝牙在回叫中接收 2.如果它是正确的数据类型,则主要活动(UI线程)中的BroadcastReceiver发出信号,并从那里调用一个例程来设置WaveFormView扩展View类的参数,然后调用ShowDialog(id)调用哪些调用主要活动中的onCreateDialog(id)回调 然后我叫无效()。
4.弹出对话框,然后绘制图形 5.对ShowDialog(id)的所有后续调用都会绕过onCreateDialog(id)

无论参数如何,都可以使整个区域无效。这里也没有用户事件。从你的例子中我可以得到的最好的是以下我在onShow()中放置invalidate而不是在showDialog(id)之后调用自己

@Override
protected Dialog onCreateDialog(int id)
{
    Log.d(TAG, "Alert Dialog 'onCreateDialog' method has been called with id " + id);
    Builder bldr = new AlertDialog.Builder(this);
    AlertDialog alert = bldr.setView(waveForm).setNegativeButton("Dismiss " + id, 
            new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialog, int id)
                {
                    dialog.cancel();
                } 
            }).create();
    // I tried adding this and invalidating here worked only first pass
    alert.setOnShowListener(
                    new DialogInterface.OnShowListener()
                    {
                        @Override
                        public void onShow(DialogInterface dialog)
                        {
                            // call to invalidate
                            waveForm.drawArea();
                        }
                    });

    //alert.getWindow().setLayout(alert.getWindow().getAttributes().width, alert.getWindow().getAttributes().height / 2);
    alert.getWindow().setLayout(waveForm.getCurrentWidth(), waveForm.getCurrentHeight());

    return alert;
}

然而,onShow()不会被调用。

调用showDialog的主要活动中的方法是

private void displayRtsa(int[] rtsaReceived)
{
    // rtsaReceived[0] has the agentsink hash code
    int agent = rtsaReceived[0];
    // rtsaReceived[1] has the index of the RtsaData object updated
    int index = rtsaReceived[1];
    TreeMap<Integer, RtsaData[]> agentRtsa = BluetoothPanService.getAgentRtsaMap();
    RtsaData[] rtsaDataValues = agentRtsa.get(agent);

    int dialogId = 0;
    synchronized(dialogIds)
    {
        int i = 0;
        if(dialogIds.containsKey(agent + index) == false)
        {
            for(i = 0; i < dialogIds.size(); i++)
            {
                if(dialogIds.containsValue(i) == false)
                {
                    break;
                }
            }
            dialogIds.put(agent + index, i);
        }
        dialogId = dialogIds.get(agent + index);
    }
    final int id = dialogId;
    Log.d(TAG, "Dialog id being shown = " + dialogId);
    waveForm.setPeriod(rtsaDataValues[index].getPeriod());
    waveForm.setMaxMin(rtsaDataValues[index].getMinValue(), rtsaDataValues[index].getMaxValue());
    waveForm.setColor(Color.argb(255, 255, 200, 0));
    waveForm.setData(rtsaDataValues[index].getData());
    waveForm.setTitle(rtsaDataValues[index].getType());
    showDialog(id);
    // invalidate
    // waveForm.drawArea(); (try to do in onCreateDialog callback)
}

这可能是一种完全错误的做法。可能openGl是唯一的方法。

顺便说一句,谢谢你忍住我!

2 个答案:

答案 0 :(得分:0)

我认为这取决于你究竟做了什么失效。如果您调用失效的视图未处理矩形失效,则会发生默认失效。

在任何情况下,如果您想改变行为,您可以自己更改。对于“onDraw”方法,使用下一个代码来获取无效的矩形:

public class InvalidateTestActivity extends Activity
{
    static class CustomView extends ImageView

    {

        public CustomView(Context context)
        {
            super(context);
        }

        @Override
        protected void onDraw(Canvas canvas)
        {
            final Rect r = canvas.getClipBounds();
            Log.d("DEBUG", "rectangle of invalidation:" + r);
            super.onDraw(canvas);
        }

    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        CustomView customView = new CustomView(this);
        customView.setLayoutParams(new FrameLayout.LayoutParams(200, 200));
        customView.setBackgroundColor(0xffff0000);
        customView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v)
            {
                v.invalidate(new Rect(0, 0, 49, 49));
            }
        });
        setContentView(customView);
    }
}

答案 1 :(得分:0)

如果您启用了硬件加速,它看起来只会使整个视图无效...

视图组:

public final void invalidateChild(View child, final Rect dirty) {
    final AttachInfo attachInfo = mAttachInfo;
    if (attachInfo != null && attachInfo.mHardwareAccelerated) {
        // HW accelerated fast path
        onDescendantInvalidated(child, child);
        return;
    }