如何在MapView上进行3DTransition?

时间:2012-04-20 08:52:10

标签: android android-layout

在我的应用程序中,我有一个事件列表及其描述,现在我想在MapView上显示事件位置。所以我使用了Android api演示(ApiDemo> Views> Animation> 3D Transition)中描述的3dTransition。 3D转换工作正常,但问题是在转换时MapView显示时,它翻转180度(参见下面的屏幕截图)。如何在不进一步旋转地图的情况下正常显示地图?我使用Rotate3DAnimation.java以下是我的代码:请帮忙...

public class EventsActivity extends MapActivity implements DialogInterface.OnDismissListener {

    private EventsItemModel     eventsItemModel;
    private Integer             eventItemId;
    private Integer             eventCategoryId;
    private static MapOverlay   mapOverlay;
    Drawable                    marker;
    Context                     context;
    private static String       MY_LOCATION = "My Location";
    private ViewGroup           mContainer;
    private ImageView           mImageView;
    private MapView             mMapView;
    private static boolean      isFlipped   = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.event_item_detail);
        mContainer = (ViewGroup) findViewById(R.id.event_container);
        // Since we are caching large views, we want to keep their cache
        // between each animation
        mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
        mMapView = (MapView) findViewById(R.id.mapview);
        mImageView = (ImageView) findViewById(R.id.mapPreview);

        mImageView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                isFlipped = true;
                applyRotation(1, 0, 90);
            }
        });

        try {
            eventCategoryId = getIntent().getIntExtra(AppConstants.EVENT_CATEGORY, 0);
            eventItemId = getIntent().getIntExtra(AppConstants.EVENT_ID, 0);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void onResume() {
        super.onResume();
        WeakReference<EventsActivity> weakContext = new WeakReference<EventsActivity>(this);
        EventsAsyncTask task = new EventsAsyncTask(weakContext);
        task.execute(eventItemId, eventCategoryId);
    }

    public void onTaskComplete(EventsItemModel eiModel) {
        this.eventsItemModel = eiModel;
        TextView calTitle = (TextView) findViewById(R.id.news_title);
        TextView eventTitle = (TextView) findViewById(R.id.cal_event_title);
        TextView calDate = (TextView) findViewById(R.id.cal_date);
        TextView calTime = (TextView) findViewById(R.id.cal_time);
        TextView calAddress = (TextView) findViewById(R.id.cal_address);
        TextView calDescription = (TextView) findViewById(R.id.cal_description);

        try {
            calTitle.setText(eventsItemModel.getEventsCategory().getTitle());
            calTitle.setVisibility(View.VISIBLE);
            eventTitle.setText(eventsItemModel.getEventTitle());
            calDate.setText(eventsItemModel.getFormattedDateRange());
            // TODO:Format start and end time
            calTime.setText("Time: " + eventsItemModel.getFormattedStartTime() + " - " + eventsItemModel.getFormattedEndTime());
            calAddress.setText(eventsItemModel.getAddress());
            calDescription.setText(eventsItemModel.getDescription());
            System.out.println("<<<<<<<<< EventsActivity >>>>>>>>> isRead? " + eventsItemModel.getReadUnread());
            eventsItemModel.setReadUnread(true);
            System.out.println("<<<<<<<<<< EventsActivity >>>>>>>>>> isRead? " + eventsItemModel.getReadUnread());
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        mMapView.setBuiltInZoomControls(true);
        setMapParameters();
        createItemizedOverlay();
        setLocationMarker(createMarker(R.drawable.location_marker));
        showLocationPointOnMap();
    }

    @Override
    public void onDismiss(DialogInterface dialog) {

    }

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

    public void createItemizedOverlay() {
        mapOverlay = new MapOverlay(this);
    }

    public void setLocationMarker(Drawable marker) {
        mapOverlay.setLocationMarker(marker);
    }

    public void showLocationPointOnMap() {

        GeoPoint geoPoint = new GeoPoint(0, 0);
        if (eventsItemModel != null && eventsItemModel.getLatitude() != null && eventsItemModel.getLatitude().length() > 0 && eventsItemModel.getLongitude() != null
                && eventsItemModel.getLongitude().length() > 0) {
            try {
                geoPoint = new GeoPoint((int) (Double.parseDouble(eventsItemModel.getLatitude()) * 1E6), (int) (Double.parseDouble(eventsItemModel.getLongitude()) * 1E6));
            }
            catch (NumberFormatException e) {
                e.printStackTrace();
            }
            OverlayItem item = new OverlayItem(geoPoint, MY_LOCATION, null);
            mapOverlay.addItem(item);
            mMapView.getOverlays().add(mapOverlay);

            // move to location
            mMapView.getController().animateTo(geoPoint);
            // redraw map
            mMapView.postInvalidate();
        }

    }

    public void setStreetView(boolean isStreetView) {
        mMapView.setStreetView(isStreetView);
    }

    public void setSatelliteView(boolean isSatelliteView) {
        mMapView.setSatellite(isSatelliteView);
    }

    public void setZoom(int zoomLevel) {
        mMapView.getController().setZoom(zoomLevel);
    }

    private void setMapParameters() {
        // setStreetView(true);
        // setSatelliteView(false);
        setZoom(17);
    }

    private Drawable createMarker(int iconID) {
        // Initialize icon
        Drawable icon = getResources().getDrawable(iconID);
        icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
        return icon;
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
    }

    /**
     * Setup a new 3D rotation on the container view.
     * 
     * @param position
     *            the item that was clicked to show a picture, or -1 to show the list
     * @param start
     *            the start angle at which the rotation must begin
     * @param end
     *            the end angle of the rotation
     */
    private void applyRotation(int position, float start, float end) {
        // Find the center of the container
        final float centerX = mContainer.getWidth() / 2.0f;
        final float centerY = mContainer.getHeight() / 2.0f;

        // Create a new 3D rotation with the supplied parameter
        // The animation listener is used to trigger the next animation
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
        rotation.setDuration(500);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        rotation.setAnimationListener(new DisplayNextView(position));

        mContainer.startAnimation(rotation);
    }

    /**
     * This class listens for the end of the first half of the animation. It then posts a new action that effectively swaps the views when the container is rotated 90 degrees and thus invisible.
     */
    private final class DisplayNextView implements Animation.AnimationListener {
        private final int   mPosition;

        private DisplayNextView(int position) {
            mPosition = position;
        }

        public void onAnimationStart(Animation animation) {
        }

        public void onAnimationEnd(Animation animation) {
            mContainer.post(new SwapViews(mPosition));
        }

        public void onAnimationRepeat(Animation animation) {
            // Do nothing!!
        }
    }

    /**
     * This class is responsible for swapping the views and start the second half of the animation.
     */
    private final class SwapViews implements Runnable {
        private final int   mPosition;

        public SwapViews(int position) {
            mPosition = position;
        }

        public void run() {
            final float centerX = mContainer.getWidth() / 2.0f;
            final float centerY = mContainer.getHeight() / 2.0f;
            Rotate3dAnimation rotation;

            if (mPosition > -1) {
                mImageView.setVisibility(View.GONE);
                mMapView.setVisibility(View.VISIBLE);
                mMapView.requestFocus();

                rotation = new Rotate3dAnimation(90, 180, centerX, centerY, 310.0f, false);
                rotation.reset();
            }
            else {
                mMapView.setVisibility(View.GONE);
                mImageView.setVisibility(View.VISIBLE);
                mImageView.requestFocus();

                rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false);
            }

            rotation.setDuration(100);
            rotation.setFillAfter(true);
            rotation.setInterpolator(new DecelerateInterpolator());

            mContainer.startAnimation(rotation);
        }
    }

    @Override
    public void onBackPressed() {
        if (isFlipped) {
            applyRotation(-1, 180, 90);
            isFlipped = false;
        }
        else {
            super.onBackPressed();
        }
    }

}

enter image description here

1 个答案:

答案 0 :(得分:1)

我发现的解决方案如下,任何其他优雅的解决方案都受到高度赞赏:

按如下方式更改了旋转度:

if (mPosition > -1) {
                mImageView.setVisibility(View.GONE);
                mMapView.setVisibility(View.VISIBLE);
                mMapView.requestFocus();

                rotation = new Rotate3dAnimation(-90, 0, centerX, centerY, 310.0f, false);
                rotation.reset();
            }

@Override
    public void onBackPressed() {
        if (isFlipped) {
            applyRotation(-1, 0, -90);
            isFlipped = false;
        }
        else {
            super.onBackPressed();
        }
    }

就是这样! :)