36

假设我们在地图上有一个居中的标记,当我们用手指移动地图时,我们可以看到当您离开该区域时,该标记将不再显示。那么,尽管我们将地图移动到任何地方,我们如何制作一个始终保持在地图中心的标记呢?有一个名为 UBER 的应用程序,他们提供此功能,您无需拖放标记,只需移动地图,标记保持其位置。

这是一个屏幕截图:

优步地图标记

如您所见,当我们移动地图时,绿色标记位于屏幕中央,它保持原位,但在用户停止移动地图时显示新位置。我们怎么能这样呢?

我有一个代码在您拖放标记时显示地址,如何再次显示地址但这次不是通过拖动,移动地图?希望你能理解任何想法都会很棒。

public class MainActivity extends AbstractMapActivity implements
    OnNavigationListener, OnInfoWindowClickListener,
    OnMarkerDragListener {
  private static final String STATE_NAV="nav";
  private static final int[] MAP_TYPE_NAMES= { R.string.normal,
    R.string.hybrid, R.string.satellite, R.string.terrain };
  private static final int[] MAP_TYPES= { GoogleMap.MAP_TYPE_NORMAL,
    GoogleMap.MAP_TYPE_HYBRID, GoogleMap.MAP_TYPE_SATELLITE,
    GoogleMap.MAP_TYPE_TERRAIN };
private GoogleMap map=null;
String filterAddress = "";
Marker marker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (readyToGo()) {
        setContentView(R.layout.activity_main);

        SupportMapFragment mapFrag=
            (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);

        mapFrag.setRetainInstance(true);
        initListNav();

        map=mapFrag.getMap();

        if (savedInstanceState == null) {
            CameraUpdate center=
                CameraUpdateFactory.newLatLng(new LatLng(
                        41.003739,
                        28.999572));
            CameraUpdate zoom=CameraUpdateFactory.zoomTo(10);

            map.moveCamera(center);
            map.animateCamera(zoom);

            addMarker(map, 41.003739, 28.999572, R.string.un, R.string.united_nations);

              map.setInfoWindowAdapter(new PopupAdapter(getLayoutInflater()));
              map.setOnInfoWindowClickListener(this);
              map.setOnMarkerDragListener(this);
        }
    }
}

@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
    map.setMapType(MAP_TYPES[itemPosition]);

    return(true);
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);

    savedInstanceState.putInt(STATE_NAV,
            getSupportActionBar().getSelectedNavigationIndex());
}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
getSupportActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_NAV));
}

@Override
public void onInfoWindowClick(Marker marker) {
    Toast.makeText(this, marker.getTitle(), Toast.LENGTH_LONG).show();
}

@Override
public void onMarkerDragStart(Marker marker) {
    LatLng position=marker.getPosition();

    Log.d(getClass().getSimpleName(), String.format("Drag from %f:%f",
            position.latitude,
            position.longitude));
}

@Override
public void onMarkerDrag(Marker marker) {
    LatLng position=marker.getPosition();

    Log.d(getClass().getSimpleName(),
            String.format("Dragging to %f:%f", position.latitude,
                    position.longitude));
}

@Override
public void onMarkerDragEnd(Marker marker) {
    LatLng position=marker.getPosition();

    String filterAddress = "";
    Geocoder geoCoder = new Geocoder(
            getBaseContext(), Locale.getDefault());
    try {
        List<Address> addresses = geoCoder.getFromLocation(
                position.latitude, 
                position.longitude, 1);

        if (addresses.size() > 0) {
            for (int index = 0; 
            index < addresses.get(0).getMaxAddressLineIndex(); index++)
                filterAddress += addresses.get(0).getAddressLine(index) + " ";
        }
    }catch (IOException ex) {        
        ex.printStackTrace();
    }catch (Exception e2) {
        // TODO: handle exception
        e2.printStackTrace();
    } 
    Log.d(getClass().getSimpleName(),
            String.format("Dragging to %f:%f", position.latitude,
                    position.longitude));
    TextView myTextView = (TextView) findViewById(R.id.test);

    myTextView.setText("Address is: " + filterAddress);

}

private void initListNav() {
    ArrayList<String> items=new ArrayList<String>();
    ArrayAdapter<String> nav=null;
    ActionBar bar=getSupportActionBar();

    for (int type : MAP_TYPE_NAMES) {
        items.add(getString(type));
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        nav=
            new ArrayAdapter<String>(
                    bar.getThemedContext(),
                    android.R.layout.simple_spinner_item,
                    items);
    }
    else {
        nav=
            new ArrayAdapter<String>(
                    this,
                    android.R.layout.simple_spinner_item,
                    items);
    }

    nav.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
    bar.setListNavigationCallbacks(nav, this);
}

private void addMarker(GoogleMap map, double lat, double lon,
        int title, int snippet)

{
    map.addMarker(new MarkerOptions().position(new LatLng(lat, lon))
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.pin))

            .draggable(true));
}
    }

这是xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/img_header" >

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

<TextView
    android:id="@+id/test"
    android:layout_width="match_parent"
    android:layout_height="90dp"
    android:layout_alignParentRight="true"
    android:text="Address : "
    android:textColor="#FF0000"
    android:textSize="22sp" />
</RelativeLayout>
4

6 回答 6

40

两个简单的步骤:

