2011-01-29 2 views
0

Un peu d'un post étrange car c'est quelque chose que j'ai posté avant, pensé que c'était résolu mais pas!ItemizedOverlay Rotation du marqueur et crash

J'ai une situation où j'ai besoin d'utiliser un Drawable personnalisé pour chaque marqueur, l'effet dont j'ai besoin est de faire tourner le marqueur d'un certain nombre de degrés et je vais probablement le faire complètement à tort.

Pour commencer, j'utilise l'excellent Creative Commons car cela fonctionne et ne se casse qu'après mes ajouts!

https://github.com/commonsguy/cw-advandroid/tree/master/Maps/NooYawkAsync

Le post précédent et le code est ici

Android Maps NullPointerException ItemizedOverlay

Si quelqu'un peut recommander une meilleure et plus stable pour obtenir une rotation Drawable et me mettre sur la bonne voie qui serait sois super.

Comme vous pouvez le voir dans mon code, je ne mets pas le Drawable dans la superposition et je le fais dehors à l'intérieur d'un autre objet et je suspecte que c'est la raison pour laquelle il se casse!

Au moment où je mets mon Drawable en faisant cela ...

public Drawable getRotatedIcon(String string) { 
     Drawable marker = null; 
     Double tempHeading = Double.valueOf(string); 
     long intHeading = Math.round(tempHeading/10); 

     int resID = getResources().getIdentifier(
       "icon_rotate_" + Long.toString(intHeading), "drawable", 
       "com.test.testapp"); 

     marker = getResources().getDrawable(resID); 
     marker.setBounds(0, 0, marker.getIntrinsicWidth(),marker.getIntrinsicHeight()); 
     return marker; 

    } 

Et puis pour créer tout ce que j'utilise cette ...

if (sites != null){ 
      sites.clearItems(); 
     }else{ 
      sites = new SitesOverlay(); 
     } 

     for (int i = 0; i < getMainOverlayArray().size(); i++) { 
      tempOver = getMainOverlayArray().get(i); 
      tempOver.setMarker(getRotatedIcon(tempOver.getcourse())); 
      if (tempOver != null){ 
       sites.addItem(tempOver); 
      } 
     } 

     sites.finishedLoading(); 

Et ma classe SitesOverlay ...

 private class SitesOverlay extends ItemizedOverlay<pfOverlayItem> { 
     private List<pfOverlayItem> items = new ArrayList<pfOverlayItem>(); 

     private PopupPanel panel=new PopupPanel(R.layout.popup); 
     private MapLocation selectedMapLocation; 
     private static final int CIRCLERADIUS = 2; 
     private ArrayList<pfOverlayItem> mOverlays = new ArrayList<pfOverlayItem>(); 



     public SitesOverlay() { 

      super(null); 
      populate(); 

     } 



public void finishedLoading(){ 

    populate(); 

} 

     @Override 
     protected pfOverlayItem createItem(int i) { 
      return (items.get(i)); 

     } 

     public void addItem(OverlayItem overlay) { 
      overlay.setMarker(boundCenter(overlay.getMarker(0))); 
      items.add((pfOverlayItem) overlay); 
     } 

     public void clearItems(){ 
      runOnUiThread(new Runnable() { 
       public void run() { 
        items.clear(); 
        myMapView.invalidate(); 
       } 
      }); 


     } 

     public void clear() { 
      mOverlays.clear(); 
      myMapView.removeAllViews(); 

      setLastFocusedIndex(-1); 
      populate(); 
     } 

     @Override 
     public void draw(Canvas canvas, MapView mapView, boolean shadow) { 
      super.draw(canvas, mapView, false); 

      try { 


      if (getMainOverlayArray().size() != 0){ 

      pfOverlayItem tempOver = null; 
      for (int i = 0; i < getMainOverlayArray().size(); i++) { 

       tempOver = getMainOverlayArray().get(i); 

      boolean isMatch = false; 

      //Log.i("Selected Name",selectedName); 

      if (tempOver.getTitle().equals(selectedName)) 
      { 
       isMatch = true; 
      } 

      if (isMatch){ 

      Projection projection = mapView.getProjection(); 
      Point point = new Point(); 
      projection.toPixels(tempOver.getPoint(), point); 

      Paint background = new Paint(); 
      background.setColor(Color.WHITE); 
      background.setAlpha(150); 
      RectF rect = new RectF(); 
      rect.set(point.x - 50, point.y +15, 
        point.x + 90, point.y + 50); 
      canvas.drawRoundRect(rect, 5, 5, background); 


      Paint text = new Paint(); 
      text.setAntiAlias(true); 
      text.setColor(Color.BLUE); 
      text.setTextSize(14); 
      text.setTypeface(Typeface.MONOSPACE); 

      canvas.drawText(tempOver.getTitle() + " " + tempOver.getcallsign(), point.x -50 , point.y + 30, text); 
      canvas.drawText(tempOver.getdestination() + " " + tempOver.getdraft(), point.x -50 , point.y + 45, text); 
      } 
      } 
      } 
      }catch (Exception e){ 
       Log.e("Error", "Problem drawing view", e); 
       e.printStackTrace(); 

      } 
     } 

     @Override 
     protected boolean onTap(int i) { 

      pfOverlayItem item = getItem(i); 

      if (selectedName.equals(item.getTitle())){ 

       try{  
       Intent myIntent = new Intent(TestApp.this, DetailActivity.class); 
       myIntent.putExtra("int", i); 
       myIntent.putExtra("string", selectedName); 
       PlaneFinderMain.this.startActivity(myIntent); 
       }catch (Exception e){ 
        Log.e("Error", "Cannot launch", e); 
       } 
      } 

      currentadshex = item.getmmsi(); 
      new GetRouteTask(item.getmmsi()).execute(); 

      selectedItem = i; 
      selectedName = item.getTitle(); 
      selectedPlanePoint = item.getPoint(); 

      GeoPoint geo=item.getPoint(); 
      Point pt=myMapView.getProjection().toPixels(geo, null); 

      View view=panel.getView(); 

      ((TextView)view.findViewById(R.id.reg)).setText(item.getTitle()); 
      ((TextView)view.findViewById(R.id.callsign)).setText(item.getcallsign()); 
      ((TextView)view.findViewById(R.id.dest)).setText(item.getdestination()); 
      ((TextView)view.findViewById(R.id.draft)).setText(item.getdraft()); 

      return (true); 
     } 

     @Override 
     public boolean onTouchEvent(MotionEvent event, MapView mapView) { 

      if (event.getAction() == MotionEvent.ACTION_DOWN){ 

       if (selectedPlanePoint != null){ 
        Projection projection = mapView.getProjection(); 
        Point point = new Point(); 
        projection.toPixels(selectedPlanePoint, point); 

        Point pointHit = new Point(); 
        pointHit.x=(int)event.getX(); 
        pointHit.y=(int)event.getY(); 

        if ((point.x - pointHit.x) >-100 && (point.x - pointHit.x) <70 && (point.y - pointHit.y) < -25 && (point.y - pointHit.y) > -95){ 

          try{  
           Intent myIntent = new Intent(TestApp.this, DetailActivity.class); 

            myIntent.putExtra("int", selectedItem); 
            myIntent.putExtra("string", selectedName); 
            TestApp.this.startActivity(myIntent); 

           }catch (Exception e){ 
            Log.e("Error", "Cannot launch", e); 
           } 

        }else{ 

        } 


       } 


      } 



      return false; 


     } 



     @Override 
     public int size() { 
      return (items.size()); 
     } 

     public void addOverlay(OverlayItem o){ 
      setLastFocusedIndex(-1); 
      populate(); 
     } 



    } 

