【问题标题】:ItemizedOverlay Rotate marker and crashItemizedOverlay 旋转标记和崩溃
【发布时间】:2011-02-01 20:53:04
【问题描述】:

有点奇怪的帖子,因为这是我之前发布的内容,以为已经解决但没有!

我有一种情况,我需要为每个标记使用自定义 Drawable,我需要的效果是将标记旋转一定的度数,并且可能完全走错了路。

作为开始,我使用了优秀的知识共享,因为它确实有效,并且只有在我添加后才会中断!

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

上一篇文章和代码在这里

Android Maps NullPointerException ItemizedOverlay

如果有人能推荐一种更好、更稳定的方法来获得旋转的 Drawable 并让我走上正确的道路,那就太好了。

从我的代码中可以看出,我没有在叠加层中设置 Drawable,而是在另一个对象中执行此操作,并怀疑这就是它崩溃的原因!

目前我通过这样做来设置我的 Drawable...

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;

    }

然后我用这个来创建它...

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();

还有我的 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();
        }



    }

【问题讨论】:

    标签: android drawable itemizedoverlay


    【解决方案1】:

    似乎很自然的 API 选择 RotateDrawable 是脑死的,因为您只能从膨胀的布局中使用它。我已将问题中引用的 Mark Murphy 的代码改编为以下活动,该活动显示纽约标记旋转,使用替代 RotateDrawable 以更灵活的方式包装包含的可绘制对象:

    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);
            }
        }
    
    }
    

    有任何问题,欢迎提问。 :-)

    【讨论】:

    • 鲁本看起来很棒,而且我认为确实有一些里程!我想每个标记具有不同角度的最佳方法是将一个额外的参数传递给 this.marker=new RotateDrawable(marker); ??
    • 哦,没错。我只是让它们在 RotateDrawable.rotate() 中每帧旋转 5 度以显示它有效……您不必保留该功能。顺便说一句,您还可以丢失未使用的 mPivotX 和 mPivotY 字段......它们不是必需的。
    • 好的,谢谢,我想我也去掉了 run() 因为我不需要为旋转设置动画,这将是项目的一次旋转,根本不需要动画。
    • 绝对。失去 Handler 和 runnable ......这一切只是为了通过让它们旋转来演示该方法。
    • @LeeArmstrong 你最近怎么样?
    【解决方案2】:

    这样的话李建议你试试AnimationDrawable

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

    编辑: 与此同时,另一个有用的帖子“moving-icons-on-a-android-mapview”建议在 onDraw() 中使用计时器线程。

    希望对您有所帮助。

    【讨论】:

    • 但那是为了给它们设置动画?我想将每一个旋转不同的度数?
    • Lee 可以考虑使用 RotateDrawable 进行旋转,但我从未以编程方式设置其角度。
    • 是的,我通过预旋转使用更轻量级的方法使其工作,因此操作系统不需要。它很少崩溃,但足以惹恼用户,所以它一定很小。你的建议我已经尝试过了,它锤击了 CPU。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多