Android 标记如何实现拖放?

问题描述 投票:0回答:7

嗨? 我正在 Android 中开发 MapView 应用程序。我有三个标记,我希望稍后能够使用 Google Map API getlocation-function。为了尝试一下,我想使用拖放功能移动标记,然后检查位置。

任何人都可以通过拖放操作来处理 Android 标记,或者知道如何开始弄清楚它吗?

/AK

android drag-and-drop android-mapview marker
7个回答
55
投票

实现 Google Maps Android API v2,请参考:https://developers.google.com/maps/documentation/android/ 并在 GoogleMap 对象上设置 setOnMarkerDragListener。例如:

map.setOnMarkerDragListener(new OnMarkerDragListener() {
        @Override
        public void onMarkerDragStart(Marker arg0) {
            // TODO Auto-generated method stub
            Log.d("System out", "onMarkerDragStart..."+arg0.getPosition().latitude+"..."+arg0.getPosition().longitude);
        }

        @SuppressWarnings("unchecked")
        @Override
        public void onMarkerDragEnd(Marker arg0) {
            // TODO Auto-generated method stub
            Log.d("System out", "onMarkerDragEnd..."+arg0.getPosition().latitude+"..."+arg0.getPosition().longitude);

            map.animateCamera(CameraUpdateFactory.newLatLng(arg0.getPosition()));
        }

        @Override
        public void onMarkerDrag(Marker arg0) {
            // TODO Auto-generated method stub
            Log.i("System out", "onMarkerDrag...");
        }
    });

//Don't forget to Set draggable(true) to marker, if this not set marker does not drag.

map.addMarker(new MarkerOptions()
    .position(crntLocationLatLng)
    .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_my_location))
    .draggable(true));

25
投票

这是一个示例项目,来自我的一本书,显示了 Android 中 Google 地图上标记的拖放移动。

简而言之,它使用

onTouchEvent()
来检测用户何时触摸并保持手指靠近标记。然后,它从叠加层中删除标记,但使用
RelativeLayout
将相同的图像放置在地图顶部。然后,在“移动”触摸事件中,图像会移动(比强制重绘整个覆盖层更快)。当手指抬起时,图像将被删除,但标记将被放回覆盖层中的新位置。


8
投票

对于MapsV2。使用谷歌地图事件。不要自己写。

        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                mVisitingMarker.setPosition(latLng);
                mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
            }
        });

        mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker arg0) {
            }

            @SuppressWarnings("unchecked")
            @Override
            public void onMarkerDragEnd(Marker arg0) {
               Log.d("System out", "onMarkerDragEnd...");
                mMap.animateCamera(CameraUpdateFactory.newLatLng(arg0.getPosition()));
            }

            @Override
            public void onMarkerDrag(Marker arg0) {
            }
        });

4
投票

以下是《Kotlin Lover》的解答!这非常非常简单!正如您在下面看到的。

   googleMap.addMarker(
        MarkerOptions()
            .position(latLatLng).draggable(true)
    )

下面是获取拖动结束位置的liner代码

   mMap.setOnMarkerDragListener(object : GoogleMap.OnMarkerDragListener {
        override fun onMarkerDragStart(arg0: Marker) {

        }

        override fun onMarkerDragEnd(arg0: Marker) {
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(arg0.position, 1.0f))
            val message = arg0.position.latitude.toString() + "" + arg0.position.longitude.toString()
            Log.d(TAG + "_END", message)
        }

        override fun onMarkerDrag(arg0: Marker?) {
            val message = arg0!!.position.latitude.toString() + "" + arg0.position.longitude.toString()
            Log.d(TAG + "_DRAG", message)
        }
    })

2
投票

我发现了对 CommonsWare 拖放出色功能的一点优化。

我正在用地图上的标记进行一些精确测量,我希望我的标记准确地位于我触摸并举起手指的位置,以便测量完全精确。

在 CommonsWare 的原件上,如果您触摸标记“附近”,标记不会到达该确切点,而是会随着手指的移动而移动。 我需要标记出现在我手指下方的 ACTION_DOWN、ACTION_MOVE 和 ACTION_UP 上。

