Android controls capture the range of click events

Source: Internet
Author: User

The location of the click event in the Tween animation of the view does not change because the location of the animation changes, because the position of the layout is virtually unchanged during the animation process, so it was once thought that the click event of the view (in fact, not just the Click event, Including all touch events) The range that is triggered is the left,top,right,bottom specified by the view at layout time. It's not exactly what we found today. Everything is because the usual look at the code is not carefully caused by the understanding of the problem is not comprehensive.

Here is a record of the process of discovering problems and dealing with them.


Customize such a viewgroup,layout two linear layouts, the left LinearLayout covers the full screen, the right side of the linearlayout is hidden outside the screen. Then observe in the process of wanting to do the sliding, the second linearlayout shows the position information of the button buttons and the second linear layout in the process:


As you can see, in the process of showing the second linear cloth to the left, his position has not changed, and this refers to the passage of getLeft (),getTop () , GetRight (),getbottom () the position obtained, that is, the position determined by layout .

Since the location has not changed, then clicking on the second linear Layout and button Click event is also a response, which means that the location of the capture click event is not entirely in the layout position. Because the hand is not stretched out to the screen to click ...


Look back at the Viewgroup#dispatchtouchevent method when distributing touch events:

for (int i = count-1; I >= 0; i--) {    final View child = Children[i];    if (child.mviewflags & visibility_mask) = = VISIBLE            | | child.getanimation () = null) {        Child.gethitrect ( frame);        if (Frame.contains (Scrolledxint, Scrolledyint)) {            //offset the event to the view ' s coordinate system            final float XC = Scrolledxfloat-child.mleft;            Final float YC = scrolledyfloat-child.mtop;            Ev.setlocation (XC, YC);            Child.mprivateflags &= ~cancel_next_up_event;            if (child.dispatchtouchevent (EV))  {                //Event handled, we have a target now.                Mmotiontarget = child;                return true;            }        

Where the Frame.contains (scrolledxint, scrolledyint) function is the judgment Point (Scrolledxint,scrolledyint) is not inside the frame rectangle. This rectangular frame is made up of child.gethitrect (frame);

    public void Gethitrect (Rect outrect) {        outrect.set (mleft, Mtop, Mright, Mbottom);}

Obviously, this rectangle is determined by the layout parameters of this sub-view. But the Scrolledxint and Scrolledyint parameters are not where we finger click:

Final int action = Ev.getaction (), final float XF = ev.getx (), final float YF = ev.gety (); final float scrolledxfloat = XF +  mscrollx;final float scrolledyfloat = YF + mscrolly;......final int scrolledxint = (int) scrolledxfloat;final int scrolledYInt = (int) scrolledyfloat;

As you can see, the point is not the coordinates that the finger clicked on when judging whether the point is contained in the sub view, but the coordinates of the finger click Plus the mscrollx and mscrolly. Then determine whether the child View is within the range.

Now think of the process of sliding to the left, although the position of the second linear layout does not change, or the layout parameter position, is: mleft:720,mtop:0,mright:1440,mbottom:1134.

But the mscrollx of his father's view changed, to the left mscrollx greater than 0, this is by hand click on the second linear layout, the position of the hand click, plus the value of MSCROLLX, this will fall in the second linear layout of the scope inside.

Test code:

Custom Myviewgroup:

public class Myviewgroup extends ViewGroup {public static final String TAG = "Myviewgroup";p rivate int childcount;private Gesturedetector detector;private Button btn;private linearlayout ll2;public myviewgroup (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, defstyle); init (context);} Public Myviewgroup (context context, AttributeSet Attrs) {Super (context, attrs); init (context);} Public Myviewgroup (Context context) {super (context); init (context);} private void init (final context context) {detector = new Gesturedetector (Context, New Myongesturelistener ()); LinearLayout ll1 = new LinearLayout (context); Ll1.setbackgroundcolor (color.blue); ll2 = new LinearLayout (context); Ll2.setbackgroundcolor (color.red); btn = new Button (context); Btn.settext ("click button"); Ll2.addview (BTN); AddView (LL1); AddView (LL2); Setontouchlistener (new Mytouchevent ()); Ll2.setonclicklistener (new Onclicklistener () {@Overridepublic void OnClick (View v) {toast.maketext (context, "Click on Linear Layout 2", 0). Show ();}); Btn.setonclicKlistener (New Onclicklistener () {@Overridepublic void OnClick (View v) {toast.maketext (Context, "clicked Button", 0). Show ();}) ;} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); childCount = Getchildcount (); for (int i = 0; i < ChildCount; i++) {View child = Getchildat (i); Measure (Widthmeasurespec,heightmeasurespec);}} @Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {for (int i = 0; i < ChildCount; i++) {Vi EW child = Getchildat (i); Child.layout (0+i*getwidth (), 0, (i+1) *getwidth (), getheight ());}} Private class Mytouchevent implements view.ontouchlistener{@Overridepublic boolean OnTouch (View V, motionevent event) { Detector.ontouchevent (event); return true;}} Private class Myongesturelistener extends simpleongesturelistener{@Overridepublic boolean onscroll (Motionevent E1, Motionevent e2,float Distancex, float distancey) {Scrollby ((int) Distancex, 0); if (GETSCROLLX ()% 10 = = 0){LOG.I (TAG, "button left upper right bottom position:" + btn.getleft () + "/" + btn.gettop () + "/" + btn.getright () + "/" + Btn.getbottom ()); LOG.I (TAG, "linear layout 2 left upper right bottom position:" + ll2.getleft () + "/" + ll2.gettop () + "/" + ll2.getright () + "/" + Ll2.getbottom ()); LOG.I (TAG, "Myviewgroup's MSCROLLX:" + GETSCROLLX ());} Return Super.onscroll (E1, E2, Distancex, Distancey);}}}

Then in the activity:

public class Mainactivity extends Activity {@Overrideprotected void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (new Myviewgroup (This));}}






Android controls capture the range of click events

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.