【问题标题】:Android: Drag map while keeping marker at the centerAndroid:拖动地图,同时将标记保持在中心
【发布时间】:2017-02-27 23:51:24
【问题描述】:

我目前正在 MapActivity 中获取设备的当前位置 (lat,lng)。现在,我想让用户移动地图,同时将标记保持在中心。这意味着无论何时移动地图,都会更新当前位置。 (对吧?)

我关注了How to move a map under a marker?How to attach a flexible marker on map something like Uber and Lyft?,但我的概念不清楚。

Activity_map.xml(这里我添加了ImageView)

<RelativeLayout 
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

<fragment
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.MapFragment"
    />

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:src="@drawable/gps"
    />

 </RelativeLayout>

我的 MapActivity 如下:

 public class MapActivity extends FragmentActivity implements      OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener,GoogleMap.OnInfoWindowClickListener{

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);
   // int x =_st.jsonArray.length();
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkLocationPermission();
    }

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    fragmentOnMap = (FragmentOnMap)getFragmentManager().findFragmentById(R.id.fragment_bottom);
    getFragmentManager().beginTransaction().hide(fragmentOnMap);

}

@Override
public void onMapReady(GoogleMap googleMap) {


    //Get Last Known Location and convert into Current Longitute and Latitude
    final LocationManager mlocManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    final Location currentGeoLocation = mlocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    double currentLat = currentGeoLocation.getLatitude();
   double currentLon = currentGeoLocation.getLongitude();

    LatLng currentLatLng = new LatLng(currentLat,currentLon);
    //Toast.makeText(this,"Cur Lat" +currentLat+"Lon"+currentLon,Toast.LENGTH_LONG).show();

    // Get JSON String and Break it down into individual nodes
    //double x=_location.getLatitude();
    //double y=_location.getLongitude();
    json_string = getIntent().getExtras().getString("JSON_DTA");
    LatLng latLng = null;
    try {
        int count = 0;
        //jsonObject = new JSONObject(json_string);
        jsonArray = new JSONArray(json_string);

        while (count < jsonArray.length()) {
            JSONObject JO = jsonArray.getJSONObject(count);
            _id = JO.getInt("id");
            _doctorname = JO.getString("doctorname");
            _doclat = JO.getString("latitude");
            _doclong = JO.getString("longitude");

            count++;

            Double d = Double.parseDouble(_doclat);
            Double e = Double.parseDouble(_doclong);
            latLng = new LatLng(d, e);

            DecimalFormat df = new DecimalFormat("####0.0");

            DistanceBetweenPoints distanceBetweenPoints = new DistanceBetweenPoints();
            double  distance = distanceBetweenPoints.CalculationByDistance(currentLatLng,latLng);

            double distanceThreshHold = 7 ;
            if(distance < distanceThreshHold  )
            {
                mMap = googleMap;
                mMap.setOnInfoWindowClickListener(this);
                MarkerOptions _markeroptions = new MarkerOptions()
                        .position(latLng)
                        .title(_doctorname+":  " + df.format(distance) + " KM" )
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.smallest_logo));
                mMap.addMarker(_markeroptions);

                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);


            }
            else
            {
                mMap = googleMap;
            }

     }


    } catch (JSONException e) {
        e.printStackTrace();
    }

    //Initialize Google Play Services
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            buildGoogleApiClient();

            mMap.setMyLocationEnabled(true);

        }
    } else {
        buildGoogleApiClient();
        mMap.setMyLocationEnabled(true);
    }
}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}
@Override
public void onConnected(@Nullable Bundle bundle) {

    mLocationRequest = new LocationRequest();

    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

}

@Override
public void onConnectionSuspended(int i) {

}


@Override
public void onLocationChanged(Location location) {

        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }


        //Place current location marker
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");
        markerOptions.draggable(true);

        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
        mCurrLocationMarker = mMap.addMarker(markerOptions);


      //  Toast.makeText(this, "Current" + latLng, Toast.LENGTH_LONG).show();
        String tag = null;
        Log.d(tag, "lon: " + location.getLongitude() + " ----- lat: " + location.getLatitude());


        //move map camera
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.animateCamera(CameraUpdateFactory.zoomTo(11));


        //stop location updates
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }


    }




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

}

