我不明白为什么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是唯一的方法。
顺便说一句,谢谢你忍住我!
答案 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;
}