5

我正在使用 Dave Morrissey 的 Subsampling Scale Image View。我修改了 Pinview 示例(如下所示:https ://github.com/davemorrissey/subsampling-scale-image-view/blob/master/sample/src/com/davemorrissey/labs/subscaleview/sample/extension/views/ PinView.java ) 来支持 pin 数组。现在我想让每个引脚都可以点击以触发点击功能。下面的代码正确放置了多个标记。请让我知道如何使每个图钉可点击,我想读取点击事件函数中的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;
    }
}
4

1 回答 1

4

目前正在处理相同的问题:您可以按照以下建议向您的自定义视图添加一个手势检测器和一个触摸监听器: https ://github.com/davemorrissey/subsampling-scale-image-view/wiki/09.-Events

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

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

  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);
        }
    });
}
于 2016-03-21T09:31:51.283 回答