使用子采样比例图像视图在触摸位置添加标记针

Adding Marker Pins at touched Position using subsampling scale image view

我在我的应用程序中使用 "subsampling scale image view",我想在用户长按 PinView 时动态地将标记图钉添加到 PinView。标记针应出现在单击的位置。

我实现了在长按后出现标记针,但位置错误。这是我的 Fragment 的 onCreateView 方法:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    pinCounter=0;

    View rootView = inflater.inflate(R.layout.fragment_edit_plan, container, false);
    src = getArguments().getString("src");
    imageView = (PinView)rootView.findViewById(R.id.imageView);

    imageView.setImage(ImageSource.uri(src));
    imageView.isLongClickable();
    imageView.isClickable();
    imageView.hasOnClickListeners();

    MapPins = new ArrayList();
    imageView.setPins(MapPins);

    imageView.setOnLongClickListener(this);
    imageView.setOnTouchListener(this);

    return  rootView;
}

侦听器方法:

@Override
public boolean onLongClick(View view) {
    if (view.getId() == R.id.imageView) {
        Toast.makeText(getActivity(), "Long clicked "+lastKnownX+" "+lastKnownY, Toast.LENGTH_SHORT).show();
        Log.d("EditPlanFragment","Scale "+imageView.getScale());
        MapPins.add(new MapPin(lastKnownX,lastKnownY,pinCounter));
        imageView.setPins(MapPins);

        imageView.post(new Runnable(){
            public void run(){
                imageView.getRootView().postInvalidate();
            }
        });

        return true;
    }
    return false;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (v.getId()== R.id.imageView && event.getAction() == MotionEvent.ACTION_DOWN){
        lastKnownX= event.getX();
        lastKnownY= event.getY();
    }
    return false;
}

我的XML-文件:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="50dp"
>

<com.example.viktoriabock.phoenixversion1.PinView
    android:id="@+id/imageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:longClickable="true"

   />

和 PinView-Class:

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(), R.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
    }
}

您正在收集长按的屏幕坐标,然后在自定义视图中将它们从源坐标转换为屏幕坐标。获取点击事件时,需要将事件坐标转换为源坐标,使用视图的viewToSourceCoord方法。

有一种比使用您的 lastKnown 值更简单的方法 - 使用您自己的 GestureDetector.

有关长按手势检测器的完整工作示例,请参阅 AdvancedEventHandlingActivity sample class