Répondre

6

Il semble que le choix de l'API naturel, RotateDrawable, est braindead en ce sens que vous ne pouvez l'utiliser qu'à partir d'une disposition gonflée. J'ai adapté le code de Mark Murphy fait référence dans la question dans l'activité ci-dessous qui montre la rotation des marqueurs de New York, en utilisant une alternative RotateDrawable qui enveloppe une drawable contenue d'une manière plus souple:

import android.graphics.Canvas; 
import android.graphics.ColorFilter; 
import android.graphics.Rect; 
import android.graphics.drawable.Drawable; 
import android.os.Bundle; 
import android.os.Handler; 
import com.google.android.maps.GeoPoint; 
import com.google.android.maps.ItemizedOverlay; 
import com.google.android.maps.MapActivity; 
import com.google.android.maps.MapView; 
import com.google.android.maps.MyLocationOverlay; 
import com.google.android.maps.OverlayItem; 
import java.util.ArrayList; 
import java.util.List; 

public class NooYawk extends MapActivity { 
    private MapView map=null; 
    private MyLocationOverlay me=null; 
    private SitesOverlay sites=null; 
    Handler handler = new Handler(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     map=(MapView)findViewById(R.id.map); 

     map.getController().setCenter(getPoint(40.76793169992044, -73.98180484771729)); 
     map.getController().setZoom(17); 
     map.setBuiltInZoomControls(true); 

     me=new MyLocationOverlay(this, map); 
     map.getOverlays().add(me); 

     sites=new SitesOverlay(); 
     map.getOverlays().add(sites); 
     map.invalidate();   
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     me.enableCompass(); 
    }  

    @Override 
    public void onPause() { 
     super.onPause(); 

     me.disableCompass(); 
    }  

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

    private GeoPoint getPoint(double lat, double lon) { 
     return(new GeoPoint((int)(lat*1000000.0), (int)(lon*1000000.0))); 
    } 

    private class SitesOverlay extends ItemizedOverlay<CustomItem> { 
     private List<CustomItem> items=new ArrayList<CustomItem>(); 

