Para fazer um jogo simples, usei um modelo que desenha uma tela com bitmaps como este:
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); } }
(A tela é definida em "run ()" / o SurfaceView reside em um GameThread.)
Minha primeira pergunta é como faço para limpar (ou redesenhar) a tela inteira para um novo layout?
Em segundo lugar, como posso atualizar apenas uma parte da tela?
// 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); } } } }
fonte
mSurfaceHolder.unlockCanvasAndPost(c)
e entãoc = mSurfaceHolder.lockCanvas(null)
, o novoc
não contém a mesma coisa que o anteriorc
. Você não pode atualizar apenas uma parte de um SurfaceView, que é o que o OP estava pedindo, eu acho.Canvas
mantém desenhos antigos.Desenhar cores transparentes com o modo de limpeza PorterDuff resolve o que eu queria.
fonte
Bitmap#eraseColor(Color.TRANSPARENT)
, como na resposta do HeMac abaixo.Color.TRANSPARENT
é desnecessário.PorterDuff.Mode.CLEAR
é totalmente o suficiente para umARGB_8888
bitmap, o que significa definir o alfa e a cor como [0, 0]. Outra maneira é usarColor.TRANSPARENT
comPorterDuff.Mode.SRC
.Encontrei isso em grupos do Google e funcionou para mim ..
Isso remove retângulos de desenhos etc., enquanto mantém o bitmap definido.
fonte
Tentei a resposta de @mobistry:
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
Mas não funcionou para mim.
A solução, para mim, foi:
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
Talvez alguém tenha o mesmo problema.
fonte
use o método de redefinição da classe Path
fonte
fonte
cole o código abaixo em surfaceview extend class constructor .............
codificação do construtor
codificação xml
tente o código acima ...
fonte
Aqui está o código de um exemplo mínimo, mostrando que você sempre tem que redesenhar cada pixel do Canvas em cada quadro.
Esta atividade desenha um novo Bitmap a cada segundo no SurfaceView, sem limpar a tela antes. Se você testá-lo, verá que o bitmap nem sempre é gravado no mesmo buffer e a tela alternará entre os dois buffers.
Testei no meu telefone (Nexus S, Android 2.3.3) e no emulador (Android 2.2).
fonte
SurfaceHolder.Callback
, não apenasCallback
.Canvas
se quisermos redesenhar totalmente a tela inteira. Isso torna verdadeira minha afirmação sobre "desenhos anteriores". OCanvas
guarda desenhos anteriores.Canvas
mantém os desenhos anteriores. Mas isso é completamente inútil, o problema é que quando você usalockCanvas()
você não sabe o que são aqueles “desenhos anteriores”, e não pode presumir nada sobre eles. Talvez se houver duas atividades com um SurfaceView do mesmo tamanho, elas compartilharão o mesmo Canvas. Talvez você obtenha um pedaço de RAM não inicializado com bytes aleatórios nele. Talvez haja sempre o logotipo do Google escrito no Canvas. Você não pode saber. Qualquer aplicativo que não estiver desenhando todos os pixels depoislockCanvas(null)
será quebrado.Para mim, ligar
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
ou algo semelhante só funcionaria depois de tocar na tela. Então, eu chamaria a linha de código acima, mas a tela só limparia depois que eu toquei na tela. Então, o que funcionou para mim foi chamarinvalidate()
seguido deinit()
que é chamado no momento da criação para inicializar a visualização.fonte
fonte
Apagar no Canvas em java android é semelhante ao apagar HTML Canvas via javascript com globalCompositeOperation. A lógica era semelhante.
U escolherá a lógica DST_OUT (Destination Out).
Nota: DST_OUT é mais útil porque pode apagar 50% se a cor da tinta tiver 50% alfa. Portanto, para clarear completamente para transparente, o alfa da cor deve ser 100%. Aplicar paint.setColor (Color.WHITE) é recomendado. E certifique-se de que o formato da imagem da tela era RGBA_8888.
Depois de apagado, volte ao desenho normal com SRC_OVER (Source Over).
Atualizar a exibição de pequena área literalmente precisará acessar o hardware gráfico e talvez não seja compatível.
O mais próximo para o melhor desempenho é usar a camada de várias imagens.
fonte
Não se esqueça de chamar invalidate ();
fonte
invalidate
depois de desenhar algo?Tente remover a visualização em onPause () de uma atividade e adicionar onRestart ()
LayoutYouAddedYourView.addView (YourCustomView); LayoutYouAddedYourView.removeView (YourCustomView);
No momento em que você adiciona sua visão, o método onDraw () é chamado.
YourCustomView, é uma classe que estende a classe View.
fonte
No meu caso, desenho minha tela em layout linear. Para limpar e redesenhar novamente:
e então chamo a classe com os novos valores:
Esta é a classe Lienzo:
fonte
Com a abordagem a seguir, você pode limpar toda a tela ou apenas uma parte dela.
Não se esqueça de desabilitar a aceleração de hardware, pois PorterDuff.Mode.CLEAR não funciona com aceleração de hardware e, finalmente, chamar
setWillNotDraw(false)
porque substituímos oonDraw
método.fonte
LAYER_TYPE_HARDWARE
paraLAYER_TYPE_SOFTWARE
Seu primeiro requisito, como limpar ou redesenhar a tela inteira - Resposta - use o método canvas.drawColor (color.Black) para limpar a tela com uma cor preta ou o que você especificar.
Seu segundo requisito, como atualizar parte da tela - Resposta - por exemplo, se você deseja manter todas as outras coisas inalteradas na tela, mas em uma pequena área da tela para mostrar um número inteiro (digamos, contador) que aumenta a cada cinco segundos. em seguida, use o método canvas.drawrect para desenhar essa pequena área especificando a parte superior esquerda inferior direita e pintar. em seguida, calcule o valor do contador (usando postdalayed por 5 segundos etc., como Handler.postDelayed (Runnable_Object, 5000);), converta-o em string de texto, calcule a coordenada xey neste pequeno retângulo e use a visualização de texto para exibir a alteração valor do contador.
fonte
Tive que usar um passe de desenho separado para limpar a tela (bloquear, desenhar e desbloquear):
fonte
Apenas ligue
canvas.drawColor (Color.TRANSPARENT)
fonte
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
. Se não me engano, a cor pode ser qualquer coisa (não precisa ser TRANSPARENTE) porquePorterDuff.Mode.CLEAR
apenas limpará o clipe atual (como fazer um furo na tela).