java - 子采样比例 ImageView - 使图钉标记在 Imageview 上可点击

标签 java android bitmap imageview subsampling

我正在使用 Dave Morrissey 的子采样比例 ImageView 。我修改了 Pinview 示例(如此处所示:https://github.com/davemorrissey/subsampling-scale-image-view/blob/master/sample/src/com/davemorrissey/labs/subscaleview/sample/extension/views/PinView.java)以支持引脚数组。现在我想让每个引脚都可以点击以触发点击功能。下面的代码正确放置了多个标记。请让我知道如何使每个图钉都可点击,我想阅读点击事件函数中的 id 并在 toast 示例中显示 MapPin(1718f, 581f, (id) 1).

修改PinView.java

   public class PinView extends SubsamplingScaleImageView {

   private PointF sPin;

   ArrayList<MapPin> mapPins;
   ArrayList<DrawPin> drawnPins;
   Context context;
   String tag = getClass().getSimpleName();

   public PinView(Context context) {
    this(context, null);
    this.context = context;
   }

   public PinView(Context context, AttributeSet attr) {
    super(context, attr);
    this.context = context;
    initialise();
   }

   public void setPins(ArrayList<MapPin> mapPins) {
    this.mapPins = mapPins;
    initialise();
    invalidate();
   }

   public void setPin(PointF pin) {
    this.sPin = pin;
   }

   public PointF getPin() {
    return sPin;
   }

   private void initialise() {

   }

   @Override
   protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Don't draw pin before image is ready so it doesn't move around during       setup.
    if (!isReady()) {
        return;
    }

    drawnPins = new ArrayList<>();

    Paint paint = new Paint();
    paint.setAntiAlias(true);
    float density = getResources().getDisplayMetrics().densityDpi;


    for (int i = 0; i < mapPins.size(); i++) {
        MapPin mPin = mapPins.get(i);
        //Bitmap bmpPin = Utils.getBitmapFromAsset(context, mPin.getPinImgSrc());
        Bitmap bmpPin = BitmapFactory.decodeResource(this.getResources(), drawable.pushpin_blue);

        float w = (density / 420f) * bmpPin.getWidth();
        float h = (density / 420f) * bmpPin.getHeight();
        bmpPin = Bitmap.createScaledBitmap(bmpPin, (int) w, (int) h, true);

        PointF vPin = sourceToViewCoord(mPin.getPoint());
        //in my case value of point are at center point of pin image, so we need to adjust it here

        float vX = vPin.x - (bmpPin.getWidth() / 2);
        float vY = vPin.y - bmpPin.getHeight();


        canvas.drawBitmap(bmpPin, vX, vY, paint);

        //add added pin to an Array list to get touched pin
        DrawPin dPin = new DrawPin();
        dPin.setStartX(mPin.getX() - w / 2);
        dPin.setEndX(mPin.getX() + w / 2);
        dPin.setStartY(mPin.getY() - h / 2);
        dPin.setEndY(mPin.getY() + h / 2);
        dPin.setId(mPin.getId());
        drawnPins.add(dPin);
    }
}

public int getPinIdByPoint(PointF point) {

    for (int i = drawnPins.size() - 1; i >= 0; i--) {
        DrawPin dPin = drawnPins.get(i);
        if (point.x >= dPin.getStartX() && point.x <= dPin.getEndX()) {
            if (point.y >= dPin.getStartY() && point.y <= dPin.getEndY()) {
                return dPin.getId();
            }
        }
    }
    return -1; //negative no means no pin selected
}
}

