onTouchEvent на Android настраиваемый вид не работает, если созданы 2 настраиваемых представления - PullRequest
0 голосов
/ 18 июня 2020

Моя цель - нарисовать 3 равных пользовательских представления в Activity. Пользовательское представление переопределяет onTouchEvent. Если я добавлю только одно настраиваемое представление в Activity, XML или программно, все будет работать нормально. Если я добавлю 2 настраиваемых представления (один и тот же настраиваемый вид), событие касания работает только для одного настраиваемого представления, другое фиксируется в макете и вообще ничего не перехватывает. Я видел другие обсуждения, но не могу найти проблему. Мой собственный класс представления:

 public class IconCropView extends View {

//contants strings
private static final String TAG = "IconCropView";
private static final int TEXT_COLOR = Color.RED;
private static final float TEXT_SIZE = 30.0f;
private static final float STROKE_WIDTH = 4.0f;
//drawing objects
private Paint paint;
//text
private Paint textPaint;

//point objects
private Point[] points;
private Point start;
private Point offset;

//variable ints
private int altezzaMinima;
private int altezza;
private int halfCorner;
private int cornerColor;
private int edgeColor;
private int outsideColor;
private int corner = 30;

//variable booleans
private boolean initialized = false;

//drawables
private Drawable moveDrawable;
private Drawable  resizeDrawable2;
//context
Context context;

//Rect del canvas
Rect cropBorder;
boolean clickInCropRect;

public IconCropView(Context context) {
    super(context);
    this.context = context;
    init(null,null);
}

public IconCropView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    init(attrs,null);
}

public IconCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.context = context;
    init(attrs,null);
}
public IconCropView(Context context, Point[] punti) {
    super(context);
    this.context = context;
    init(null,punti);
}


private void init(@Nullable AttributeSet attrs,Point[] punti ){


    paint = new Paint();
    start = new Point();
    offset = new Point();

    //initial dimensions
    altezzaMinima = 400;
    altezza = altezzaMinima;
    halfCorner = 25;

    //colors
    cornerColor = Color.BLACK;
    edgeColor = Color.WHITE;
    outsideColor =Color.parseColor("#00000088");

    //initialize corners;
    points = new Point[4];

    points[0] = new Point();
    points[1] = new Point();
    points[2] = new Point();
    points[3] = new Point();

    if(punti == null) {
        //init corner locations;
        //top left
        points[0].x = 0;
        points[0].y = 0;

        //top right
        points[1].x = 600;
        points[1].y = 0;

        //bottom left
        points[2].x = 0;
        points[2].y = altezzaMinima;

        //bottom right
        points[3].x = 600;
        points[3].y = altezzaMinima;
    }
    if(punti != null){
        //init corner locations;
        //top left

        points[0].x = punti[0].x;
        points[0].y = punti[0].y;

        //top right
        points[1].x = punti[1].x;
        points[1].y = punti[1].y;

        //bottom left
        points[2].x = punti[2].x;
        points[2].y = punti[2].y;

        //bottom right
        points[3].x = punti[3].x;
        points[3].y = punti[3].y;
    }
    //init drawables

    resizeDrawable2 = getResources().getDrawable(R.drawable.circle);

    //set initialized to true
    initialized = true;

    //inizializzo testo
    textPaint = new Paint();
    textPaint.setColor(TEXT_COLOR);
    textPaint.setTextSize(TEXT_SIZE);

}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //set paint to draw edge, stroke
    if(initialized) {
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setColor(edgeColor);
        paint.setStrokeWidth(4);
        cropBorder = new Rect(points[0].x + halfCorner, points[0].y + halfCorner,points[0].x + halfCorner + 500,points[0].y + halfCorner + altezza);
        //crop rectangle
        canvas.drawRect(cropBorder, paint);
        //set paint to draw outside color, fill
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(outsideColor);
        resizeDrawable2.setBounds(points[2].x, points[2].y, points[2].x + halfCorner*2, points[2].y + halfCorner*2);
        //place corner drawable
        resizeDrawable2.draw(canvas);

    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    //return super.onTouchEvent(event);

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

            //get the coordinates
            start.x = (int)event.getX();
            start.y = (int)event.getY();

            //get the corner touched if any
            corner = getCorner(start.x, start.y);

            //get the offset of touch(x,y) from corner top-left point
            offset = getOffset(start.x, start.y, corner);

            //account for touch offset in starting point
            start.x = start.x - offset.x;
            start.y = start.y - offset.y;

            // dentro il rettangolo
            clickInCropRect = cropBorder.contains( start.x, start.y);
            break;

        }
        case MotionEvent.ACTION_MOVE:{
            if(corner == 0 || clickInCropRect ) {
                points[0].x = Math.max(points[0].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[0].x - 2*halfCorner - (cropBorder.width()))), 0);
                points[1].x = Math.max(points[1].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[1].x - 2*halfCorner)), altezza);
                points[2].x = Math.max(points[2].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[2].x - 2*halfCorner - (cropBorder.width()))), 0);
                points[3].x = Math.max(points[3].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[3].x - 2*halfCorner)), altezza);

                points[0].y = Math.max(points[0].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[0].y - 2*halfCorner - (cropBorder.height()) )), 0);
                points[1].y = Math.max(points[1].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[1].y - 2*halfCorner - (cropBorder.height()))), 0);
                points[2].y = Math.max(points[2].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[2].y - 2*halfCorner)), altezza);
                points[3].y = Math.max(points[3].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[3].y - 2*halfCorner)), altezza);

                start.x = points[0].x+(cropBorder.width()/2);
                start.y = points[0].y+(cropBorder.height()/2);
                Log.v("TOUCHED", points[0].x + " ");

                invalidate();

            }
            else if (corner == 2){
                altezza =  Math.min((Math.min((Math.max(altezzaMinima, (int)(altezza + Math.floor(event.getY()) - start.y - offset.y))), altezza + (getHeight() - points[2].y - 2* halfCorner ))), altezza + (getWidth() - points[1].x - 2* halfCorner ));
                points[2].y = points[0].y + altezza;
                points[3].y = points[0].y + altezza;
                points[3].x = points[0].x + altezza;
                points[1].x = points[0].x + altezza;
                start.y = points[2].y;
                invalidate();


            }
            break;

        }

    }
    return true;
}

