2012-05-29 100 views
1

我正在寫一個Android應用程序,我想盡快地圖已經加載zoomIn。 我得到以下錯誤:我應該在哪裏放縮放在我的MapActivity中?

java.lang.IllegalArgumentException: width and height must be > 0 

MapActivity - width and height must be > 0問題提出的問題是zoomIn()方法是在onCreate()方法。 但是,當我將它放入onResume()方法時,我得到同樣的錯誤。

我一直在尋找的小時,我找不到任何關於它在http://developer.android.com或其他地方... 此外,我找不到方法來獲取地圖已加載的時間點。 A 「MapLoadedListener」 或類似的東西...

編輯這裏是我的代碼:

public class AMap extends MapActivity{ 

private final String LOG_TAG = this.getClass().getSimpleName(); 
private Context mContext; 
private Chronometer timer; 
private TextView tvCountdown; 
private RelativeLayout rl; 
private MapView mapView; 
private MapController mapController; 
private List<Overlay> mapOverlays; 
private PlayersOverlay playersOverlay; 
private Drawable drawable;  
private Builder endDialog; 
private ContextThemeWrapper ctw; 
private Handler mHandler = new Handler(); 
private Player player = new Player(); 
private StartTask startTask; 
private EndTask endTask;  
private MyDBAdapter mdba; 
private Cursor playersCursor; 
private UpdateBroadcastReceiver r; 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.map_view); 
    mContext = AMap.this; 

    // set map 
    mapView = (MapView) findViewById(R.id.mapview); 
    mapView.setBuiltInZoomControls(true); 
    mapView.setFocusable(true); 

    // find the relative layout 
    rl = (RelativeLayout) findViewById(R.id.rl);   

    // set the chronometer 
    timer = (Chronometer) findViewById(R.id.tv_timer); 
    timer.setBackgroundColor(Color.DKGRAY); 

    // set the countdown textview 
    tvCountdown = (TextView) findViewById(R.id.tv_countdown); 


    // Open DB connection and get players Cursor 
    mdba = new MyDBAdapter(mContext); 
    mdba.open(); 
    playersCursor = mdba.getGame(); 

    // Get this player's id and location 
    Intent starter = this.getIntent(); 
    player.setId(starter.getIntExtra("id", 0)); 
    player.setLatitude(starter.getDoubleExtra("lat", 0)); 
    player.setLongitude(starter.getDoubleExtra("lon", 0)); 

    // Set this player's location as map's center 
    GeoPoint geoPoint = new GeoPoint((int) (player.getLatitude()*1E6), (int) (player.getLongitude()*1E6));  
    mapController = mapView.getController(); 
    mapController.setCenter(geoPoint);  
    mapController.setZoom(15); 

    Log.d(LOG_TAG, "My playersCursor has "+playersCursor.getCount()+" rows");  
    // drawable is needed but not used 
    drawable = this.getResources().getDrawable(R.drawable.ic_launcher); 

    // set PlayersOverlay (locations and statuses) 
    playersOverlay = new PlayersOverlay(player.getId(), playersCursor, drawable, this); 
    mapOverlays = mapView.getOverlays(); 
    mapOverlays.add(playersOverlay); 

    mHandler.postDelayed(mUpdateTimeTask, 100);   
} 



private Runnable mUpdateTimeTask = new Runnable() { 
    public void run() { 
     int h = mapView.getLayoutParams().height; 
     int w = mapView.getLayoutParams().width; 
     Log.d(LOG_TAG, "w = "+w+" , h = "+h);   
     mHandler.postAtTime(this, SystemClock.elapsedRealtime() + 1000); 
    } 
}; 



@Override 
public void onAttachedToWindow(){ 
     Log.d(LOG_TAG, "Attached to Window"); 
     int h = mapView.getLayoutParams().height; 
     int w = mapView.getLayoutParams().width; 
     Log.d(LOG_TAG, " Attached to window: w = "+w+" , h = "+h); 
     //mapController.zoomInFixing(screenPoint.x, screenPoint.y); 
} 



