Java 我如何在android中用x y位置在图像上制作可移动的圆点?

Java 我如何在android中用x y位置在图像上制作可移动的圆点?,java,android,canvas,Java,Android,Canvas,我有一个图像,我想在图像上画一个8点,当触摸点并拖动到屏幕上时,这个点会移动,这能在图像上画出这种类型的触摸点和可移动的点吗 在8点上显示上面的图像,我想得到这样的结果,当你们触摸那个点时,那个点是移动的,在图像上移动,也要那个点的x,y坐标 我尝试了下面的代码,但它的显示点的形式不正确,并且所有的点同时移动 class DrawingView extends View { Bitmap bitmap; float x, y; public

我有一个图像,我想在图像上画一个8点,当触摸点并拖动到屏幕上时,这个点会移动,这能在图像上画出这种类型的触摸点和可移动的点吗

在8点上显示上面的图像,我想得到这样的结果,当你们触摸那个点时,那个点是移动的,在图像上移动,也要那个点的x,y坐标

我尝试了下面的代码,但它的显示点的形式不正确,并且所有的点同时移动

class DrawingView extends View {
        Bitmap bitmap;

        float x, y;

        public DrawingView(Context context) {
            super(context);
            bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_dot);
        }


        public boolean onTouchEvent(MotionEvent event) {

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {

                }
                break;

                case MotionEvent.ACTION_MOVE: {
                    x = (int) event.getX();
                    y = (int) event.getY();

                    invalidate();
                }

                break;
                case MotionEvent.ACTION_UP:

                    x = (int) event.getX();
                    y = (int) event.getY();
                    System.out.println(".................." + x + "......" + y); //x= 345 y=530
                    invalidate();
                    break;
            }
            return true;
        }

        @Override
        public void onDraw(Canvas canvas) {
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.WHITE);
           // canvas.drawBitmap(bitmap, x, y, paint);  //originally bitmap draw at x=o and y=0
            for (int i = 0; i < 8; i++) {
                canvas.drawBitmap(bitmap, x++, y++,  null);
            }
        }
    }

类DrawingView扩展视图{
位图;
浮动x,y;
公共绘图视图(上下文上下文){
超级(上下文);
位图=BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_点);
}
公共布尔onTouchEvent(运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:{
}
打破
case MotionEvent.ACTION\u移动:{
x=(int)event.getX();
y=(int)event.getY();
使无效();
}
打破
case MotionEvent.ACTION\u UP:
x=(int)event.getX();
y=(int)event.getY();
System.out.println(“…”+x+“…”+y);//x=345 y=530
使无效();
打破
}
返回true;
}
@凌驾
公共空白onDraw(画布){
油漆=新油漆();
绘制.设置样式(绘制.样式.填充);
油漆。设置颜色(颜色。白色);
//drawBitmap(位图,x,y,paint);//最初在x=o和y=0处绘制位图
对于(int i=0;i<8;i++){
drawBitmap(位图,x++,y++,null);
}
}
}
如果有人知道这种类型的视图或解决方案,请提供帮助

