1

一連の ARGB ビットマップを循環させるために、SurfaceView を拡張するクラスを作成しました。これは、基礎となるビットマップの状態が (通常は常にではありませんが) 新しいフレームごとに保持されることを除いて、ほとんど機能します。

つまり、最初に表示するフレームが不透明で、後続のフレームが透明である場合、元のフレームの不透明なピクセルは、新しいフレームが描画されるときに消去されません。

SurfaceHolder.lockCanvas() のドキュメントには具体的に次のように記載されているため、この動作は私を混乱させます。

「Surface のコンテンツは、unlockCanvas() と lockCanvas() の間で保持されることはありません。このため、Surface 領域内のすべてのピクセルを書き込む必要があります。」

背景が無地の場合、canvas.drawARGB(255,0,0,0) を呼び出すと黒くクリアされますが、背景を透明にしたいのですが、背景を透明にすることはできません。 canvas.drawARGB(0,0,0,0) は効果がないためです。

import java.util.ArrayList;
import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/*
 * Accepts a sequence of Bitmap buffers and cycles through them.
 */

class AnimatedBufferView extends SurfaceView implements Runnable
{
    Thread thread = null;
    SurfaceHolder surfaceHolder;
    volatile boolean running = false;

    ArrayList<Bitmap> frames;
    int curIndex = 0;

    public AnimatedBufferView(ArrayList<Bitmap> _frames, Context context) 
    {
        super(context);
        surfaceHolder = getHolder();
        frames = _frames;
    }

    public void onResume(){
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    public void onPause(){
        boolean retry = true;
        running = false;
        while(retry){
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void run() 
    {
        // TODO Auto-generated method stub
        while(running)
        {
            if(surfaceHolder.getSurface().isValid())
            {               
                Canvas canvas = surfaceHolder.lockCanvas();

                //clear the buffer?
                //canvas.drawARGB(255, 0, 0, 0);

                //display the saved frame-buffer..
                Matrix identity = new Matrix();
                Bitmap frame = frames.get(curIndex);
                canvas.drawBitmap(frame, identity, null);


                surfaceHolder.unlockCanvasAndPost(canvas);

                curIndex = (curIndex + 1) % frames.size();

                try {
                    thread.sleep( 100 );
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}
4

3 に答える 3

5

OK、問題はデフォルトの Porter-Duff 描画モードであり、透明な色の描画が不可能であることがわかりました。モードチェンジするしかない。つまり、

Canvas canvas surfaceView.lockCanvas();
canvas.drawColor(0, Mode.CLEAR);
于 2012-08-11T02:20:50.527 に答える
2

これはしばらく私を混乱させました。基本的に、フレームごとに画面全体を再描画する必要があります。これは、キャンバスをロックすると、ポストされた最後のフレームではなく、2 フレーム後のキャンバスが得られるためです。これは、フレームがバッファリングされる方法によるものです。現在表示されているバッファと、現在のバッファより前にポストされたバッファの 2 つだけです。キャンバスをロックすると、現在表示されていないキャンバスが表示されます (つまり、1 フレーム遅れたキャンバスが表示されます)。

これが、現在表示されている画面がすべてを描画する画面と交換されるため、バッファーをスワップバッファーと呼ぶのを聞くかもしれない理由です。これは、実際には最新のバッファを取得できないことを意味します。

それがあなたにとって何らかの意味を成すことを願っています。

于 2012-08-11T00:01:53.470 に答える