105

簡単なゲームを作成するために、次のようなビットマップでキャンバスを描画するテンプレートを使用しました。

private void doDraw(Canvas canvas) {
    for (int i=0;i<8;i++)
        for (int j=0;j<9;j++)
            for (int k=0;k<7;k++)   {
    canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }

(キャンバスは「run()」で定義されます/ SurfaceViewはGameThreadに存在します。)

私の最初の質問は、新しいレイアウトのためにキャンバス全体をクリア(または再描画)するにはどうすればよいですか?
次に、画面の一部だけを更新するにはどうすればよいですか?

// This is the routine that calls "doDraw":
public void run() {
    while (mRun) {
        Canvas c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) 
                    updateGame();
                doDraw(c);          }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);  }   }   }       }
4

21 に答える 21

288

PorterDuffクリアモードで透明色を描くと、私が望んでいたことをうまく行うことができます。

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
于 2012-06-04T13:37:35.673 に答える
83

新しいレイアウトのためにキャンバス全体をクリア(または再描画)するにはどうすればよいですか(=ゲームで試してみてください)?

Canvas.drawColor(Color.BLACK)、またはクリアしたい色を呼び出すだけですCanvas

そして:どうすれば画面の一部だけを更新できますか?

Android OSは画面の更新時にすべてのピクセルを再描画するため、「画面の一部」を更新するだけの方法はありません。ただし、の古い図面をクリアしていない場合でもCanvas、古い図面は表面に残っているため、画面の「一部のみを更新」する方法の1つである可能性があります。

したがって、「画面の一部を更新」する場合は、メソッドの呼び出しを避けてくださいCanvas.drawColor()

于 2011-04-20T12:01:33.863 に答える
35

これをグーグルグループで見つけて、これは私のために働いた。

Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint); 

これにより、設定されたビットマップを維持しながら、図面の長方形などが削除されます。

于 2012-09-04T12:13:42.577 に答える
21

Pathクラスのresetメソッドを使用する

Path.reset();
于 2013-11-06T12:22:27.033 に答える
18

@mobistryの答えを試しました:

canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);

しかし、それは私にはうまくいきませんでした。

私にとっての解決策は次のとおりです。

canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);

たぶん誰かが同じ問題を抱えています。

于 2014-05-21T04:47:21.897 に答える
12
mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
于 2012-11-02T13:27:17.737 に答える
5
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
于 2017-03-05T07:38:25.717 に答える
4

以下のコードをsurfaceview拡張クラスコンストラクターに貼り付けてください............。

コンストラクターコーディング

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    SurfaceView sur = (SurfaceView)findViewById(R.id.surfaceview);
    sur.setZOrderOnTop(true);    // necessary
    holder = sur.getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);

xmlコーディング

    <com.welcome.panelview.PanelViewWelcomeScreen
        android:id="@+id/one"
        android:layout_width="600px"
        android:layout_height="312px"
        android:layout_gravity="center"
        android:layout_marginTop="10px"
        android:background="@drawable/welcome" />

上記のコードを試してください...

于 2012-06-22T07:25:37.070 に答える
3

これは、各フレームでCanvasのすべてのピクセルを常に再描画する必要があることを示す最小限の例のコードです。

このアクティビティは、前に画面をクリアせずに、SurfaceViewに毎秒新しいビットマップを描画します。テストすると、ビットマップが常に同じバッファーに書き込まれるとは限らず、画面が2つのバッファー間で交互に表示されることがわかります。

携帯電話(Nexus S、Android 2.3.3)とエミュレーター(Android 2.2)でテストしました。

public class TestCanvas extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TestView(this));
    }
}

class TestView extends SurfaceView implements SurfaceHolder.Callback {

    private TestThread mThread;
    private int mWidth;
    private int mHeight;
    private Bitmap mBitmap;
    private SurfaceHolder mSurfaceHolder;

    public TestView(Context context) {
        super(context);
        mThread = new TestThread();
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        mWidth = width;
        mHeight = height;
        mThread.start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {/* Do nothing */}

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mThread != null && mThread.isAlive())
            mThread.interrupt();
    }

    class TestThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        c.drawBitmap(mBitmap, (int) (Math.random() * mWidth), (int) (Math.random() * mHeight), null);
                    }
                } finally {
                    if (c != null)
                        mSurfaceHolder.unlockCanvasAndPost(c);
                }

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }   
    }
}
于 2011-04-20T13:26:04.663 に答える
3

私にとって、電話Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)などは画面に触れた後にのみ機能します。したがって、上記のコード行を呼び出しますが、画面に触れた後にのみ画面がクリアされます。だから私のために働いたのは、ビューを初期化するために作成時に呼び出されたinvalidate()後に呼び出されることでした。init()

private void init() {
    setFocusable(true);
    setFocusableInTouchMode(true);
    setOnTouchListener(this);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);

    mCanvas = new Canvas();
    mPaths = new LinkedList<>();

    addNewPath();
}
于 2015-08-30T19:15:58.853 に答える
2

java androidのCanvasでの消去は、globalCompositeOperationを使用したjavascriptによるHTMLCanvasの消去と同様です。論理は似ていました。

UはDST_OUT(Destination Out)ロジックを選択します。

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

