[Android] View touch operation - MotionEvent

 introduce

For any operation on the screen, the system will create a touch event object MotionEvent to deal with this operation. When you click on a certain view of the mobile phone screen, the screen is first sensed, because the Activity system is a layered structure, and the bottom layer is some drivers, so the driver will get information and transmit the information to the clicked application, and then the application will Hand it over to the Activity, which uses the MotionEvent object to realize the touch operation of the view, then let's learn how the MotionEvent object realizes the touch operation of the view.


1. The operation type of the event

Under normal circumstances, a finger touching the screen will cause a series of click events. The MotionEvent object has a variable action to reflect the operation type of this series of click events, so we can get the current click through the value of the action variable of the MotionEvent object. state.

  • When the finger is pressed , the value of action is equal to ACTION_DOWN , equal to 0
  • When the finger moves on the screen , the value of action is equal to ACTION_MOVE , equal to 2
  • The finger leaves the screen, the value of action is equal to ACTION_UP , which is equal to 1

There are two situations for a simple interaction process of single touch:

  • When the finger is pressed and left immediately, the value of action changes from 0->1
  • Press the finger, move a certain distance on the screen and then leave the screen, the value of action changes to 0->2->...->2->1


2. Transmission, consumption and processing of MotionEvent

Three important methods of event distribution :

       1. dispatchTouchEvent() method : It will distribute events to sub-Views layer by layer starting from Activity until there are no sub-Views. (When distributing, the View can only be distributed to the child View, and the View cannot be distributed to the grandson View)

        2. onTouchEvent() method : After the dispatchTouchEvent() method is called to the bottom View, it will call back layer by layer from the bottom View. If the onTouchEvent method of a certain View returns true, it will stop calling back upwards. .

        3. onInterceptTouchEvent method : with the existence of the dispatchTouchEvent() method, its function is to intercept ViewGroup events and prevent it from continuing to distribute events downwards.

The main methods of Activity, View, ViewGroup and MotionEvent:

Activity:

dispatchTouchEvent(ev: MotionEvent?): Boolean Distribute events
onTouchEvent(ev: MotionEvent?): Boolean callback for handling events

View:

dispatchTouchEvent(ev: MotionEvent?): Boolean Distribute events
onTouchEvent(ev: MotionEvent?): Boolean callback for handling events
setOnTouchListener(l:OnTouchListener) Set up event listeners
setOnClickListener(l:OnClickListener) Set click listener
setOnLongClickListener(l:OnClickListener) Set up long press monitoring
setOnCreateContextMenuListener(l:OnCreateContextMenuListener) for creating menus

Note: The onTouch() event in OnTouchListener has a higher priority than the onTouchEvent() event. If the return result of onTocuh() is true, the onTouchEvent() event of the View will not be called.

ViewGroup:

dispatchTouchEvent(ev: MotionEvent?): Boolean Distribute events
onInterceptTouchEvent(ev: MotionEvent?): Boolean
Intercept event

Note: The onInterceptTouchEvent method can only be rewritten in ViewGroup.

MotionEvent:

At the same time, we can get the x and y axis coordinates of the click event through the MotionEvent object.

The methods provided by the system are as follows:

getX() Get the x-axis coordinate of the event (relative to the current view)
getY() Get the y-axis coordinate of the event (relative to the current view)
getRawX() Get the x-axis coordinate of the event (relative to the left vertex of the screen)
getRawY() Get the y-axis coordinate of the event (relative to the left vertex of the screen)

 Let's understand the transmission, consumption and processing of MotionEvent

As shown in the figure, when the click event is generated, the event will first be passed to the current Activtiy, and the Activity will call the distribution event method dispatchTouchEvent to pass the event to the largest View, and then pass it down to the sub-View layer by layer until it passes Go to the smallest view, call the onTouchEvent method of the smallest view, and pass it up until a view's onTouchEvent method returns true, consume this click event, and will not pass it up after consuming this click event. If not, then the event will eventually be consumed by the activity.

In layman's terms: grandpa (Activity) got an apple (click event), grandpa gave the apple to dad (View), dad gave me the apple (sub-View), if I choose not to eat the apple, then I will eat the apple Give it to Dad. If Dad chooses to eat the apple, he will consume the apple. If Dad chooses not to eat the apple, he will give the apple to Grandpa. Grandpa can only eat the apple, and it is over.

Deepen understanding of MotionEvent delivery, consumption, and processing through code

When View's onTouch and onTouchEvent methods both return false

Click the View once, and the click event generated is as follows:

Click View and move, and the click event generated is as follows:

In the end, the Activity consumes the click event.

When View's onTouch method returns true:

Click the View once, and the click event generated is as follows:

 

 Click View and move, and the click event generated is as follows:

In the end, the View consumes the click event, and it can be seen that the onTouch() event in OnTouchListener has a higher priority than the onTouchEvent() event. If the return result of onTocuh() is true, then the onTouchEvent() event of the View will not is called.

Small projects

First look at the renderings:

 

  • Functional description

            Drag the picture by moving your finger

           The control picture cannot exceed the display area of ​​the screen

  • technical point

         MotionEvent handling

         Dynamic positioning of View (layout)

code:

class MainActivity : AppCompatActivity(),View.OnTouchListener{
    var lastX=0
    var lastY=0
    lateinit var imageView: ImageView
    lateinit var parentView:RelativeLayout
    var maxRight=0
    var maxBottom=0
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        imageView=findViewById(R.id.imageView4)
        parentView=imageView.parent as RelativeLayout
        imageView.setOnTouchListener(this)
    }
    override fun onTouch(p0: View?, event: MotionEvent): Boolean {
        val eventX=event.rawX
        val eventY=event.rawY
        when(event.action){
            MotionEvent.ACTION_DOWN->{
                if(maxRight==0){
                    maxRight=parentView.right
                    maxBottom=parentView.bottom
                }
                lastX= eventX.toInt()
                lastY=eventY.toInt()}
            MotionEvent.ACTION_MOVE->{
                var dx:Int=(eventX-lastX).toInt()
                var dy:Int=(eventY-lastY).toInt()
                var left=imageView.left+dx
                var top=imageView.top+dy
                var right=imageView.right+dx
                var bottom=imageView.bottom+dy
                //限制left>=0
                if(left<0){
                    right+=-left
                    left=0
                }
                //限制top>=0
                if(top<0){
                    bottom+=-top
                    top=0
                }
                //限制right<maxRight
                if(right>maxRight){
                    left-=right-maxRight
                    right=maxRight
                }
                //限制bottom>=0
                if(bottom>maxBottom){
                    top-=bottom-maxBottom
                    bottom=maxBottom
                }
                imageView.layout(left, top, right, bottom)
                lastX=eventX.toInt()
                lastY=eventY.toInt()
            }
        }
        return true
    }
}

Guess you like

Origin blog.csdn.net/weixin_63357306/article/details/128472539