public boolean checkLocationPermission(){
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

        // Asking user if explanation is needed
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_FINE_LOCATION)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

            //Prompt the user once explanation has been shown
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_LOCATION);


        } else {
            // No explanation needed, we can request the permission.
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_LOCATION);
        }
        return false;
    } else {
        return true;
    }
}
@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_LOCATION: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // Permission was granted.
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {

                    if (mGoogleApiClient == null) {
                        buildGoogleApiClient();
                    }
                    mMap.setMyLocationEnabled(true);
                }

            } else {

                // Permission denied, Disable the functionality that depends on this permission.
                Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
            }
            return;
        }

        // other 'case' lines to check for other permissions this app might  request.
        //You can add here other case statements according to your requirement.
    }
}

您的帮助将不胜感激。谢谢。

【问题讨论】:

  • 只需将 RelativeLayout 放在 MapFragment 上,带有 android:layout_width="match_parent" android:layout_height="wrap_content" ImageView 带有标记图片(它应该像带有透明层的 png 和标记图像本身应该位于图像的上半部分)并为其设置centerInParent="true"
  • 我已经在我的 XML 文件中完成了这项工作,添加了标记图像 (gps.png) 和 line centerInParent="true" 。我应该如何在 MapActivity 中调用它?
  • 在您的代码中,没有android:name="com.google.android.gms.maps.SupportMapFragment" 的容器,也没有RelativeLayout,也没有centerInParent="true"centerInParent="true" 参数
  • android:name="com.google.android.gms.maps.SupportMapFragment‌​" 在片段中,它是RelativeLayout的一部分。为 centerinParent 编辑

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


【解决方案1】:

在 ImageView 下放置一个带有标记图标的地图将是最好的方法(只需一个框架布局,其中地图片段位于下方,标记图像居中位于顶部即可)。然后您可以使用OnCameraIdleListener,它会在地图移动结束时收到回调。因此,只需为您的地图设置一个 OnCameraIdleListener 的实例,以监听移动回调,如下所示:

map.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
        @Override
        public void onCameraIdle() {
            //get latlng at the center by calling
            LatLng midLatLng = map.getCameraPosition().target;
        }
    });

【讨论】:

  • 所以我的 ImageView 将位于地图片段之上?
  • 是的,它应该在地图片段的顶部。
  • 如果您使用的是框架布局,请确保将其居中(android:layout_gravity="center"),否则它会显示在左上角。
  • 这必须在 OnMapReady 方法中调用?
  • @AIS 是的,在调用 OnMapReady 后设置 OnCameraIdleListener。还是你在问别的?
【解决方案2】:

首先为您的 Activity_map.xml 尝试此布局:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment"
    />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/gps"
    />

</RelativeLayout>

【讨论】:

  • 已编辑...见原帖
  • 1) 删除您的根 RelativeLayoutandroid:orientation="vertical" 2) 从您的地图片段中删除 xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"; 3) 将android:name="com.google.android.gms.maps.SupportMapFragment" 更改为class="com.google.android.gms.maps.SupportMapFragment" 提供here。它应该会有所帮助。
  • 不使用 xmlns:android="schemas.android.com/apk/res/android"> 给出了一个错误..因此它在那里
  • 您应该 2) 从您的地图片段中删除 xmlns:android="schemas.android.com/apk/res/android" 和 xmlns:tools="schemas.android.com/tools" 不是从根目录 RelativeLayout 从root RelativeLayout 你应该只删除 android:orientation="vertical" 文本。
  • 好的,现在我正在地图顶部获取图像视图...现在我希望它显示我当前的位置,就像我显示我的 MyActivity 代码一样。
猜你喜欢
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 2015-12-29
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多