为了制作一个简单的游戏,我使用了一个模板来绘制带有这样位图的画布:
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); } } } }
答案 0 :(得分:265)
使用PorterDuff清晰模式绘制透明色可以实现我想要的技巧。
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
答案 1 :(得分:71)
如何为新布局清除(或重绘)WHOLE画布(=在游戏中尝试)?
只需拨打Canvas.drawColor(Color.BLACK)
或您想要清除Canvas
的任何颜色。
而且:我怎样才能更新屏幕的一部分?
由于Android OS在更新屏幕时重新绘制每个像素,因此没有这样的方法只更新“屏幕的一部分”。但是,当你没有清除Canvas
上的旧图纸时,旧图纸仍然在表面上,这可能只是“更新屏幕的一部分”的一种方式。
因此,如果您想“更新屏幕的一部分”,请避免调用Canvas.drawColor()
方法。
答案 2 :(得分:28)
在谷歌小组中找到了这个,这对我有用..
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint);
这样可以在保持设置位图的同时删除图形矩形等。
答案 3 :(得分:17)
我尝试了@mobistry的答案:
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
但它对我没用。
对我而言,解决方案是:
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
也许有人有同样的问题。
答案 4 :(得分:12)
mBitmap.eraseColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
答案 5 :(得分:12)
使用Path类的重置方法
Path.reset();
答案 6 :(得分:4)
请在surfaceview extend class constructor上粘贴下面的代码.............
构造函数编码
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" />
尝试以上代码......
答案 7 :(得分:3)
以下是最小示例的代码,显示您必须在每帧重绘Canvas的每个像素。
此活动每秒在SurfaceView上绘制一个新的Bitmap,而不会在之前清除屏幕。 如果你测试它,你会发现位图并不总是写入同一个缓冲区,屏幕将在两个缓冲区之间交替。
我在手机(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();
}
}
}
}
}
答案 8 :(得分: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();
}
答案 9 :(得分:2)
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
答案 10 :(得分:1)
在Java android中的Canvas上擦除与通过globalCompositeOperation通过javascript擦除HTML Canvas相似。逻辑相似。
U将选择DST_OUT(目标输出)逻辑。
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
注意:DST_OUT更加有用,因为如果绘画颜色的alpha值为50%,则DST_OUT可以擦除50%。因此,要完全清除为透明,颜色的Alpha必须为100%。建议应用paint.setColor(Color.WHITE)。并确保画布图像格式为RGBA_8888。
擦除后,使用SRC_OVER(源结束)返回正常绘图。
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
实际上,更新小区域显示将需要访问图形硬件,并且可能不支持。
最接近以获得最佳性能的是使用多图像层。
答案 11 :(得分:0)
别忘了调用invalidate();
canvas.drawColor(backgroundColor);
invalidate();
path.reset();
答案 12 :(得分:0)
使用以下方法,您可以清除整个画布或其中的一部分。
请不要忘记禁用硬件加速,因为 PorterDuff.Mode.CLEAR 不适用于硬件加速,并最终调用setWillNotDraw(false)
,因为我们重写了onDraw
方法。
//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, null);
//view's onDraw
Paint TransparentPaint = new Paint();
TransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, TransparentPaint);
答案 13 :(得分:0)
尝试删除活动的onPause()视图并添加onRestart()
LayoutYouAddedYourView.addView(YourCustomView); LayoutYouAddedYourView.removeView(YourCustomView);
添加视图后,onDraw()方法将被调用。
YourCustomView,是扩展View类的类。
答案 14 :(得分: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
}
}
答案 15 :(得分: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);
答案 16 :(得分:-1)
您的第一个要求,如何清除或重绘整个画布 - 答案 - 使用canvas.drawColor(color.Black)方法清除屏幕上的颜色为黑色或您指定的任何内容。
你的第二个要求,如何更新部分屏幕 - 答案 - 例如,如果你想在屏幕上保持所有其他内容不变,但在屏幕的一小块区域显示一个整数(比如计数器),每个都会增加五秒钟然后使用canvas.drawrect方法通过指定左上角的底部和绘制来绘制该小区域。然后计算你的计数器值(使用postdalayed 5秒等,llike Handler.postDelayed(Runnable_Object,5000);),将其转换为文本字符串,计算这个小矩形中的x和y坐标,并使用文本视图显示更改反价值。
答案 17 :(得分:-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);
}
}
答案 18 :(得分:-3)
致电
canvas.drawColor(Color.TRANSPARENT)