步骤1

我使用 RelativeLayout 作为片段的父级,其中包含地图和居中的 ImageView(就像在 uber 或简易出租车应用程序中一样,它将作为居中的地图标记):

<!-- Map and ImageView in center for simulating the map marker -->
<RelativeLayout
    android:id="@+id/confirm_address_map_wrapper"
    android:layout_width="match_parent"
    android:layout_height="220dp">

    <fragment
        android:id="@+id/confirm_address_map_fragment"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        />
    <!-- Image View that acts as map marker notice centerInParent-->

     <View
        android:id="@+id/view"
        android:layout_width="1dp"
        android:layout_height="1dp"
        android:layout_centerInParent="true"/>


    <ImageView
        android:id="@+id/confirm_address_map_custom_marker"
        android:layout_width="@dimen/ICON_DEFAULT_SIZE"
        android:layout_height="@dimen/ICON_DEFAULT_SIZE"
        android:layout_above="@+id/view"
        android:layout_centerHorizontal="true"
        android:src="@mipmap/my_map_marker"/>
</RelativeLayout>

第2步

我的活动中的 onMapReady() 方法我使用 googleMap 实例方法setOnCameraChangeListener(),该方法让我在使用地图时进行监听,并根据相机位置的中心获取纬度和经度:

    @Override
    public void onMapReady(GoogleMap googleMap) {

        googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {

           Log.i("centerLat",cameraPosition.target.latitude);

           Log.i("centerLong",cameraPosition.target.longitude);
        }
    });

}

更新:
OnCameraChangeListener已弃用。请使用OnCameraIdleListener
[来源:https://stackoverflow.com/a/38732283/421467]

于 2015-12-11T18:58:40.257 回答
9

我无法获得 Uber 应用程序效果,但是我能够做类似的事情,也许它会为您使用GoogleMap.OnCameraChangeListener的解决方案做得很好。

活动:

public class MyActivity extends Activity implements OnCameraChangeListener {

    ...

    @Override
    public void onCameraChange(CameraPosition position) {
        mMap.clear();
        mMap.addMarker( new MarkerOptions()
            .position( position.target )
            .title( position.toString() )
        );
    }

    ...

}

问题是,在移动相机时未绘制标记。但是,您似乎已经创建了标记的叠加层。因此,通过叠加,它应该像 Uber 应用程序一样工作。

我希望这会有所帮助,即使是几个月前的问题,也许它会对未来的开发人员有所帮助。

亲切的问候三木

于 2013-12-15T17:38:37.223 回答
3

如果您Fragment用于显示您的谷歌地图,请将其ImageView放在里面Fragment以覆盖您的自定义标记,以便在您移动地图时您的标记保持固定。按照xml文件的代码:

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

    <ImageView
        android:id="@+id/pin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:contentDescription="@null"
        android:src="@drawable/pin" />
</fragment>

在 activity.java 文件中使用:

ImageView pinButton = (ImageView) findViewById(R.id.pin);

用于setOnCameraChangeListener()根据相机位置的中心获取纬度和经度或按照@androidPlusPlus提供的答案

于 2016-01-11T11:53:54.767 回答
2
mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
    @Override
    public void onCameraMove() {
        mCurrLocationMarker.remove();
        LatLng midLatLng = mMap.getCameraPosition().target;
        mCurrLocationMarker = mMap.addMarker(new MarkerOptions().title("I am here ").
        position(midLatLng).icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_point));
    }
});

mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
    @Override
    public void onCameraIdle() {
        mCurrLocationMarker.remove();
        LatLng position = mCurrLocationMarker.getPosition();
        mCurrLocationMarker = mMap.addMarker(new MarkerOptions().title("I am here ").
        position(position).icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_source)));
        getAddress(position.latitude, position.longitude);

    }
});
于 2019-02-07T13:31:31.807 回答
1

检查这个答案

首先:将一个imageview添加到相同的布局和位置等于中心。第二:获取地图中心的坐标使用以下方法

1_ get viewgroup ( FrameLayout ) in my case where the map fragment is located.

 - FrameLayout myContainer = (FrameLayout) findViewById(R.id.content_frame);
    int mapHeight = myContainer.getHeight();
    int mapWidth = myContainer.getWidth();
2_ use setOnCameraChangeListener and on camera change get the coordinates:

LatLng center = mMap.getCameraPosition().target;

这也是 我完整解决方案

于 2014-12-16T12:32:59.993 回答
0

对于那些使用osmdroid地图 api 的人,请使用以下代码

marker = new Marker(map);
marker.setDraggable(true);
marker.setPosition(defPosition);
marker.setAnchor((float)0.5, (float)0.5);
map.getOverlays().add(marker);
////The overlay
Overlay mOverlay = new Overlay() {

    @Override
    public boolean onScroll(MotionEvent pEvent1, MotionEvent pEvent2, float pDistanceX, float pDistanceY, MapView pMapView) {

        marker.setPosition(new GeoPoint((float) pMapView.getMapCenter().getLatitude(),
                (float) pMapView.getMapCenter().getLongitude()));

        return super.onScroll(pEvent1, pEvent2, pDistanceX, pDistanceY, pMapView);
    }
};

map.getOverlays().add(mOverlay);
于 2020-04-05T22:56:54.900 回答