2

invalidate(Rect) が領域全体を無効にする理由がわかりません。領域は 5 つのセクションに分割され、それぞれに折れ線グラフが描かれています。各セクションには 100 ポイントが含まれます。データが時間 tn から tn+100 に到着すると、invalidate(new Rect(left, top, right bottom)) を呼び出します。ここで、top は画面の高さの上部です (ただし、底より低い数値です)。これにより、onDraw() メソッドの呼び出しが呼び出されます。tn から tn+100 までの領域が描画されますが、領域 tn-100 から tn の以前に描画されたセグメントは消去されます。それは永遠にそのように続きます。各無効化は、正しいその領域のみを描画します (それが私が持っている唯一のデータであるため) が、以前に描画されたデータはすべて消去されます。だから私はマーチングセグメントを手に入れます!

つまり、invalidate() または invalidate(Rect) を呼び出すと、同じ動作が得られます。

Rect() のパラメーターはピクセルであり、これが描画されている AlertDialog ウィンドウの高さと幅に基づいて値を取得していると想定しています。

最終的には「Rect()」の領域を縮小して、リアルタイムの描画をシミュレートし、領域ではなく時間ステップ t から t+1 までを無効にすることを望んでいます。

私は愚かなことをしているに違いない。

AlertDialog で行われているという事実が問題ではないことを願っています。

この部分は、「アンドロイド開発者」が私のような初心者がこれを正しく行うのを助けるためのものです。最初の一連のイベント:
1. コールバックで Bluetooth を介してデータが受信される
2. データのタイプが正しい場合、メイン アクティビティ (UI スレッド) で BroadcastReceiver が通知され、そこからパラメータを設定するルーチンが呼び出されるWaveFormView の が View クラスを拡張し、メイン アクティビティで onCreateDialog(id) コールバックを呼び出す ShowDialog(id) が呼び出されます。
3. 次に、invalidate() を呼び出します。
4. ダイアログがポップアップし、グラフが描画されます。
5. ShowDialog(id) への後続のすべての呼び出しは、onCreateDialog(id) をバイパスします。

それは機能しますが、パラメータに関係なく、領域全体が常に無効になります。ここにもユーザーイベントはありません。あなたの例から私が思いつくことができる最高のものは、showDialog(id) の後に自分自身を呼び出す代わりに onShow() に無効化を配置する次のとおりです。

@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が唯一の方法です。

ところで、我慢してくれてありがとう!

4

2 に答える 2

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);
    }
}
于 2012-05-02T23:39:17.650 に答える
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;
    }
于 2021-07-12T19:51:51.973 に答える