Как нарисовать движущийся круг по нижней линии овала? - PullRequest
0 голосов
/ 08 ноября 2018

Мне нужно реализовать что-то вроде SeekBar. Я создал своего наследника класса из View. В котором я рисую овал на холсте. При прикосновении этот овал поднимается и опускается. Я не могу правильно рассчитать положение для точки (большой палец).

введите описание изображения здесь

вот мой код, но он уже много раз повторялся и перестал работать:

public class BalanceView extends View {
    private Paint ovalPaint;
    private Paint thumbPaint;
    private float ovalBottom = 0f;
    private Bitmap thumb;
    private RectF oval1;


    //params
    private int maxValue = 18;
    private float ovalPaintWidth = 2.0f;
    private float ovalHeight = 60f;
    //end params


    private float touchX = 0f;
    private float touchY = 0f;

    private float mUnreachedRadius;



    public BalanceView(Context context) {
        super(context);
        init(context, null);
    }

    public BalanceView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public BalanceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }



    private void init(Context ctx,  @Nullable AttributeSet attrs){
        if (attrs != null){

        }

        if (ovalPaint == null){
            ovalPaint = new Paint();
            ovalPaint.setAntiAlias(true);
            ovalPaint.setStrokeWidth(ovalPaintWidth);
            ovalPaint.setStyle(Paint.Style.STROKE);
            Shader shader = new SweepGradient(10, 10, new int[]{R.color.white, R.color.black, R.color.white}, null);
            ovalPaint.setShader(shader);
        }

        if (thumbPaint == null){
            thumbPaint = new Paint();
        }

        thumb = BitmapFactory.decodeResource(getResources(), R.drawable.move_point);
    }

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

        //refershPosition();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        paintOval(ovalPaint, canvas);


        float cos = computeCos(touchX, touchY);
        float y = calcYLocationInWheel(cos);

        Log.d("balance", "cos: " + cos + " y: " + y + " touchX: " + touchX + " touchY: " + touchY + "mUnreachedRadius: " + mUnreachedRadius) ;
        canvas.drawBitmap(thumb, touchX, y, thumbPaint);

        super.onDraw(canvas);
    }

    private void paintOval(Paint paint, @NonNull Canvas canvas){
        if (paint != null) {
            int right = getWidth() - 30;
            int left = (getWidth() - right) / 2;
            float top = ovalBottom - ovalHeight;

            oval1 = new RectF(left, top, right + left, ovalBottom);
            canvas.drawOval(oval1, paint);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getY() >= getTop() && event.getY() <= getBottom()) {
            touchY = event.getY();
        }
        if (event.getX() <= oval1.right - thumb.getWidth() && event.getX() >= oval1.left) {
            touchX = event.getX();
        }

        ovalBottom = touchY;
        invalidate();
        return super.dispatchTouchEvent(event);
    }

    private float computeCos(float x, float y) {
        float width = x - oval1.width() / 2;
        float height = y - oval1.height() / 2;
        float slope = (float) Math.sqrt(width * width + height * height);
        return height / slope;
    }

    private float calcYLocationInWheel(double cos) {
        return oval1.bottom * (float) cos;
    }

}

Я стараюсь так:

private float getY(float a, float b, float x){
       // return (float) (Math.pow(b, 2d) * ((Math.pow(a, 2d) - Math.pow(x, 2d)) / Math.pow(a, 2d)));
        return (float)
                ((Math.pow(b, 2d) / Math.pow(a, 2d)) * (Math.sqrt(b * b * (a * a - x * x))));
    }

Но данные неверны.

...