MapPin.java

    public class MapPin {
    float X, Y;
    int id;

        public MapPin(float X, float Y, int id) {
            this.X = X;
            this.Y = Y;
            this.id = id;
        }

        public MapPin() {
        }

        public float getX() {
            return X;
        }

        public void setX(float X) {
            this.X = X;
        }

        public float getY() {
            return Y;
        }

        public void setY(float Y) {
            this.Y = Y;
        }

        public PointF getPoint() {
            return new PointF(this.X, this.Y);
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

DrawPin.java

public class DrawPin {

    float startX, startY, endX, endY;
    int id;

    public DrawPin(float startX, float startY, float endX, float endY, int id) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;
        this.id = id;
    }

    public DrawPin() {
        //empty
    }

    public float getStartX() {
        return startX;
    }

    public void setStartX(float startX) {
        this.startX = startX;
    }

    public float getStartY() {
        return startY;
    }

    public void setStartY(float startY) {
        this.startY = startY;
    }

    public float getEndX() {
        return endX;
    }

    public void setEndX(float endX) {
        this.endX = endX;
    }

    public float getEndY() {
        return endY;
    }

    public void setEndY(float endY) {
        this.endY = endY;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

ExtensionPinFragment

public class ExtensionPinFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(layout.extension_pin_fragment, container, false);
        rootView.findViewById(id.next).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                ((ExtensionActivity) getActivity()).next();
            }
        });
        PinView imageView = (PinView)rootView.findViewById(id.imageView);
        imageView.setImage(ImageSource.asset("squirrel.jpg"));

        MapPin mapPin = new MapPin(1718f, 581f, 1);
        MapPin mapPin1 = new MapPin(500f, 681f, 2);

        ArrayList<MapPin> MapPins = new ArrayList();
        MapPins.add(new MapPin(1718f, 581f, 1));
        MapPins.add(new MapPin(500f, 681f, 2));
        imageView.setPins(MapPins);

        // Below on click listener associated with entire image but I want the click event listener for individual pins

        imageView.setOnClickListener(new OnClickListener() {
                                         @Override
                                         public void onClick(View view) {
                                             ((ExtensionActivity) getActivity()).next();
                                         }
                                     }
        );
        return rootView;
    }
}

最佳答案

目前正在处理同一个问题: 您可以按照以下建议将 gestureDetector 和触摸监听器添加到自定义 View 中: https://github.com/davemorrissey/subsampling-scale-image-view/wiki/09.-Events

在 GestureDetector 中覆盖 onSingleTapConfirmed() 方法并检查点击的触摸坐标是否与引脚坐标匹配(使用 sourceToView 转换触摸和引脚坐标...),如果匹配则处理您想要执行的任何代码。

这是我的自定义 SubsamplingScaleImageView 中的部分代码,在将 pin 添加到 View 后调用它:

  private void setTouchListener() {
    /** https://github.com/davemorrissey/subsampling-scale-image-view/wiki/09.-Events:
     *  ...you must check that the view is ready with the isReady() method before attempting to convert screen
     *  coordinates to image coordinates. A NullPointerException may be thrown if you don't. It is safe to override
     *  onSingleTapUp, onSingleTapConfirmed, onLongPress and onDown from the SimpleOnGestureListener class. If you
     *  override other methods, you will prevent the view from properly handling double taps, zoom and pan gestures.
     */

    final GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            if (isReady() && deeplinkCoordinates != null) {
                PointF tappedCoordinate = new PointF(e.getX(), e.getY());

                int blockWidth = deepLinkBitmap.getWidth();
                int blockHeight = deepLinkBitmap.getHeight();

                // check if deepLinkBitmap is touched
                for (PointF deeplink : deeplinkCoordinates) {
                    PointF deeplinkCoordinate = sourceToViewCoord(deeplink);
                    int deeplinkX = (int) (deeplinkCoordinate.x - (deepLinkBitmap.getWidth() / 2));
                    int deeplinkY = (int) (deeplinkCoordinate.y - deepLinkBitmap.getHeight());

                    // center coordinate -/+ blockWidth actually sets touchable area to 2x icon size
                    if (tappedCoordinate.x >= deeplinkX - blockWidth && tappedCoordinate.x <= deeplinkX + blockWidth &&
                            tappedCoordinate.y >= deeplinkY - blockHeight && tappedCoordinate.y <= deeplinkY + blockHeight) {
                        // App.toast("You tapped on a deeplink!");
                    } 
                }
            }
            return true;
        }
    });

    setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            return gestureDetector.onTouchEvent(motionEvent);
        }
    });
}

关于java - 子采样比例 ImageView - 使图钉标记在 Imageview 上可点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35307624/

相关文章:

java - 从 jar 中提取 scala 源代码

java - FindBugs 希望 readObject(...) 为序列化私有(private),为什么?

java - Java 中可以接受这种类型的 while 循环吗?

android - 如何在Android上强制关闭应用程序,例如系统关闭

java - 在切换期间存储变量更改 [Java]

c# - 去除图像透明度

java - 实现一个队列,您可以在特定位置插入元素,同时在恒定时间内入队/出队?

android - 创建适配器图像时无法应用对象中的 object()

Android:位图中的 RGB 值错误

Android位图FileNotFoundException ENOENT while方法仅在文件存在时调用