OnMarkerDragStart正在更改标记原始位置

时间:2017-04-10 19:04:18

标签: android google-maps google-maps-markers marker

我正在使用Google Maps v2创建应用程序。每次拍摄或选择照片时,我都会创建一个自定义标记并将其添加到地图中,如下所示:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE_INTENT) {
            Bitmap photo = createBitmap(data);
            Marker m = map.addMarker(photoMarker(lastKnownLatLng, photo));
            markersInMap.add(m);
            Log.d(TAG, "Marker created with " + m.getPosition().toString());
        }
    }
}

然后,如果我想删除标记,我将其拖到垃圾桶图标。如果标记触及垃圾桶图标,它会从地图中移除;工作正常。如果标记没有碰到垃圾桶,它应该返回到原来的位置,但是失败了。当我开始拖动标记时,看起来位置会发生变化,并且会在地图上方略微结束。

@Override
public void onMarkerDragStart(Marker marker) {
    trashImageView.setVisibility(View.VISIBLE);
    draggedMarkerOriginalPosition = marker.getPosition();
    Log.d(TAG, "OnMarkerDragStart with " + draggedMarkerOriginalPosition.toString());
}

这两种方法将nex信息转储到logcat中,因此我开始拖动时标记位置会发生变化,但我不知道为什么并且确实需要防止这种情况发生:< / p>

Marker created with lat/lng: (19.3457139,-99.1522399)
OnMarkerDragStart with lat/lng: (19.35094919370183,-99.15169514715672)

这是我的整个活动代码:

