1

我正在编写一个 Android 应用程序,我想在地图加载后立即放大。我收到以下错误:

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

这个MapActivity - width and height must be > 0 question表明问题是 zoomIn() 方法在 onCreate() 方法中。但是当我把它放在 onResume() 方法中时,我得到了同样的错误。

我已经搜索了几个小时,但在http://developer.android.com或其他任何地方都找不到任何关于它的信息……我也找不到获取地图加载时间点的方法. “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 开始每 1500 毫秒调用一次。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);          
    }   
}
4

1 回答 1

1

只需覆盖onAttachedToWindow()您的 MapActivity,放大那里,一切都应该没问题。如果 MapView 附加到 Window 并且因此具有宽度和高度,它会被调用

由于代码更新而编辑:

我不舒尔。这里有一些东西,我会改变,因为它们对我来说看起来很奇怪:

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

于 2012-05-29T15:53:57.243 回答