Viewpager nested Recyclerview and nested Recyclerview to see the Android event distribution mechanism

Source: Internet
Author: User
Tags xdiff

This two-day great PM under a demand, in a vertical slip list to implement a horizontal sliding list, yes, again this common but often be with a strong sense of responsibility and professional ethics programmers scoff at the effect, nonsense said, first:

There are many ways to implement it, because the basic framework is already VIEWPAGER+RV in the project, so now I also choose to add another RV to achieve the corresponding effect.

But before you write the code, estimate all the pits for this effect.
VP is horizontal sliding, RV is vertical sliding, then now add a lateral sliding rv, there will definitely be a sliding conflict, mainly in the

VP and Lateral sliding RV clash, because both are horizontal sliding, there must be conflict, unable to determine which to swipe
Vertical RV and Lateral rv conflicts, if the previous VP and vertical RV conflicts have been resolved, then now I can only solve the
When the transverse RV slides to the last item, the VP should be slid to the second page, not stuck there.

Above is to rely on my poor development experience pre-projected pit, after all, the word sliding conflict is simply too sensitive to Android developers, as long as the sliding direction is inconsistent, will be reflected in the mind, there must be a conflict!
However, here first of all, we actually follow the most basic finish is OK, do not have to deal with conflict.
What??!!, quasi-ben up the pipe when the gun, found not to solve, although worry and effort, but the heart is not happy ah. Why, where is the sliding conflict handled, is the VP or RV?

I started off with RV because it was better to deal with sliding conflicts from the sub-view level. However, the distribution mechanism of the event is tunnel propagation, bubbling processing form, that is, the first event to the upper view, the upper view if not processed to the lower view, the lower view processing, consumes the event, not processing, then return to the upper layer processing, until someone finishes processing.

Since we have not replicated any of the methods of sliding events, we want to find out why, only from the source, in the source of the break point, before the break point, you have to the Android event distribution have a little understanding, the following list of event distribution common methods:

Dispatchtouchevent (), the distribution of the event, returns true to indicate that the event was consumed and not distributed downward
Ontouchevent (), returns True to indicate that the event is consumed, in fact the return value of the Dispatchtouchevent () determines the return value, see the source can know
In addition to the above methods, ViewGroup also has a Onintercepttouchevent method that indicates whether to intercept the event, return true is also intercepted
ViewGroup The default is not to intercept any events, the view default is to handle all events.

For a more detailed summary, you can look at this blog Android event distribution mechanism

Next start break point, open the VP source, found that he is inherited from ViewGroup. This means that he does not intercept any events by default.

See this should be keenly aware that if the VP does not do any sliding effect, then he is like a linearlayout. All events will be issued to his child view by default. But now that he has a sliding effect, how did he get it to the RV, did he leave the RV to deal with it, or did he handle it and let the RV accept the incident?

Make a good breakpoint:

First sell a Xiaoguanzi, this breakpoint hit is a problem.
The same way, open the RV source code, found that he also inherited ViewGroup, but I was looking for his onintercepttouchevent () method and did not find him to replicate the method, it appears that he does not intercept the default event delivery?

Now that we can't find the Onintercepttouchevent () method, we'll find the Ontouchevent method, and after that, the break point is as follows:


There's a problem with this breakpoint.
By the way, I looked at the return value of the Ontouch event and found

Coincidentally, the default is to return True, it appears by default, RV is to handle all events.

All breakpoints are finished, start debugging,

Step by step, find out

Code into this branch inside, see a lot of variables and some methods I carefully debugging, look at the value, a line of understanding, the results of debugging only found, this! And! Didn't! Yes! What! You! Eggs! Use!
If you are so complicated by the source code around, then you really will be frightened, you have to know that RV has more than 10,000 lines of code, think about, why I said the breakpoint has a problem? That's the reason. What we are going to look at now is why there is no sliding conflict in the horizontal slide, in fact we just need to break the point in the Action.move branch, and the others can pass directly.
*

