如何在android中的图像视图上添加图钉标记

Posted

技术标签:

【中文标题】如何在android中的图像视图上添加图钉标记【英文标题】:how to add a pin marker on image view in android 【发布时间】:2012-12-08 21:44:40 【问题描述】:

我正在做一个项目,我需要在图像视图上添加引脚,如下图所示。 我们怎么能这样做。

我使用成功创建了一个可缩放的图像视图

TouchImageview.java

 class TouchImageView extends ImageView 

Matrix matrix = new Matrix();

// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;

// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;

float redundantXSpace, redundantYSpace;

float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

ScaleGestureDetector mScaleDetector;

Context context;


@Override
protected void onDraw(Canvas canvas) 

    super.onDraw(canvas);       




public TouchImageView(Context context) 
    super(context);
    super.setClickable(true);
    this.context = context;
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    matrix.setTranslate(1f, 1f);
    m = new float[9];
    setImageMatrix(matrix);
    setScaleType(ScaleType.MATRIX);

    setOnTouchListener(new OnTouchListener() 

        @Override
        public boolean onTouch(View v, MotionEvent event) 
            mScaleDetector.onTouchEvent(event);



            Log.e("Deepak", "X" + event.getRawX());

            Log.e("Deepak", "Y" + event.getRawY());



            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            PointF curr = new PointF(event.getX(), event.getY());



            switch (event.getAction()) 
                case MotionEvent.ACTION_DOWN:
                    last.set(event.getX(), event.getY());
                    start.set(last);
                    mode = DRAG;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) 
                        float deltaX = curr.x - last.x;
                        float deltaY = curr.y - last.y;
                        float scaleWidth = Math.round(origWidth * saveScale);
                        float scaleHeight = Math.round(origHeight * saveScale);
                        if (scaleWidth < width) 
                            deltaX = 0;
                            if (y + deltaY > 0)
                                deltaY = -y;
                            else if (y + deltaY < -bottom)
                                deltaY = -(y + bottom); 
                         else if (scaleHeight < height) 
                            deltaY = 0;
                            if (x + deltaX > 0)
                                deltaX = -x;
                            else if (x + deltaX < -right)
                                deltaX = -(x + right);
                         else 
                            if (x + deltaX > 0)
                                deltaX = -x;
                            else if (x + deltaX < -right)
                                deltaX = -(x + right);

                            if (y + deltaY > 0)
                                deltaY = -y;
                            else if (y + deltaY < -bottom)
                                deltaY = -(y + bottom);
                        
                        matrix.postTranslate(deltaX, deltaY);
                        last.set(curr.x, curr.y);
                    
                    break;

                case MotionEvent.ACTION_UP:
                    mode = NONE;
                    int xDiff = (int) Math.abs(curr.x - start.x);
                    int yDiff = (int) Math.abs(curr.y - start.y);
                    if (xDiff < CLICK && yDiff < CLICK)
                        performClick();
                    break;

                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
            
            setImageMatrix(matrix);
            invalidate();
            return true; // indicate event was handled
        

    );


@Override
public void setImageBitmap(Bitmap bm)  
    super.setImageBitmap(bm);
    bmWidth = bm.getWidth();
    bmHeight = bm.getHeight();


public void setMaxZoom(float x)


    maxScale = x;


