画面がタッチされた場所にpngグラフィックを描画する簡単なアプリケーションを作成しようとしました。私が抱えている問題は、追加したグラフィックの他のすべてのインスタンスのみが実際にレンダリングされることです。新しいインスタンスを追加するたびに、パターンが交互になります。私は常にレンダリングされたグラフィックスの 50% しか取得しません。
HTC Hero で Android レベル 3 を使用しています。
問題をもう少し説明すると、これはサーフェス ホルダー コールバックから呼び出している描画メソッドです。
public void surfaceCreated(SurfaceHolder holder) {
drawOK = true;
drawIcon(100.0f, 100.0f);//line-1
drawIcon(50.0f, 100.0f);//line-2
drawIcon(100.0f, 50.0f);//line-3
drawIcon(50.0f, 50.0f);//line-4
//drawIcon(200.0f, 200.0f);//line-5
//drawIcon(100.0f, 200.0f);//line-6
}
5 行目と 6 行目をコメント アウトすると (図のように)、2 行目と 4 行目だけが表示されます。5 行目を追加すると、1、3、5 行目が表示されます。最後に 6 行目を追加すると、2、4、6 行目が表示されます。
これはなぜでしょうか?
アプリケーションの残りの部分をより詳細に説明します。次のレイアウト xml があります。
<SurfaceView android:id="@+id/SurfaceView01" android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"/>
つまり、png グラフィックを描画する単一のサーフェス ビューがあります。
私のアクティビティは SurfaceHolder.Callback を実装し、次のように初期化します。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
surfaceView = (SurfaceView) findViewById(R.id.SurfaceView01);
// register our interest in hearing about changes to our surface
holder = surfaceView.getHolder();
holder.addCallback(this);
}
つまり、呼び出しをチェーンし、R クラスを使用してコンテンツ ビューを設定します。次に、サーフェス ビューへの参照を取得し、アクティビティをサーフェス ホルダー コールバックとして登録します。
アイコンを画面に描画するメソッドがあります。これです:
private void drawIcon(float x, float y) {
if (!drawOK) return;
Canvas canvas = holder.lockCanvas();
// getting instance each time in case problem is related to reusing obj
mFiringImage = getResources().getDrawable(R.drawable.icon);
//so i can see overlapping icons, to rule out clipping issues
mFiringImage.setAlpha(125);
// This mutate call is incase the bounds are shared state, which i doubt
mFiringImage.mutate().setBounds(
(int)x-mFiringImage.getIntrinsicWidth()/2,
(int)y-mFiringImage.getIntrinsicHeight()/2,
(int)x+mFiringImage.getIntrinsicWidth()/2,
(int)y+mFiringImage.getIntrinsicHeight()/2
);
mFiringImage.draw(canvas);
holder.unlockCanvasAndPost(canvas);
}
つまり、キャンバスをロックし、ドローアブル png リソースを取得し、境界を設定し (念のため mutate を使用)、ドローアブルにキャンバス上に自分自身を描画するように要求します。サーフェスが作成されていない限り、描画しないことに注意してください。
私はここで本当に困惑しています。
すべての助けに感謝します。
ps 完全なリストは次のとおりです。
package com.mypackage;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class Toucher extends Activity implements SurfaceHolder.Callback {
private Drawable mFiringImage;
private SurfaceView surfaceView;
private boolean drawOK;
private SurfaceHolder holder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
surfaceView = (SurfaceView) findViewById(R.id.SurfaceView01);
// register our interest in hearing about changes to our surface
holder = surfaceView.getHolder();
holder.addCallback(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
Log.e(getClass().getSimpleName(), "=========================");
Log.e(getClass().getSimpleName(), "Action="+event.getAction());
Log.e(getClass().getSimpleName(), "History Size="+event.getHistorySize());
Log.e(getClass().getSimpleName(), "Pressure="+event.getPressure());
Log.e(getClass().getSimpleName(), "Raw X="+event.getRawX());
Log.e(getClass().getSimpleName(), "Raw Y="+event.getRawY());
Log.e(getClass().getSimpleName(), "X="+x);
Log.e(getClass().getSimpleName(), "Y="+y);
Log.e(getClass().getSimpleName(), "Precision X="+event.getXPrecision());
Log.e(getClass().getSimpleName(), "Precision Y="+event.getYPrecision());
Log.e(getClass().getSimpleName(), "Size="+event.getSize());
Log.e(getClass().getSimpleName(), "=========================");
drawIcon(x, y);
return super.onTouchEvent(event);
}
private void drawIcon(float x, float y) {
if (!drawOK) return;
Canvas canvas = holder.lockCanvas();
mFiringImage = getResources().getDrawable(R.drawable.icon);
mFiringImage.setAlpha(125);
mFiringImage.mutate().setBounds(
(int)x-mFiringImage.getIntrinsicWidth()/2,
(int)y-mFiringImage.getIntrinsicHeight()/2,
(int)x+mFiringImage.getIntrinsicWidth()/2,
(int)y+mFiringImage.getIntrinsicHeight()/2
);
mFiringImage.draw(canvas);
holder.unlockCanvasAndPost(canvas);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawOK = true;
drawIcon(100.0f, 100.0f);//1
drawIcon(50.0f, 100.0f);//2
drawIcon(100.0f, 50.0f);//3
drawIcon(50.0f, 50.0f);//4
//drawIcon(200.0f, 200.0f);//5
//drawIcon(100.0f, 200.0f);//6
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) drawOK = false;
}
}