This is my break point encountered the first pit, after all, not in the source before the breakpoint, a look at the source code so complex and can not understand only disorderly dozen a pass, slowly see, in fact, this can only let you deterred.

*
Into the Action.move branch, before analyzing this branch code, we must always keep in mind what we want to achieve and what we are doing, and we are now in the Intercepettouch method to decide whether to intercept the event, return true means intercept, return false means no interception, so we do not look at this branch of the code, after all, more than 50 lines of code, you have no patience to go around.
Take a look at the return value, found to be a variable, misbeingdragged, the default is False, which, as we said before, viewgroup the default does not intercept all events coincide.

Since the return value is determined by misbeingdragged, we first search globally where the parameter is assigned a value, crtl+f a global search, and find that there are no additional assignments in the Actiondown event and Actionmove event, so This provides us with the convenience of troubleshooting, Actiondown incident has been excluded, do not need to analyze, only see actionmove inside the

 CaseMotionevent.action_move:if(!misbeingdragged) {Final intPointerindex = Ev.findpointerindex (Mactivepointerid);if(Pointerindex = =-1) {//A child has consumed some touch events and put us to an inconsistent                        //state.Needsinvalidate = Resettouch (); Break; }Final floatx = Ev.getx (Pointerindex);Final floatXdiff = Math.Abs (X-mlastmotionx);Final floaty = ev.gety (Pointerindex);Final floatYdiff = Math.Abs (y-mlastmotiony);if(DEBUG) {LOG.V (TAG,"Moved x to"+ x +","+ y +"diff="+ Xdiff +","+ Ydiff); }if(Xdiff > Mtouchslop && xdiff > Ydiff) {if(DEBUG) LOG.V (TAG,"Starting drag!"); Misbeingdragged =true; Requestparentdisallowintercepttouchevent (true); Mlastmotionx = X-minitialmotionx >0?                        Minitialmotionx + mtouchslop:minitialmotionx-mtouchslop;                        Mlastmotiony = y;                        Setscrollstate (scroll_state_dragging); Setscrollingcacheenabled (true);//Disallow Parent Intercept, just in caseViewparent parent = GetParent ();if(Parent! =NULL) {Parent.requestdisallowintercepttouchevent (true); }                    }                }//Not else! Note that misbeingdragged can is set above.                if(misbeingdragged) {//Scroll to follow the motion event                    Final intActivepointerindex = Ev.findpointerindex (Mactivepointerid);Final floatx = Ev.getx (Activepointerindex);                Needsinvalidate |= Performdrag (x); } Break;

The code is still pretty much, but we just need to analyze to misbeingdragged assignment and have the return value of the place, so in fact, the core of the two code,

if0 && !isGutterDrag(mLastMotionX, dx)                        && canScroll(thisfalse, (int) dx, (int) x, (int) y)) {                    // Nested view has scrollable area under this point. Let it be handled there.                    mLastMotionX = x;                    mLastMotionY = y;                    true;                    returnfalse;                }

And

if  (Xdiff > Mtouchslop && Xdiff * 0.5  F > Ydiff) {if (DEBUG) log.v (TAG,  "starting drag!" );                    misbeingdragged = true ;                    Requestparentdisallowintercepttouchevent (true ); set                     Scrollstate (scroll_state_dragging); Mlastmotionx = DX > 0 ?                    Minitialmotionx + mtouchslop:minitialmotionx-mtouchslop;                    Mlastmotiony = y; set                 scrollingcacheenabled (true ); }

Combined with our present situation, Viewpager nested RV does not appear sliding conflict, it is definitely returned false, so, the second code can actually be abolished, not analysis, but I want to install force or to say, if the condition is to judge the direction of sliding, If the sliding distance in the x direction is greater than the minimum sliding distance, and the X-direction sliding distance of 0.53 is greater than the Y-direction distance, it is determined to be horizontal sliding, then intercept the event, Misbeingdragged is set to true, but this is not enough, the method allows the call of the Requestparentdisallowintercepttouchevent (True); method, this method is to tell the parent control, I want to start the installation force, you don't care about me, the rest of the matter I will deal with it, you don't care. My personal understanding is double insurance, as for the other code, do not have to analyze, because it is not related to our analysis. This code is the interception of horizontal sliding events, after all, VP is doing this thing.

So the next thing is clear, the problem must appear in the first code, the judgment statement has a problem if (dx! = 0 &&!isgutterdrag (mlastmotionx, DX) && CanScroll (this, false , (int) dx, (int) x, (int) y))
Dx! =0 Needless to say, let's go through the analysis of Isgutterdrag (Mlastmotionx, DX) and CanScroll (this, false, (int) dx, (int) x, (int) y)), and there's no specific analysis, Isgutterdrag (Mlastmotionx, DX) is to determine whether to move within the gap between two pages, so definitely return false, then it must be this canscroll (this, false, (int) dx, (int) x, (int) y ) returns True. Into the source to see a

 protected BooleanCanScroll (View V,BooleanCHECKV,intDxintXintY) {if(v instanceof ViewGroup) {FinalViewGroupGroup= (ViewGroup) v;Final intSCROLLX = V.getscrollx ();Final intscrolly = v.getscrolly ();Final int Count=Group. Getchildcount ();//Count Backwards-let topmost views consume scroll distance first.             for(inti =Count-1; I >=0; i--) {//Todo:add versioned support here for transformed views.                // This won't work for transformed views in honeycomb+                FinalView Child =Group. Getchildat (i);if(x + scrollx >= child.getleft () && x + scrollx < Child.getright () && y + scro Lly >= child.gettop () && y + scrolly < Child.getbottom () && canscroll (Child,true, DX, x + scrollx-child.getleft (), Y + scrolly-child.gettop ())) {return true; }            }        }returnCheckv && viewcompat.canscrollhorizontally (V,-DX); }

Look very scary, at first glance do not know what to use, but also used to recursion. But we see that there is getchildcount this function, the explanation is definitely related to the child view, so, this is definitely to judge the sub-view in the VP, called CanScroll, roughly can guess, this function is used to determine whether the child view can be scrolled, Look at the note and you'll know:

* * Tests scrollabilitywithinChild views ofV GivenaDelta ofDX. * * @paramV View toTest forHorizontal scrollability * @paramCHECKV Whether theView v passed should itself be checked forScrollability (true),     *orJust its children (false). * @paramDX Delta scrolledinchpixels * @paramx x coordinate of  theActive Touch Point * @paramY y coordinate of  theActive Touch Point * @return true ifChild views ofV can be scrolled byDelta ofDX. */

Return true if child view of V can is scrolled by Delta of DX, said very clearly, if the sub-views can scroll will return to TRUE,VP in the RV is a sub view, and can scroll horizontally, naturally walk into the branch, Cut Intercpetontouch return False, do not intercept, to sub-view processing, sub-view how to deal with it, do not do analysis

There is a general understanding of why the VP nested RV does not appear to have an event conflict.

VP does not intercept events by default
The VP will intercept the horizontal slide event, which is his instinct, but before this code, he did other things, that is, to determine whether his sub-view can scroll, can scroll, will not intercept the move event.
VP Nested VP also does not have a rolling conflict, because the above two, do not know why the network will have VP sets of VP sliding conflict, do not understand, I wrote the code did not find.

As for RV incident conflict, do not do analysis, roughly the same, write blog good tired, code did not upload GitHub, because the new company has not configured ~ There is need to contact ....

Big guy Pat Brick, write a blog than write code more tired, many places I myself are not clear ~~~> also rv nested RV conflict How to solve, read the blog you analyze it, right when exercise.

Viewpager nested Recyclerview and nested Recyclerview to see the Android event distribution mechanism

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.