private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener 
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) 
        mode = ZOOM;
        return true;
    

    @Override
    public boolean onScale(ScaleGestureDetector detector) 
        float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
        float origScale = saveScale;
        saveScale *= mScaleFactor;
        if (saveScale > maxScale) 
            saveScale = maxScale;
            mScaleFactor = maxScale / origScale;
         else if (saveScale < minScale) 
            saveScale = minScale;
            mScaleFactor = minScale / origScale;
        
        right = width * saveScale - width - (2 * redundantXSpace * saveScale);
        bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
        if (origWidth * saveScale <= width || origHeight * saveScale <= height) 
            matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
            if (mScaleFactor < 1) 
                matrix.getValues(m);
                float x = m[Matrix.MTRANS_X];
                float y = m[Matrix.MTRANS_Y];
                if (mScaleFactor < 1) 
                    if (Math.round(origWidth * saveScale) < width) 
                        if (y < -bottom)
                            matrix.postTranslate(0, -(y + bottom));
                        else if (y > 0)
                            matrix.postTranslate(0, -y);
                     else 
                        if (x < -right) 
                            matrix.postTranslate(-(x + right), 0);
                        else if (x > 0) 
                            matrix.postTranslate(-x, 0);
                    
                
            
         else 
            matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            if (mScaleFactor < 1) 
                if (x < -right) 
                    matrix.postTranslate(-(x + right), 0);
                else if (x > 0) 
                    matrix.postTranslate(-x, 0);
                if (y < -bottom)
                    matrix.postTranslate(0, -(y + bottom));
                else if (y > 0)
                    matrix.postTranslate(0, -y);
            
        
        return true;

    


@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = MeasureSpec.getSize(widthMeasureSpec);
    height = MeasureSpec.getSize(heightMeasureSpec);
    //Fit to screen.
    float scale;
    float scaleX =  (float)width / (float)bmWidth;
    float scaleY = (float)height / (float)bmHeight;
    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);
    setImageMatrix(matrix);
    saveScale = 1f;

    // Center the image
    redundantYSpace = (float)height - (scale * (float)bmHeight) ;
    redundantXSpace = (float)width - (scale * (float)bmWidth);
    redundantYSpace /= (float)2;
    redundantXSpace /= (float)2;

    matrix.postTranslate(redundantXSpace, redundantYSpace);

    origWidth = width - 2 * redundantXSpace;
    origHeight = height - 2 * redundantYSpace;
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
    setImageMatrix(matrix);



现在我需要在上面添加标记。 任何帮助。

【问题讨论】:

我搜索并找到了***.com/questions/13679189/…,但没有得到解决方案 那么你能把它们画在你得到的图像上并保存为新的位图吗? @vodich 好的,但是如何将点击事件添加到标记(我试过了。但在创建单个位图后点击事件出现问题)。 @CommonsWare 你知道怎么做吗 【参考方案1】:

我在这里找到了答案https://github.com/catchthecows/androidImageMap

在 Android 视图中实现类似 html 地图的元素:

支持图像作为可绘制或布局中的位图 允许在 xml 中列出区域标签 允许对资源 xml 使用剪切和粘贴 HTML 区域标签(即,能够获取 HTML 地图 - 和图像并在最少编辑的情况下使用它) 如果图像大于设备屏幕,则支持平移 支持捏合缩放 支持点击区域时的回调。 支持将注释显示为气泡文本,并在点击气泡时提供回调

【讨论】:

【参考方案2】:

我使用过 AndroidImageMap,但我不喜欢它缩放图像的方式,而且您没有将自定义视图添加为可点击区域的功能。

查看这个示例项目https://github.com/jzafrilla/AndroidImageHostpot 我使用https://github.com/chrisbanes/PhotoView/ 来获得缩放和平移功能。

希望这会有所帮助......(对我来说,绝对是的)

【讨论】:

我设法用 PhotoView 实现了这个功能。你的代码帮助了我,谢谢。但是,您的方法需要修改 PhotoView 库,这并不是真正必要的:更好的解决方案是将 onMatrixChangeListener 设置为 photoView 并将用于更新坐标的代码放在那里。此外,这是一个看起来很有前途的库。它支持缩放/平移和在图像上添加图钉github.com/davemorrissey/subsampling-scale-image-view

以上是关于如何在android中的图像视图上添加图钉标记的主要内容,如果未能解决你的问题,请参考以下文章

如何在地图上显示图像而不是作为图钉而是作为单独的图像? [复制]

如何让地图视图中的应用程序用户删除多个图钉?

群集注释图钉需要更多时间才能在 Mapview 上添加它们

如何在 SwiftUI 的新地图视图中制作可点击的图钉?

通过 SVG 保存和加载图钉标记

如何使用相机谷歌地图 xcode 移动标记(图钉)