2017-04-10 59 views
1

我正在使用Google Maps v2創建應用程序。每次我拍攝或選擇一張圖片,我創建一個自定義標記,並將其添加到地圖是這樣的:OnMarkerDragStart正在更改標記的原始位置

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

這兩種方法傾倒在logcat中的NEX信息,所以很明顯的標記位置,當我開始拖移的變化,但我不知道爲什麼,真正需要防止這種情況的發生:

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

} 

而且這些圖像顯示在標記開始和在哪裏結束後,我拖,隨時隨地釋放標記的外TRA sh可以。

enter image description here

enter image description here

回答

1

OK,所以我想出了這個解決方案。我不確定這是否是最好的,但它的工作。

我改變:

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()); 
    } 
} 
+0

此變通辦法是我找到的唯一解決方案,用於解決同一問題。您能否將您的答案標記爲已接受,這樣可以幫助其他人? – antonio