public void onWindowFocusChanged(boolean hasFocus){ 
     Log.d(LOG_TAG, "Focus changed to: "+hasFocus); 
     int h = mapView.getLayoutParams().height; 
     int w = mapView.getLayoutParams().width; 
     Log.d(LOG_TAG, " Window focus changed: w = "+w+" , h = "+h); 
     //mapController.zoomInFixing(screenPoint.x, screenPoint.y); 
} 



@Override 
protected void onStart(){ 
    super.onStart(); 

    // Create and register the broadcast receiver for messages from service 
    IntentFilter filter = new IntentFilter(AppConstants.iGAME_UPDATE); 
    r = new UpdateBroadcastReceiver(); 
    registerReceiver(r, filter);  


    // Create the dialog for end of game 
    ctw = new ContextThemeWrapper(mContext, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen); 
    endDialog = new AlertDialog.Builder(ctw); 
    endDialog.setMessage("End of Game"); 
    endDialog.setCancelable(false); 
    endDialog.setNeutralButton("OK", new OnClickListener(){ 

     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      Intent highScores = new Intent(AMap.this, HighScores.class); 
      startActivity(highScores);      
      playersCursor.close(); 
      finish();    
     } 

    }); 

} 



@Override 
protected void onStop() {  

    if(!playersCursor.isClosed()) 
     playersCursor.close(); 

    unregisterReceiver(r); 
    mdba.close();  
    super.onStop(); 
} 



@Override 
protected boolean isRouteDisplayed() { 
    return false; 
} 



// Receives signal from NetworkService that DB has been updated 
public class UpdateBroadcastReceiver extends BroadcastReceiver { 

    boolean startSignal, update, endSignal; 

    @Override 
    public void onReceive(Context context, Intent intent) { 

     endSignal = intent.getBooleanExtra("endSignal", false); 
     if(endSignal){ 
      Log.d(LOG_TAG, "Game Update BroadcastReceiver received End Signal"); 
      endTask = new EndTask(); 
      endTask.execute(); 
      return; 
     } 


     update = intent.getBooleanExtra("update", false); 
     if(update){ 
      Log.d(LOG_TAG, "Game Update BroadcastReceiver received game update"); 
      playersCursor.requery(); 
      mapView.invalidate(); 
      return; 
     } 


     startSignal = intent.getBooleanExtra("startSignal", false); 
     if(startSignal){     
      Log.d(LOG_TAG, "Game Update BroadcastReceiver received Start Signal"); 
      startTask = new StartTask(); 
      startTask.execute();   
      return; 
     } 
    } 
} 



class StartTask extends AsyncTask<Void,Integer,Void>{ 

    private final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100); 
    private final long DELAY = 1200; 

    @Override 
    protected Void doInBackground(Void... params) { 

     int i = 3; 
     while(i>=0){ 

      publishProgress(i); 
      try { 
       Thread.sleep(DELAY); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      i--; 
     } 

     return null; 
    } 


    @Override 
    protected void onProgressUpdate(Integer... progress){ 

     tg.startTone(ToneGenerator.TONE_PROP_PROMPT); 
     tvCountdown.setText(""+progress[0]); 
    } 


    @Override 
    protected void onPostExecute(Void result) {   
     rl.removeView(tvCountdown); 
     timer.setBase(SystemClock.elapsedRealtime()); 
     timer.start(); 
     //enable screen touches 
     playersOverlay.setGameStarted(true); 
    }  
} 



class EndTask extends AsyncTask<Void,Void,Void>{ 

    @Override 
    protected void onPreExecute(){ 
     //disable screen touches 
     playersOverlay.setEndOfGame(true); 
     timer.stop(); 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) {   
     try{ 
      endDialog.show(); 
     }catch(Exception e){ 
      Toast.makeText(mContext, "End of game", Toast.LENGTH_LONG); 
      Intent highScores = new Intent(AMap.this, HighScores.class); 
      startActivity(highScores);      
      playersCursor.close(); 
      finish(); 
     } 
     mHandler.removeCallbacks(mUpdateTimeTask); 
    } 
} 

}