如果有人需要的话,这是代码。我要感谢 CommonsWare 做了这个功能,真是个好主意。

这是我修改的部分代码。

我的MapView是mapa;

        @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView) {

        final int action=event.getAction();
        final int x=(int)event.getX();
        final int y=(int)event.getY();
        boolean result=false;

              if (action==MotionEvent.ACTION_DOWN) {
                for (OverlayItem item : mOverlays) {
                  Point p=new Point(0,0);

                  mapa.getProjection().toPixels(item.getPoint(), p);

                      //I maintain the hitTest's bounds so you can still
                      //press near the marker
                  if (hitTest(item, marker, x-p.x, y-p.y)) {
                    result=true;

                    inDrag=item;

                    mOverlays.remove(inDrag);
                    populate();

                        //Instead of using the DragImageOffSet and DragTouchOffSet
                        //I use the x and y coordenates from the Point
                    setDragImagePosition(x, y);

                    dragImage.setVisibility(View.VISIBLE);

                    break;
                  }
                }
              }
              else if (action==MotionEvent.ACTION_MOVE && inDrag!=null) {
                setDragImagePosition(x, y);

                result=true;
              }
              else if (action==MotionEvent.ACTION_UP && inDrag!=null) {
                dragImage.setVisibility(View.GONE);

                    //I get the geopoint without using any OffSet, directly with the 
                    //Point coordenates
                GeoPoint pt=mapa.getProjection().fromPixels(x,y);

                OverlayItem toDrop=new OverlayItem(pt, inDrag.getTitle(),
                                                   inDrag.getSnippet());
                orig = inDrag.getMarker(0);

                    //In my case I had down heading Arrows as markers, so I wanted my 
                    //bounds to be at the center bottom
                toDrop.setMarker(boundCenterBottom(orig));

                mOverlays.add(toDrop);
                populate();

                inDrag=null;
                result=true;
              }


           return(result || super.onTouchEvent(event, mapView));


    }

    private void setDragImagePosition(int x, int y) {
      RelativeLayout.LayoutParams lp=
        (RelativeLayout.LayoutParams)dragImage.getLayoutParams();

          //Instead of using OffSet I use the Point coordenates.
          //I want my arrow to appear pointing to the point I am moving, so 
          //I set the margins as the Point coordenates minus the Height and half the
          //width of my arrow.
      lp.setMargins(x-(dragImage.getWidth()/2),y-dragImage.getHeight(), 0, 0);
      dragImage.setLayoutParams(lp);
    }

这样,您的箭头就会出现在您按下的位置,而不是箭头从原来的位置移动。


0
投票

我上周偶然发现了这一点。我想我找到了解决方案: 需要拦截触摸事件并编写自己的拖动算法。要拦截onTouchEvent,我们需要用自定义视图包装它来拦截它。

class TouchableWrapper(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
    var touchListener: OnTouchListener? = null

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        val result = touchListener?.onTouch(this, ev)
        return if (result == false) super.dispatchTouchEvent(ev)
        else result == true
    }
}

包裹你的地图片段:

<com.example.mapplayground.presentation.utils.TouchableWrapper
        android:id="@+id/map_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </com.example.mapplayground.presentation.utils.TouchableWrapper>

然后我们可以创建自定义触摸监听器,然后分配给可触摸包装器

class CustomOnTouchListener: View.OnTouchListener {
    override fun onTouch(v: View, event: MotionEvent): Boolean {
        when(event.action){
            MotionEvent.ACTION_DOWN ->{
                // do something like recording initial touch point
                return true // if consumed, if not, it will propagated to the parent
            }
            MotionEvent.ACTION_MOVE -> {
                // do something
                
                return true // if consumed, if not, it will propagated to the parent
            }
            MotionEvent.ACTION_UP ->{
                // do something
            }
        }
        
        return false // propagate to parent eventually
    }
}

touchableWrapper.touchListener = CustomTouchListener()

这是完整的代码: https://gist.github.com/Humayung/30623f3fed1e07794cc01a98c2fae97f


-2
投票

这里是Android中Mapview中拖放图钉的完整代码

© www.soinside.com 2019 - 2024. All rights reserved.