I found a sample code with the implementation of Drag & Drop, almost understood everything, there were some unclear points.
There is a container (ImageView4) and 3 images (ImageView1-3). We can capture and drag any of the three pictures. If, when released, it turns out that the picture is above the container, then it will remain in it, otherwise it will return to its initial position.
MainActivity.java
public class MainActivity extends Activity implements OnTouchListener { View selectedItem = null; int offSetX = 0; int offSetY = 0; boolean touchFlag = false, dropFlag= false; android.view.ViewGroup.LayoutParams imageParams; ImageView imageView4, imageView1, imageView2, imageView3; int ex, ey; int topY, leftX, rightX, bottomY; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("MyLog", "onCreate begin"); this.requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); View root = findViewById(android.R.id.content).getRootView(); imageView1 = (ImageView) findViewById(R.id.imageView1); imageView2 = (ImageView) findViewById(R.id.imageView2); imageView3 = (ImageView) findViewById(R.id.imageView3); imageView4 = (ImageView) findViewById(R.id.imageView4); root.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.d("MyLog", "onCreate onTouch begin"); if (touchFlag) { Log.d("MyLog", "onCreate onTouch if begin"); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: Log.d("MyLog", "onCreate ACTION_DOWN begin"); //определяем коордынаты прямоугольника topY = imageView4.getTop(); leftX = imageView4.getLeft(); rightX = imageView4.getRight(); bottomY = imageView4.getBottom(); Log.d("MyLog", "onCreate ACTION_DOWN end"); break; case MotionEvent.ACTION_UP: Log.d("MyLog", "onCreate ACTION_UP begin"); touchFlag = false; if (dropFlag) { dropFlag = false; } else { selectedItem.setLayoutParams(imageParams); } Log.d("MyLog", "onCreate ACTION_DOWN end"); break; case MotionEvent.ACTION_MOVE: Log.d("MyLog", "onCreate ACTION_MOVE begin"); ex = (int) event.getX(); ey = (int) event.getY(); int x = (int) event.getX()-offSetX; int y = (int) event.getY()-offSetY; Log.d("MyLogs", "ex = " + ex + " ey = " + ey); Log.d("MyLogs", "x = " + x + " y = " + y); //int w = getWindowManager().getDefaultDisplay().getWidth()-50; //int y = getWindowManager().getDefaultDisplay().getWidth()-50; DisplayMetrics disp = new DisplayMetrics();//метод позволяет узнать размеры экрана getWindowManager().getDefaultDisplay().getMetrics(disp); int screenWi = disp.widthPixels; int screenHei = disp.heightPixels; if (x > screenWi) { x = screenWi; } if (y > screenHei) { y = screenHei; } RelativeLayout.LayoutParams il = new RelativeLayout.LayoutParams( new ViewGroup.MarginLayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); il.setMargins(x, y, 0, 0); //проверка что отпустили картинку в пределах прямоугольника if(ex>leftX && ex<rightX && ey>topY&&ey<bottomY) { imageView4.setBackgroundColor(Color.RED); selectedItem.bringToFront(); dropFlag = true; } else { imageView4.setBackgroundColor(Color.BLUE); } selectedItem.setLayoutParams(il); Log.d("MyLog", "onCreate ACTION_MOVE end"); break; } Log.d("MyLog", "onCreate onTouch if end"); } Log.d("MyLog", "onCreate onTouch end"); return true; } }); imageView1.setOnTouchListener(this); imageView2.setOnTouchListener(this); imageView3.setOnTouchListener(this); Log.d("MyLog", "onCreate end"); } @Override public boolean onTouch(View v, MotionEvent event) { Log.d("MyLog", "onTouch begin"); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: Log.d("MyLog", "onTouch ACTION_DOWN begin"); touchFlag = true; offSetX = (int) event.getX(); offSetY = (int) event.getY(); selectedItem = v; imageParams = v.getLayoutParams(); Log.d("MyLogs", "offSetX = " + offSetX + " offSetY = " + offSetY); Log.d("MyLog", "onTouch ACTION_DOWN end"); break; case MotionEvent.ACTION_UP: Log.d("MyLog", "onTouch ACTION_UP begin"); selectedItem = null; touchFlag = false; Log.d("MyLog", "onTouch ACTION_UP end"); break; default: break; } Log.d("MyLog", "onTouch end"); return false; } } activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView4" android:layout_width="300dp" android:layout_height="200dp" android:layout_alignParentBottom="true" android:src="@drawable/p4" /> <ImageView android:id="@+id/imageView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/p2" android:layout_alignParentRight="true" /> <ImageView android:id="@+id/imageView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/p3" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:src="@drawable/p1" /> </RelativeLayout> Everything is simple, the only thing is whether I understand correctly that due to the fact that the OnTouch method returns false, we inform the system that this method did not work completely or incorrectly, and therefore the processing of this event should be entrusted to another handler, so she entrusts it The case for the "touch handler for the whole window" that we created already in onCreate ??
First, the handler is specifically created for our image , and then the "handler for the whole window . "
If this is so, then why then when we release the finger, then the "handler for the whole window" immediately works, why not in the same way as with ACTION_DOWN ? Checked by logs.