     public SitesOverlay() { 
      super(null); 
      items.add(new CustomItem(getPoint(40.748963847316034, -73.96807193756104), 
        "UN", "United Nations",getMarker(R.drawable.blue_full_marker))); 
      items.add(new CustomItem(getPoint(40.76866299974387, -73.98268461227417), 
        "Lincoln Center", "Home of Jazz at Lincoln Center", getMarker(R.drawable.orange_full_marker))); 
      items.add(new CustomItem(getPoint(40.765136435316755, -73.97989511489868), 
        "Carnegie Hall", "Where you go with practice, practice, practice", getMarker(R.drawable.green_full_marker))); 
      items.add(new CustomItem(getPoint(40.70686417491799,-74.01572942733765), "The Downtown Club", 
        "Original home of the Heisman Trophy", getMarker(R.drawable.purple_full_marker))); 
      populate(); 
     } 

     @Override 
     protected CustomItem createItem(int i) { 
      return(items.get(i)); 
     } 

     @Override 
     public void draw(Canvas canvas, MapView mapView, boolean shadow) { 
      super.draw(canvas, mapView, shadow); 
      handler.post(new Runnable() { 
       @Override 
       public void run() { 
        for (CustomItem item : items) { 
         item.marker.rotate(); 
        } 
        map.invalidate(); 
       }    
      }); 
     } 

     @Override 
     public int size() { 
      return(items.size()); 
     } 


     private Drawable getMarker(int resource) { 
      Drawable marker=getResources().getDrawable(resource); 

      marker.setBounds(0, 0, marker.getIntrinsicWidth(), 
               marker.getIntrinsicHeight()); 
      boundCenter(marker); 

      return(marker); 
     } 
    } 

    // 
    // A RotateDrawable that isn't braindead. 
    // 
    private class RotateDrawable extends Drawable { 
     private Drawable mDrawable; 
     private float mPivotX = 0.5f; 
     private float mPivotY = 0.5f; 
     private float mCurrentDegrees = 0f; 
     public RotateDrawable(Drawable drawable) { 
      this.mDrawable = drawable; 
     } 
     public void rotate() { 
      mCurrentDegrees+=5; 
      if (mCurrentDegrees>=360) { 
       mCurrentDegrees-=360; 
      } 
     } 
     public void draw(Canvas canvas) { 
      int saveCount = canvas.save(); 
      Rect bounds = mDrawable.getBounds(); 
      int w = bounds.right - bounds.left; 
      int h = bounds.bottom - bounds.top; 
      float px = w * mPivotX; 
      float py = h * mPivotY; 
      canvas.rotate(mCurrentDegrees, 0, 0); 
      mDrawable.draw(canvas); 
      canvas.restoreToCount(saveCount); 
     } 

     @Override public int getOpacity() { 
      return mDrawable.getOpacity(); 
     } 

     @Override 
     public void setAlpha(int arg0) { 
      mDrawable.setAlpha(arg0); 
     } 

     @Override 
     public void setColorFilter(ColorFilter arg0) { 
      mDrawable.setColorFilter(arg0); 
     } 
    } 

    class CustomItem extends OverlayItem { 
     public RotateDrawable marker=null; 
     CustomItem(GeoPoint pt, String name, String snippet, Drawable marker) { 
      super(pt, name, snippet); 
      this.marker=new RotateDrawable(marker); 
     } 


     @Override 
     public Drawable getMarker(int stateBitset) { 
      Drawable result=(marker); 

      setState(result, stateBitset); 

      return(result); 
     } 
    } 

} 

Pour toute question, vous pouvez demander. :-)

+0

Cela semble très bien Reuben et un je pense que cela a du kilométrage en effet! Je suppose que le meilleur moyen pour chaque marqueur d'avoir un angle différent est de passer un paramètre supplémentaire dans this.marker = new RotateDrawable (marqueur); ?? –

+1

Oh, exactement. Je les ai simplement fait pivoter de 5 degrés chaque image dans RotateDrawable.rotate() pour montrer que ça a marché ... vous n'avez pas besoin de garder cette fonction. Vous pouvez également perdre les champs mPivotX et mPivotY inutilisés btw ... ils ne sont pas nécessaires. –

+0

OK merci, je suppose que je supprime aussi le run() car je n'ai pas besoin d'animer le roatation, ce sera une rotation unique de l'objet, aucune animation nécessaire du tout. –

0

Dans ce cas Lee, je vous suggère de donner un essai à AnimationDrawable

AnimationDrawable frameAnimation = 
(AnimationDrawable) getResources().getDrawable(R.drawable.spin_animationm); 

EDIT: En attendant est venu un autre poste utile « moving-icons-on-a-android-mapview » qui suggère l'aide d'un fil de minuterie dans le onDraw().

Espérons que ça aide.

+0

Mais c'est pour les animer? Je veux faire pivoter chacun d'un nombre différent de degrés? –

+0

Lee pour la rotation, vous pouvez envisager d'utiliser RotateDrawable mais je n'ai jamais défini ses angles par programmation. – 100rabh

+0

Oui bien je l'ai travailler en utilisant une méthode plus légère par pré-rotation afin que le système d'exploitation n'a pas besoin. Il se bloque rarement mais assez pour ennuyer les utilisateurs, donc il doit être quelque chose de petit. Ce que vous suggérez j'ai essayé et ça martèle le CPU. –

Questions connexes