android: move a view on touch move (ACTION_MOVE) f

2019-08-18 22:25发布

I created a Draggable Circle. I want my circle to be draggable only if it is clicked inside using ACTION_DOWN and dragged using ACTION_MOVE.

It's working fine but not perfect. In some places inside circle it is not draggable. How could I improve isPointInside method and is there any improvements or suggestions.

public class CircleDraggingView extends View {

    private static final String TAG = "CustomDrawing";
    private float circleRadius = 180;
    boolean isDrawCalledFirstTime = true;
    boolean isAllowedToDrag = false;

    private float center_circle_X = 0;
    private float center_circle_Y = 0;

    private Paint circlePaint;

    public CircleDraggingView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setupPaint();
    }

    private void setupPaint() {
        circlePaint = new Paint();
        circlePaint.setColor(Color.BLACK);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeWidth(4);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeJoin(Paint.Join.ROUND);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        ///super.onDraw(canvas);
        if (isDrawCalledFirstTime) {
            center_circle_X = canvas.getWidth() / 2;
            center_circle_Y = canvas.getHeight() / 2;

            isDrawCalledFirstTime = false;
        }

        //Center Circle
        circlePaint.setColor(Color.BLACK);
        canvas.drawCircle(center_circle_X, center_circle_Y, circleRadius, circlePaint);

        Log.d(TAG, "onDraw:centerX= " + center_circle_X + " centerY= " + center_circle_Y );
    }

    private int getyPositionOfText(float yPositionOfText, Paint mPaint) {
        return (int) ((yPositionOfText) - ((mPaint.descent() + mPaint.ascent()) / 2));
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

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

                if(isPointInside(event.getRawX(),event.getRawY()))
                    isAllowedToDrag = true;
                Log.d(TAG, "ACTION_DOWN:getRawX= " + event.getRawX() + " getRawY= " + event.getRawY() + " getX= "
                        + event.getX() + " getY= " + event.getY());

                break;
                ///return true;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "ACTION_MOVE:getRawX= " + event.getRawX() + " getRawY= " + event.getRawY() + " getX= "
                        + event.getX() + " getY= " + event.getY());
                if(isAllowedToDrag){
                    center_circle_X = event.getRawX() ;
                    center_circle_Y = event.getRawY();
                    }/*this.animate().x(event.getRawX()).y(event.getRawY())
                            .setDuration(50).start();*/
                break;
            case MotionEvent.ACTION_UP:
                if(isAllowedToDrag)
                    isAllowedToDrag = false;
                break;
            default:
                return false;
        }
        // Force a view to draw again
        ///postInvalidate();
        invalidate();
        return true;
    }

    private boolean isPointInside(float pointX, float pointY) {
        float circleX = center_circle_X, circleY = center_circle_Y;

        //Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
        Double distance = Math.sqrt(Math.pow((pointX - circleX), 2) + Math.pow((pointY - circleY), 2));
        ////Double distance2 = Math.hypot(pointX-circleX, pointY-circleY);

        boolean isPointInside = true;
        if ((distance * distance) > (circleRadius * circleRadius))
            isPointInside = false;
        return isPointInside;
    }
}

Whether I need to save the lastX position in Action_Down and animate or translate it smoothly to newX,newY position (in Action_move) ?

0条回答
登录 后发表回答