注:DST_OUTは、ペイントカラーのアルファが50%の場合、50%を消去できるため、より便利です。したがって、完全に透明にクリアするには、色のアルファが100%である必要があります。paint.setColor(Color.WHITE)を適用することをお勧めします。また、キャンバスの画像形式がRGBA_8888であることを確認してください。

消去後、SRC_OVER(ソースオーバー)で通常の描画に戻ります。

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));

小領域ディスプレイの更新は、文字通りグラフィックハードウェアにアクセスする必要があり、サポートされていない可能性があります。

最高のパフォーマンスを得るには、マルチイメージレイヤーを使用するのが最も効果的です。

于 2020-06-14T10:02:56.517 に答える
1

invalidate();を呼び出すことを忘れないでください。

canvas.drawColor(backgroundColor);
invalidate();
path.reset();
于 2019-08-17T16:28:40.147 に答える
1

次のアプローチでは、キャンバス全体または一部のみをクリアできます。PorterDuff.Mode.CLEAR
はハードウェアアクセラレーションでは機能しないため、ハード ウェアアクセラレーションを無効にすることを忘れないでください。メソッドをオーバーライドするため、最後に呼び出します。setWillNotDraw(false)onDraw

//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_SOFTWARE, null);

//view's onDraw
Paint TransparentPaint = new Paint();
TransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, TransparentPaint); 
于 2019-08-22T13:08:59.037 に答える
0

アクティビティのonPause()でビューを削除し、onRestart()を追加してみてください

LayoutYouAddedYourView.addView(YourCustomView); LayoutYouAddedYourView.removeView(YourCustomView);

ビューを追加すると、onDraw()メソッドが呼び出されます。

YourCustomViewは、Viewクラスを拡張するクラスです。

于 2019-10-17T07:17:53.347 に答える
0

私の場合、キャンバスをlinearlayoutに描画します。クリーニングして再描画するには:

    LinearLayout linearLayout = findViewById(R.id.myCanvas);
    linearLayout.removeAllViews();

次に、新しい値を使用してクラスを呼び出します。

    Lienzo fondo = new Lienzo(this,items);
    linearLayout.addView(fondo);

これはクラスLienzoです:

class Lienzo extends View {
    Paint paint;
    RectF contenedor;
    Path path;
    ArrayList<Items>elementos;

    public Lienzo(Context context,ArrayList<Items> elementos) {
        super(context);
        this.elementos=elementos;
        init();
    }

    private void init() {
        path=new Path();
        paint = new Paint();
        contenedor = new RectF();
        paint.setStyle(Paint.Style.FILL);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        contenedor.left = oneValue;
        contenedor.top = anotherValue;
        contenedor.right = anotherValue;
        contenedor.bottom = anotherValue;

        float angulo = -90; //starts drawing at 12 o'clock
        //total= sum of all element values
        for (int i=0;i<elementos.size();i++){
            if (elementos.get(i).angulo!=0 && elementos.get(i).visible){
                paint.setColor(elementos.get(i).backColor);
                canvas.drawArc(contenedor,angulo,(float)(elementos.get(i).value*360)/total,true,paint);

                angulo+=(float)(elementos.get(i).value*360)/total;
            }
        } //for example
    }
}
于 2020-07-24T18:24:13.453 に答える
0

私の場合、メモリに優しいわけではありませんが、毎回キャンバスを作成することは私にとってはうまくいきました

Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);
imageBitmap = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
canvas = new Canvas(imageBitmap);
canvas.drawBitmap(bm, 0, 0, null);
于 2021-02-15T15:43:40.390 に答える
0

以下は私のために働いた:

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SCREEN);
于 2021-12-17T23:34:11.200 に答える
0

私は自分の解決策を見つけました。

PaintViewクラス:

public void clear() {
    mPath.reset();
    mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    paths.clear();
}

そしてMainActivity:

  clear_canvas_.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            paintView.clear();
        }
    });
于 2022-01-11T07:19:28.853 に答える
-1

最初の要件である、キャンバス全体をクリアまたは再描画する方法-回答-canvas.drawColor(color.Black)メソッドを使用して、画面を黒または指定した色でクリアします。

2番目の要件、画面の一部を更新する方法-回答-たとえば、画面上で他のすべてのものを変更せずに、画面の小さな領域に5秒ごとに増加する整数(たとえばカウンター)を表示したい場合。次に、canvas.drawrectメソッドを使用して、左上と右下を指定してペイントすることにより、その小さな領域を描画します。次に、カウンター値を計算し(postdalayedを5秒間使用するなど、Handler.postDelayed(Runnable_Object、5000);のように)、それをテキスト文字列に変換し、この小さなrectのx座標とy座標を計算し、テキストビューを使用して変化を表示しますカウンター値。

于 2013-04-08T01:28:11.013 に答える
-1

キャンバスをクリアするために別の描画パスを使用する必要がありました(ロック、描画、ロック解除):

Canvas canvas = null;
try {
    canvas = holder.lockCanvas();
    if (canvas == null) {
        // exit drawing thread
        break;
    }
    canvas.drawColor(colorToClearFromCanvas, PorterDuff.Mode.CLEAR);
} finally {
    if (canvas != null) {
        holder.unlockCanvasAndPost(canvas);
    }
}
于 2018-08-12T18:51:53.947 に答える
-3

電話するだけ

canvas.drawColor(Color.TRANSPARENT)

于 2011-11-29T09:20:20.100 に答える