私のアプリは API レベル 10 (Gingerbread) 以上をサポートしています。アクティビティの 1 つは、新しいバージョンで完全に機能するチャートを描画しますが、レベル 10 エミュレーターを実行すると、間違ったキャンバス ID で View.onDraw への余分な呼び出しが発生し、画面が空白になります。(これは単なるエミュレーターではありません。この問題は、Gingerbread フォンを実行している誰かによって報告されました。)
通常の操作では、onDraw が 2 回呼び出されます。1 回目はキャンバス ID を取得するフレームワークから、2 回目は同じキャンバス ID を渡す invalidate() への呼び出しからです。これら 2 つの呼び出しはレベル 10 エミュレーターで発生しますが、別のキャンバス ID (ビューに属していない) を持つ 3 番目の呼び出しがあり、これにより空白になります。
このアクティビティは、アクション バーを提供するために SherlockActivity から派生したものであり、これが問題の原因であると考えています。
私の活動クラスからの関連コード:
public class Chart extends SherlockActivity implements OnGestureListener, OnDoubleTapListener, OnScaleGestureListener
{
public static boolean mDataSet = false;
private ChartView mView;
private Menu mMenu;
private GestureDetector mDetector;
private ScaleGestureDetector mScaleDetector;
private ActionBar mActionBar;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mDataSet = false;
mActionBar = getSupportActionBar();
mActionBar.setHomeButtonEnabled(true);
mActionBar.setDisplayHomeAsUpEnabled(true);
mActionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
mView = new ChartView(this, mCentreLat, mCentreLong, mRadius);
setContentView(mView);
setTitle("");
Context context = getApplicationContext();
mDetector = new GestureDetector(context, this);
mScaleDetector = new ScaleGestureDetector(context, this);
}
@Override
public void onConfigurationChanged(Configuration config)
{
super.onConfigurationChanged(config);
mDataSet = false;
}
// Menu handling
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
mMenu = menu;
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.chart_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
boolean handled = true;
switch (item.getItemId())
{
case android.R.id.home:
finish();
break;
case R.id.viewOptions:
mDataSet = false;
Intent i = new Intent(getBaseContext(), ChartSettings.class);
startActivity(i);
break;
// Other menu options here...
default:
handled = false;
}
return handled;
}
私のViewクラスからの関連コード:
public class ChartView extends View
{
public ChartView(Context context, float centreLat, float centreLong, float radius)
{
super(context);
mContext = context;
mCentreLat = centreLat;
mCentreLong = centreLong;
mRadius = radius;
}
@Override
protected void onDraw(Canvas canvas)
{
// First time
// (We pick up the canvas id mCanvas from the parameter.)
// (Nothing much else relevant here, except this is where stuff
// gets initialized, then in setDataInfo(), mDataSet is set true
// and invalidate() is called at the end.)
if (!Chart.mDataSet)
{
setBackgroundColor(Color.WHITE);
mCanvas = canvas;
initPaint();
setDataInfo(); // invalidate() called at end
}
else
{
// Second call to onDraw() with same canvas id comes here,
// then an unwanted third call with a different canvas id, only
// with the Level 10 (Gingerbread) emulator.
// This is where the various lines and shapes are plotted
// on the canvas (mCanvas)
plotLinesAndShapes();
}
Gingerbread エミュレーター (または電話) で 3 番目の呼び出しが発生する理由を誰か説明できますか? その効果は、画面がブランク (完全に白) になることです。
この関数に到達するまでには手遅れであり、呼び出しを無視することはできません。呼び出しスタックが巻き戻されると、画面が空白になります。
回避策があります。ユーザーがメニューから表示オプションを選択し、すぐにチャートに戻ると、チャートは再描画され、それ以降は正常に動作します。