public class MapsActivity extends FragmentActivity implements
        OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        com.google.android.gms.location.LocationListener,
        GoogleMap.OnMarkerDragListener {

    private static final String TAG = "MAP_ACTIVITY";
    private static final int SELECT_PICTURE_INTENT = 1;

    private GoogleMap map; 
    private Polyline gpsTrack; 
    private SupportMapFragment mapFragment; 
    private GoogleApiClient googleApiClient; 
    private Uri imageUri;
    private LatLng lastKnownLatLng;
    private List<Marker> markersInMap = new ArrayList<>();
    private ImageView trashImageView;
    private LatLng draggedMarkerOriginalPosition;

    private enum MapStatus {
        EXPANDED, NORMAL, MINIMIZED
    }

    private MapStatus mapStatus = MapStatus.NORMAL;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        moveMapLocationButton();

        ImageButton down = (ImageButton) findViewById(R.id.down_arrow);
        down.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animateDownMapView();
            }
        });

        ImageButton up = (ImageButton) findViewById(R.id.up_arrow);
        up.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animateUpMapView();
            }
        });

        ImageView camara = (ImageView) findViewById(R.id.camara);
        camara.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startImageChoosingIntent();
            }
        });

        Button finalizar = (Button) findViewById(R.id.btn_finalizar_recorrido);
        finalizar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                gpsTrack.setPoints(new ArrayList<LatLng>());
                for(Marker m : markersInMap) m.remove();
                markersInMap.clear();
            }
        });


        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        trashImageView = (ImageView) findViewById(R.id.trash);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;

        map.addTileOverlay(new TileOverlayOptions().tileProvider(new CustomMapTileProvider(getResources().getAssets())));

        LatLng calymayor = new LatLng(19.345822, -99.152274);
        map.moveCamera(CameraUpdateFactory.newLatLng(calymayor));
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(calymayor, 15));

        PolylineOptions polylineOptions = new PolylineOptions();
        polylineOptions.color(Color.CYAN);
        polylineOptions.width(4);
        gpsTrack = map.addPolyline(polylineOptions);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        map.setMyLocationEnabled(true);

        map.setOnMarkerDragListener(this);

    }


    private void moveMapLocationButton() {
        View locationButton = ((View) mapFragment.getView().findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
        RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) locationButton.getLayoutParams();
        rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
        rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        rlp.setMargins(0, 0, 30, 30);
    }


    private void animateDownMapView() {
        ResizeAnimation a = new ResizeAnimation(mapFragment.getView());
        a.setDuration(250);

        if (mapStatus == MapStatus.NORMAL) {
            mapStatus = MapStatus.EXPANDED;
            a.setParams(mapFragment.getView().getLayoutParams().height, dpToPx(getResources(), pxToDp(getResources().getDisplayMetrics().heightPixels)));
            mapFragment.getView().startAnimation(a);
        } else if (mapStatus == MapStatus.MINIMIZED) {
            mapStatus = MapStatus.NORMAL;
            mapFragment.getView().setLayoutParams(
                    new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.MATCH_PARENT,
                            0,
                            0.3333f
                    )
            );
        }
    }

    private void animateUpMapView() {
        if (mapStatus == MapStatus.NORMAL) {
            mapStatus = MapStatus.MINIMIZED;
            mapFragment.getView().setLayoutParams(
                    new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.MATCH_PARENT,
                            0,
                            0.04f
                    )
            );
        } else if (mapStatus == MapStatus.EXPANDED) {
            mapStatus = MapStatus.NORMAL;
            mapFragment.getView().setLayoutParams(
                    new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.MATCH_PARENT,
                            0,
                            0.3333f
                    )
            );
        }
    }

    private int pxToDp(int px) {
        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        int dp = Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return dp;
    }

    private int dpToPx(Resources res, int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
    }

    @Override
    protected void onStart() {
        googleApiClient.connect();
        super.onStart();
    }

    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopLocationUpdates();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (googleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

    @Override
    public void onLocationChanged(Location location) {
        lastKnownLatLng = new LatLng(location.getLatitude(), location.getLongitude());
        updateTrack();
    }

    protected void startLocationUpdates() {
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setInterval(5000);
        locationRequest.setFastestInterval(1000);
        locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
    }

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(
                googleApiClient, this);
    }

    private void startImageChoosingIntent() {
        Intent pickIntent = new Intent();
        pickIntent.setType("image/*");
        pickIntent.setAction(Intent.ACTION_GET_CONTENT);

        Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String pickTitle = "Seleccionar";

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "New Picture");
        values.put(MediaStore.Images.Media.DESCRIPTION, "From your Camera");
        imageUri = getContentResolver().insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

        Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{takePhotoIntent});

        startActivityForResult(chooserIntent, SELECT_PICTURE_INTENT);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE_INTENT) {
                Bitmap photo = createBitmap(data);
                Marker m = map.addMarker(photoMarker(lastKnownLatLng, photo));
                markersInMap.add(m);
                Log.d(TAG, "Marker created with " + m.getPosition().toString());
            }
        }
    }

    private Bitmap createBitmap(Intent data) {
        boolean isCamera;
        Bitmap photoTaken = null;

        if(data == null) {
            isCamera = true;
        } else {
            String action = data.getAction();
            if(action == null) {
                isCamera = false;
            } else {
                isCamera = action.equals(MediaStore.ACTION_IMAGE_CAPTURE);
            }
        }
        if(!isCamera) {
            imageUri = data.getData();
        }

        try {
            photoTaken = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return photoTaken;
    }

    private MarkerOptions photoMarker(LatLng latlng, Bitmap bitmap) {
        return new MarkerOptions()
                .position(latlng)
                .draggable(true)
                .icon(BitmapDescriptorFactory.fromBitmap(Utils.getMarkerBitmap(getBaseContext(), bitmap)));
    }

    private void updateTrack() {
        List<LatLng> points = gpsTrack.getPoints();
        points.add(lastKnownLatLng);
        gpsTrack.setPoints(points);
    }

    @Override
    public void onMarkerDragStart(Marker marker) {
        trashImageView.setVisibility(View.VISIBLE);
        draggedMarkerOriginalPosition = marker.getPosition();
        Log.d(TAG, "OnMarkerDragStart with " + draggedMarkerOriginalPosition.toString());
    }

    @Override
    public void onMarkerDrag(Marker marker) {
        Point markerScreenPosition = map.getProjection().toScreenLocation(marker.getPosition());
        int size = 0;
        if (overlap(markerScreenPosition, trashImageView)) {
            size = dpToPx(getResources(), 60);
        } else {
            size = dpToPx(getResources(), 40);
        }
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(size, size);
        params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
        trashImageView.setLayoutParams(params);
    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        trashImageView.setVisibility(View.GONE);
        Point markerScreenPosition = map.getProjection().toScreenLocation(marker.getPosition());
        if (overlap(markerScreenPosition, trashImageView)) {
            marker.remove();
        } else {
            marker.setPosition(draggedMarkerOriginalPosition);
            Log.d(TAG, "OnMarkerDragEnd with " + draggedMarkerOriginalPosition.toString());
        }
    }

    private boolean overlap(Point point, ImageView imgview) {
        int[] imgCoords = new int[2];
        imgview.getLocationOnScreen(imgCoords);
        boolean overlapX = point.x < imgCoords[0] + imgview.getWidth() && point.x > imgCoords[0] - imgview.getWidth();
        boolean overlapY = point.y < imgCoords[1] + imgview.getHeight() && point.y > imgCoords[1] - imgview.getWidth();
        return overlapX && overlapY;
    }

}

这些图像显示标记开始的位置以及标记在垃圾桶外的任何位置拖动和释放后的结束位置。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

好的,所以我提出了这个解决方案。我不确定它是否是最好的,但它是否有效。

我改变了:

 private List<Marker> markersInMap = new ArrayList<>();

要:

 private Map<Marker, LatLng> markersInMap = new HashMap<>();

然后当我添加标记时:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE_INTENT) {
            Bitmap photo = createBitmap(data);
            Marker m = map.addMarker(photoMarker(lastKnownLatLng, photo));
            markersInMap.put(m, new LatLng(lastKnownLatLng.latitude, lastKnownLatLng.longitude));
            Log.d(TAG, "Marker created with " + m.getPosition().toString());
        }
    }
}

最后,将其设置回原来的位置:

 @Override
public void onMarkerDragEnd(Marker marker) {
    trashImageView.setVisibility(View.GONE);
    Point markerScreenPosition = map.getProjection().toScreenLocation(marker.getPosition());
    if (overlap(markerScreenPosition, trashImageView)) {
        marker.remove();
        Log.d(TAG, "OnMarkerDragEnd " + "removed");
    } else {
        marker.setPosition(markersInMap.get(marker));
        Log.d(TAG, "OnMarkerDragEnd " + marker.getPosition().toString());
    }
}