提前感谢:)

  • 创建一个自定义的
    ImageView
    ,它扩展了
    androidx.appcompat.widget.AppCompatImageView
    类,该类使用
    ArrayList
    实现了一个
    OnTouchListener
    ,该列表将跟踪
    Dot
    s

  • 覆盖自定义
    ImageView
    onDraw(画布画布)
    ,并迭代
    Dot
    s的
    ArrayList
    ,使用
    Canvas.drawCircle(float-cx,float-cy,float-radius,@NonNull-Paint-Paint)绘制列表中的每个
    Dot

  • 每当触发
    MotionEvent.ACTION\u DOWN
    时,检查触摸是否在现有点内

    如果您将
    Dot
    设置为全局变量,即
    touchedDot
    ,则当用户将
    移动到TouchListener
    上时,将触发
    MotionEvent.ACTION\u MOVE
    然后检查
    touchedDot!=null
    如果是,只需更改其
    x
    y
    即可,通过
    touchedDot.x=event.getX()
    touchedDot.y=event.getY()
    方法匹配事件,然后调用
    invalidate()
    调用
    ImageView
    s
    onDraw
    方法,点将随着用户手指的移动而移动。当用户从触摸或移动中抬起手指时,
    MotionEvent.ACTION\u UP
    被触发,您只需检查
    touchedDot==null
    ,如果是,则在他们触摸的
    x
    y
    处创建一个新的
    点,否则,您将设置
    touchedDot=null
    ,以便在下一个移动或触摸事件中重置它

  • 下面是我创建的一个示例,用于将图像加载到自定义
    ImageView

    build.gradle:

    dependencies {
        ...
        implementation 'com.squareup.picasso:picasso:2.71828'
    }
    
    <uses-permission android:name="android.permission.INTERNET" />
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    import java.util.ArrayList;
    
    public class DrawableDotImageView extends androidx.appcompat.widget.AppCompatImageView implements View.OnTouchListener {
    
        private final ArrayList<Dot> dots = new ArrayList<>();
        private Paint dotPaint;
        private Dot touchedDot;
    
        public DrawableDotImageView(@NonNull Context context) {
            super(context);
            setup();
        }
    
        public DrawableDotImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            setup();
        }
    
        public DrawableDotImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            setup();
        }
    
        private void setup() {
            setOnTouchListener(this);
            dotPaint = new Paint();
            dotPaint.setColor(Color.WHITE);
            dotPaint.setAlpha(100);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            dots.forEach((dot) -> {
                canvas.drawCircle(dot.getX(), dot.getY(), dot.getRadius(), dotPaint);
                Log.d("ImageView", "Drawing X: " + dot.x + " Y: " + dot.y);
            });
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    dots.forEach((dot) -> {
                        if (dot.isInside(event.getX(), event.getY())) {
                            touchedDot = dot;
                            Log.d("ImageView", "Dot touched");
                        }
                    });
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (touchedDot != null) {
                        touchedDot.x = event.getX();
                        touchedDot.y = event.getY();
                        invalidate();
                        Log.d("ImageView", "Dot moving X: " + touchedDot.x + " Y: " + touchedDot.y);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (touchedDot != null) {
                        touchedDot = null;
                    } else {
                        dots.add(new Dot(event.getX(), event.getY(), 35));
                        invalidate();
                        Log.d("ImageView", "Dot created X: " + event.getX() + " Y: " + event.getY());
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    break;
                default:
                    break;
            }
            return true;
        }
    
        private static class Dot {
            private float x;
            private float y;
            private final float radius;
    
            public Dot(float x, float y, float radius) {
                this.x = x;
                this.y = y;
                this.radius = radius;
            }
    
            public float getX() {
                return x;
            }
    
            public float getY() {
                return y;
            }
    
            public float getRadius() {
                return radius;
            }
    
            //https://www.geeksforgeeks.org/find-if-a-point-lies-inside-or-on-circle/
            public boolean isInside(float x, float y) {
                return (getX() - x) * (getX() - x) + (getY() - y) * (getY() - y) <= radius * radius;
            }
        }
    }
    
    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        DrawableDotImageView imageView = view.findViewById(R.id.imageView);
        Picasso.get().load("https://i.pinimg.com/originals/d4/d8/a0/d4d8a016155f00165411066bb9a0ab42.jpg").into(imageView);
    }
    
    AndroidManifest.xml:

    dependencies {
        ...
        implementation 'com.squareup.picasso:picasso:2.71828'
    }
    
    <uses-permission android:name="android.permission.INTERNET" />
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    import java.util.ArrayList;
    
    public class DrawableDotImageView extends androidx.appcompat.widget.AppCompatImageView implements View.OnTouchListener {
    
        private final ArrayList<Dot> dots = new ArrayList<>();
        private Paint dotPaint;
        private Dot touchedDot;
    
        public DrawableDotImageView(@NonNull Context context) {
            super(context);
            setup();
        }
    
        public DrawableDotImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            setup();
        }
    
        public DrawableDotImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            setup();
        }
    
        private void setup() {
            setOnTouchListener(this);
            dotPaint = new Paint();
            dotPaint.setColor(Color.WHITE);
            dotPaint.setAlpha(100);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            dots.forEach((dot) -> {
                canvas.drawCircle(dot.getX(), dot.getY(), dot.getRadius(), dotPaint);
                Log.d("ImageView", "Drawing X: " + dot.x + " Y: " + dot.y);
            });
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    dots.forEach((dot) -> {
                        if (dot.isInside(event.getX(), event.getY())) {
                            touchedDot = dot;
                            Log.d("ImageView", "Dot touched");
                        }
                    });
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (touchedDot != null) {
                        touchedDot.x = event.getX();
                        touchedDot.y = event.getY();
                        invalidate();
                        Log.d("ImageView", "Dot moving X: " + touchedDot.x + " Y: " + touchedDot.y);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (touchedDot != null) {
                        touchedDot = null;
                    } else {
                        dots.add(new Dot(event.getX(), event.getY(), 35));
                        invalidate();
                        Log.d("ImageView", "Dot created X: " + event.getX() + " Y: " + event.getY());
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    break;
                default:
                    break;
            }
            return true;
        }
    
        private static class Dot {
            private float x;
            private float y;
            private final float radius;
    
            public Dot(float x, float y, float radius) {
                this.x = x;
                this.y = y;
                this.radius = radius;
            }
    
            public float getX() {
                return x;
            }
    
            public float getY() {
                return y;
            }
    
            public float getRadius() {
                return radius;
            }
    
            //https://www.geeksforgeeks.org/find-if-a-point-lies-inside-or-on-circle/
            public boolean isInside(float x, float y) {
                return (getX() - x) * (getX() - x) + (getY() - y) * (getY() - y) <= radius * radius;
            }
        }
    }
    
    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        DrawableDotImageView imageView = view.findViewById(R.id.imageView);
        Picasso.get().load("https://i.pinimg.com/originals/d4/d8/a0/d4d8a016155f00165411066bb9a0ab42.jpg").into(imageView);
    }
    
    产生:


    我需要在图像视图上添加8个点,可以通过图像缩放和缩放移动。有可能吗。这在
    setup()
    方法中非常简单,将初始的8个点添加到
    数组列表
    。2.若要放大和缩小,请参见能否编辑设置方法?我不明白你说的,我想要这个可绘制的点图像视图的缩放视图。我相信你可以自己编辑它并添加8行
    点。添加(新点(x,y,35))
    setup()
    中,其中x和y是您想要的坐标。至于链接,我的答案扩展了
    ImageView
    ,因此任何使用
    ImageView
    的示例都适用于
    DrawableDotImageView
    好的,谢谢您的帮助