private int getCorner(float x, float y){
    int corner = 5;
    for (int i = 0; i < points.length; i++){
        float dx = x - points[i].x;
        float dy = y - points[i].y;
        int max = halfCorner * 2;
        if(dx <= max && dx >= 0 && dy <= max && dy >= 0){
            return i;
        }
    }
    return corner;
}

private Point getOffset(int left, int top, int corner){
    Point offset = new Point();
    if(corner == 5){
        offset.x = 0;
        offset.y = 0;
    }else{
        offset.x = left - points[corner].x;
        offset.y = top - points[corner].y;
    }
    return offset;
}

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

  }

В действии onCreate:

    IconCropView iconCrop1 = new IconCropView(context);
    IconCropView iconCrop2 = new IconCropView(context,punti);
    RelativeLayout myLayout = findViewById(R.id.myLayout);
    myLayout .addView(iconCrop1);
    myLayout .addView(iconCrop2);

Я поместил их также в файл XML, но результат тот же.

Буду признателен за вашу помощь.

Всем спасибо.

1 Ответ

0 голосов
/ 03 июля 2020

Я решил проблему. Проблема была не в onTouchEvent, а в контейнере, в котором был определен IconCropView. Раньше я просто определял элемент и добавлял его в макет. Теперь, на мой взгляд, правильный способ:

  1. Определить макет, в котором создается IconCropView. Он должен быть больше, чем IconCropview, иначе он не может перемещаться касанием:

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams (mImageViewWidth, mImageViewHeight / 4);

Определите поля IconCropView, связанные с его контейнером.

params.setMargins (marginLeft, marginTop, marginRight, marginBottom);

3) Создайте новый IconCropView и добавьте его в родительский макетная деятельность. Mlayout - это основной макет активности:

IconCropView cropView = new IconCropView(context, width, height);

cropView .setLayoutParams(params);

mLayout.addView(cropView);

Надеюсь, это может быть кому-то полезно.

...