Android Studio — как перетащить ImageView в точное положение

#java #android #touch-event #ontouchlistener

#java #Android #касание-событие #ontouchlistener

Вопрос:

итак, я создал приложение, которое используется bitmap в canvas качестве шаблона, и я хочу, чтобы пользователь мог добавлять изображения из галереи, а затем масштабировать, позиционировать и поворачивать. в настоящее время застрял в imageView правильном позиционировании, когда я перетаскиваю в другую позицию imageView , она немного отклоняется от позиции, в которую я поместил.

вот xml мой проект для демонстрации структуры макета:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".search.CreateActivity">

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        tools:layout_editor_absoluteX="283dp">

<!-- reault_layout contains layout and imageView:
layout for canvas the contains bitmap
layout for the image added by the user -->

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@ id/result_layout"
            android:layout_width="512dp"
            android:layout_height="512dp"
            android:orientation="vertical">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@ id/canvas_layout"
                android:layout_width="512dp"
                android:layout_height="512dp">

            </androidx.constraintlayout.widget.ConstraintLayout>

            <ImageView
                android:id="@ id/iv_promo"
                android:layout_width="100dp"
                android:layout_height="100dp"
                app:srcCompat="..."/>

        </androidx.constraintlayout.widget.ConstraintLayout>
    </HorizontalScrollView>

<!-- this button to add the image -->
    <Button
        android:id="@ id/add_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

<!-- this button saves whatever in the result layout as image in internal storage-->
    <Button
        android:id="@ id/save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>
 

другая проблема заключается в том, imageView что при прокрутке изображение не может быть помещено в крайнем правом углу, оно размещается только в видимой области экрана перед прокруткой.

Я установил ширину и высоту макета холста на 512dp, потому что его фактическое значение для рисования равно 512dpx512dp, и если я установлю для него значение match_parent, может стать меньше и сложнее размещать небольшие изображения в определенных областях внутри шаблона.

Для отрисовки шаблона я поместил эти две строки внутрь onCreate();

 create_canvas = new CreateCanvas(this);
nCanvas_layout.addView(create_canvas);
 

Я не использовал setContentView(); , чтобы не рисовать шаблон на всем макете, поэтому он будет отображаться внутри canvas_layout

вот CreateCanvas класс, который рисует шаблон:

 public class CreateCanvas extends View {

    Drawable temp_drawable
    Bitmap temp_bitmap

    public CreateCanvas(Context context) {
        super(context);
        this.context = context;

        // DRAWABLE OF THE TEMPLATE
        temp_drawable = ContextCompat.getDrawable(context, R.drawable.ic_template_master);

    }
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
     //drawableToBitmap() IS A CUSTOM METHOD TO CONVERT THE DRAWABLE TEMPLATE TO BITMAP
    // RETURNS BITMAP
        temp_bitmap = drawableToBitmap(temp_drawable);

   // DRAWS THE TEMPLATE INTO CANVAS
        canvas.drawBitmap(temp_bitmap, left, top, null);
    }

// THE CUSTOM METHOD TO CONVERT DRAWABLE TO BITMAP
public Bitmap drawableToBitmap(Drawable drawable) {

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable)drawable).getBitmap();
        }
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),  drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);

        bitmap.setHeight(getWidth());
        bitmap.setWidth(getWidth());
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
    
        return bitmap;
    }
}
 

приведенный выше класс помогает в создании шаблона canvas_layout , ниже canvas_layout есть imageView место, где пользователь может загрузить изображение из внутреннего хранилища.

Я добавил их implements , чтобы получать события касания пользователя implements View.OnTouchListener, View.OnDragListener, GestureDetector.OnGestureListener

затем получил эти @overrides методы:

 @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
            // the imageView that host the image added by user: iv_promo
               if (view.getId() == R.id.iv_promo)
               {
                   nGestureDetector.onTouchEvent(motionEvent);
                   return true;
               }

               return true;
           }

@Override
    public boolean onDown(MotionEvent motionEvent) {return false;}

    @Override
    public void onShowPress(MotionEvent motionEvent) {}

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {return false;}

    @Override
    public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {return false;}

    @Override
    public void onLongPress(MotionEvent motionEvent) {

        View.DragShadowBuilder builder = new View.DragShadowBuilder(nIv_promo);
        nIv_promo.startDragAndDrop(null, builder, null, 0);
        builder.getView().setOnDragListener(this);
    }

    @Override
    public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {return false;}

    @Override
    public boolean onDrag(View view, DragEvent dragEvent) {
 
   // I was trying thses outside if-statment to check if its working, but did not work
        //nIv_promo.setX(dragEvent.getX()-(nIv_promo.getWidth()/2f));
        //nIv_promo.setY(dragEvent.getY()-(nIv_promo.getHeight()/2f));

        if (dragEvent.getAction() == DragEvent.ACTION_DRAG_STARTED)
        {
            // . . .
        }
        if (dragEvent.getAction() == DragEvent.ACTION_DRAG_ENTERED)
        {
           // . . . 
        }
        if (dragEvent.getAction() == DragEvent.ACTION_DRAG_LOCATION)
        {

            //nIv_promo.setX(dragEvent.getX());
            //nIv_promo.setY(dragEvent.getY());
        }
        if (dragEvent.getAction() == DragEvent.ACTION_DRAG_EXITED)
        {
           // . . .
        }
        if (dragEvent.getAction() == DragEvent.ACTION_DROP)
        {
          // . . .
        }
        if (dragEvent.getAction() == DragEvent.ACTION_DRAG_ENDED)
        {
                nIv_promo.setX(dragEvent.getX()-(nIv_promo.getWidth()/2f));
                nIv_promo.setY(dragEvent.getY()-(nIv_promo.getHeight()/2f));
        }
        return true;
    }
 

Мне не понравился DragShadowBuilder(), я хотел перетащить фактический ImageView
и переместить в другую позицию на экране. но я слишком поглощен точным размещением ImageView. если возможно, пожалуйста, помогите мне с этим тоже