最後編輯: 我結束了使用此代碼。我想反覆放大,所以我使用了一個處理程序和一個從onWindowFocusChanged開始每1500ms調用一次的runnable。那裏的MapView對寬度和高度肯定有正值。 OnAttachedToWindow可能不會 工作,因爲它的寬度和高度返回0。

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.map_view); 
    mContext = AMap.this; 

    // set map 
    mapView = (MapView) findViewById(R.id.mapview); 
    mapView.setBuiltInZoomControls(true); 
    mapView.setFocusable(true); 


    // Set this player's location as map's center 
    geoPoint = new GeoPoint((int) (37.974718*1E6), (int) (23.733684*1E6)); 
    projection = mapView.getProjection(); 
    screenPoint = new Point(); 
    projection.toPixels(geoPoint, screenPoint); 
    mapController = mapView.getController(); 
    mapController.setCenter(geoPoint);  
    mapController.setZoom(1); 

    // drawable is needed but not used 
    Timer t = new Timer(); 
    HTask ht = new HTask(); 
    t.schedule(ht, 15000); 

} 


public void onWindowFocusChanged(boolean hasFocus){ 
     Log.d(LOG_TAG, "Focus changed to: "+hasFocus+" ("+i+")");  
     int h = mapView.getHeight(); 
     int w = mapView.getWidth(); 
     Log.d(LOG_TAG, " Window focus changed: w = "+w+" , h = "+h); 
     if(w > 0 && h > 0) {   
      mHandler.postDelayed(mUpdateTimeTask, 100); 
     }   
} 



private Runnable mUpdateTimeTask = new Runnable() { 
    public void run() { 
     int h = mapView.getHeight(); 
     int w = mapView.getWidth(); 
     if(h>0 && w>0){ 
       mapController.zoomIn(); 
       mapController.animateTo(geoPoint); 
       mHandler.postAtTime(this, SystemClock.uptimeMillis() + 1500); 
     } 

    } 
}; 


class HTask extends TimerTask{ 

    @Override 
    public void run() { 
     mHandler.removeCallbacks(mUpdateTimeTask);   
    } 
} 

回答

1

只要覆蓋你的MapActivity的onAttachedToWindow(),放大那裏,一切都應該沒問題。如果的MapView被附加到Window它被調用和therfore具有寬度&高度

編輯,由於代碼更新:

我不是舒爾。這裏有一些事情,我會改變,因爲它們看起來很奇怪,我:

private Runnable mUpdateTimeTask = new Runnable() { 
    public void run() { 
     //WHY you asking LayoutPARAMS for their dimensions? try this: 
     int h = mapView.getHeight(); 
     int w = mapView.getWidth(); 
     Log.d(LOG_TAG, "w = "+w+" , h = "+h);   
     mHandler.postAtTime(this, SystemClock.elapsedRealtime() + 1000); 
    } 
}; 

同樣在這裏:

@Override 
public void onAttachedToWindow(){ 
    Log.d(LOG_TAG, "Attached to Window"); 
    int h = mapView.getHeight(); 
    int w = mapView.getWidth(); 
    Log.d(LOG_TAG, " Attached to window: w = "+w+" , h = "+h); 
    //mapController.zoomInFixing(screenPoint.x, screenPoint.y); 
} 
public void onWindowFocusChanged(boolean hasFocus){ 
    .... 

也,我不知道你叫zoomIn隨時隨地

+0

剛試過我得到了同樣的錯誤。我應該做一些特定的操作來將mapView附加到窗口中嗎? – Johny

+0

真的很確定你不把zoomIn叫做其他地方嗎?它適用於我的三星Nexus S.一個黑客解決方案將設置一個定時器,每隔一秒會觸發,直到MapView具有寬度和高度。 –

+0

嘿!是的,我不會在其他地方撥打zoomIn。我確實設置了一個Timer,並且我始終得到值爲-1的MapView的寬度和高度,即使地圖顯示正確。 – Johny