Сделать круг холста Draggable в android

export PATH=$PATH:~/.config/composer/vendor/bin работает только для текущего сеанса. В ~/.profile и ~/.bashrc ~/ не работает в кавычках, либо опускайте кавычки, либо используйте $HOME вместо ~/, например.
export PATH=$PATH:$HOME/.config/composer/vendor/bin
/etc/environment не допускает никакого синтаксиса оболочки, поэтому ни ~/, ни $HOME не работают. Вместо этого вам нужно использовать полный путь, например.
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/youruser/.config/composer/vendor/bin"
0
задан 13 August 2018 в 15:18

1 ответ

Кажется, что у вас могут возникнуть проблемы с обработкой multi-touch / drawing.

На этом я смог создать пример, который, как я думаю, очень похож на тот, который вы пытаетесь достичь (без полного рисования круга). - круги генерируются одним касанием):

   public class CirclesDrawingView extends View {

private static final String TAG = "CirclesDrawingView";

/** Main bitmap */
private Bitmap mBitmap = null;

private Rect mMeasuredRect;

/** Stores data about single circle */
private static class CircleArea {
    int radius;
    int centerX;
    int centerY;

    CircleArea(int centerX, int centerY, int radius) {
        this.radius = radius;
        this.centerX = centerX;
        this.centerY = centerY;
    }

    @Override
    public String toString() {
        return "Circle[" + centerX + ", " + centerY + ", " + radius + "]";
    }
}

/** Paint to draw circles */
private Paint mCirclePaint;

private final Random mRadiusGenerator = new Random();
// Radius limit in pixels
private final static int RADIUS_LIMIT = 100;

private static final int CIRCLES_LIMIT = 3;

/** All available circles */
private HashSet<CircleArea> mCircles = new HashSet<CircleArea>(CIRCLES_LIMIT);
private SparseArray<CircleArea> mCirclePointer = new SparseArray<CircleArea>(CIRCLES_LIMIT);

/**
 * Default constructor
 *
 * @param ct {@link android.content.Context}
 */
public CirclesDrawingView(final Context ct) {
    super(ct);

    init(ct);
}

public CirclesDrawingView(final Context ct, final AttributeSet attrs) {
    super(ct, attrs);

    init(ct);
}

public CirclesDrawingView(final Context ct, final AttributeSet attrs, final int defStyle) {
    super(ct, attrs, defStyle);

    init(ct);
}

private void init(final Context ct) {
    // Generate bitmap used for background
    mBitmap = BitmapFactory.decodeResource(ct.getResources(), R.drawable.up_image);

    mCirclePaint = new Paint();

    mCirclePaint.setColor(Color.BLUE);
    mCirclePaint.setStrokeWidth(40);
    mCirclePaint.setStyle(Paint.Style.FILL);
}

@Override
public void onDraw(final Canvas canv) {
    // background bitmap to cover all area
    canv.drawBitmap(mBitmap, null, mMeasuredRect, null);

    for (CircleArea circle : mCircles) {
        canv.drawCircle(circle.centerX, circle.centerY, circle.radius, mCirclePaint);
    }
}

@Override
public boolean onTouchEvent(final MotionEvent event) {
    boolean handled = false;

    CircleArea touchedCircle;
    int xTouch;
    int yTouch;
    int pointerId;
    int actionIndex = event.getActionIndex();

    // get touch event coordinates and make transparent circle from it
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            // it's the first pointer, so clear all existing pointers data
            clearCirclePointer();

            xTouch = (int) event.getX(0);
            yTouch = (int) event.getY(0);

            // check if we've touched inside some circle
            touchedCircle = obtainTouchedCircle(xTouch, yTouch);
            touchedCircle.centerX = xTouch;
            touchedCircle.centerY = yTouch;
            mCirclePointer.put(event.getPointerId(0), touchedCircle);

            invalidate();
            handled = true;
            break;

        case MotionEvent.ACTION_POINTER_DOWN:
            Log.w(TAG, "Pointer down");
            // It secondary pointers, so obtain their ids and check circles
            pointerId = event.getPointerId(actionIndex);

            xTouch = (int) event.getX(actionIndex);
            yTouch = (int) event.getY(actionIndex);

            // check if we've touched inside some circle
            touchedCircle = obtainTouchedCircle(xTouch, yTouch);

            mCirclePointer.put(pointerId, touchedCircle);
            touchedCircle.centerX = xTouch;
            touchedCircle.centerY = yTouch;
            invalidate();
            handled = true;
            break;

        case MotionEvent.ACTION_MOVE:
            final int pointerCount = event.getPointerCount();

            Log.w(TAG, "Move");

            for (actionIndex = 0; actionIndex < pointerCount; actionIndex++) {
                // Some pointer has moved, search it by pointer id
                pointerId = event.getPointerId(actionIndex);

                xTouch = (int) event.getX(actionIndex);
                yTouch = (int) event.getY(actionIndex);

                touchedCircle = mCirclePointer.get(pointerId);

                if (null != touchedCircle) {
                    touchedCircle.centerX = xTouch;
                    touchedCircle.centerY = yTouch;
                }
            }
            invalidate();
            handled = true;
            break;

        case MotionEvent.ACTION_UP:
            clearCirclePointer();
            invalidate();
            handled = true;
            break;

        case MotionEvent.ACTION_POINTER_UP:
            // not general pointer was up
            pointerId = event.getPointerId(actionIndex);

            mCirclePointer.remove(pointerId);
            invalidate();
            handled = true;
            break;

        case MotionEvent.ACTION_CANCEL:
            handled = true;
            break;

        default:
            // do nothing
            break;
    }

    return super.onTouchEvent(event) || handled;
}

/**
 * Clears all CircleArea - pointer id relations
 */
private void clearCirclePointer() {
    Log.w(TAG, "clearCirclePointer");

    mCirclePointer.clear();
}

/**
 * Search and creates new (if needed) circle based on touch area
 *
 * @param xTouch int x of touch
 * @param yTouch int y of touch
 *
 * @return obtained {@link CircleArea}
 */
private CircleArea obtainTouchedCircle(final int xTouch, final int yTouch) {
    CircleArea touchedCircle = getTouchedCircle(xTouch, yTouch);

    if (null == touchedCircle) {
        touchedCircle = new CircleArea(xTouch, yTouch, mRadiusGenerator.nextInt(RADIUS_LIMIT) + RADIUS_LIMIT);

        if (mCircles.size() == CIRCLES_LIMIT) {
            Log.w(TAG, "Clear all circles, size is " + mCircles.size());
            // remove first circle
            mCircles.clear();
        }

        Log.w(TAG, "Added circle " + touchedCircle);
        mCircles.add(touchedCircle);
    }

    return touchedCircle;
}

/**
 * Determines touched circle
 *
 * @param xTouch int x touch coordinate
 * @param yTouch int y touch coordinate
 *
 * @return {@link CircleArea} touched circle or null if no circle has been touched
 */
private CircleArea getTouchedCircle(final int xTouch, final int yTouch) {
    CircleArea touched = null;

    for (CircleArea circle : mCircles) {
        if ((circle.centerX - xTouch) * (circle.centerX - xTouch) + (circle.centerY - yTouch) * (circle.centerY - yTouch) <= circle.radius * circle.radius) {
            touched = circle;
            break;
        }
    }

    return touched;
}

@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    mMeasuredRect = new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight());
}
 }

Активность содержит только setContentView (R.layout.main) там main.xml:

  <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/scroller">
<com.example.TestApp.CirclesDrawingView
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

0
ответ дан 15 August 2018 в 17:01

Другие вопросы по тегам:

Похожие вопросы: