background
Right swipe on douyin’s home page to enter the “Personal Center” page. In theory, the PV of this page should not be too small for the APP whose home page lives over 100 million times a day. But some of the time in this page will appear sliding conflict of small problems, not conducive to the user experience, through repeated tests, play found will now operation, as a senior shaking, fan and a non senior Android development of I, delving into thought – to see how the problem is, and is there any solution can be optimized.
scenario
Right swipe on the home page to enter the “Personal Center” page, then swipe left and right on RecylerView at the bottom without triggering the switch of their parent layout ViewPager, then swipe up and down without lifting the finger, and the RecylerView will receive the sliding event, resulting in sliding dislocation (specific visible video, The android versions of Tiktok are randomly selected here, v14.8.0, V14.9.0, V1.7.2 and V3.9.0 respectively. Find the problems… There is no such problem when using iOS at the same time).
Analysis of the
Now that the problem is clear, the next step is how the analysis comes about. Through comprehensive analysis, I find that Tiktok uses a custom LinearLayout of header + Viewpager + RecyclerView. The nested slides are then handled by intercepting the disptachTouchEvent of the LinearLayout. The overall sliding process is shown in the figure:
-
When the finger touches the screen, record the position. After sliding, judge whether it is horizontal or vertical, judge only once
-
If it is sliding up and down, judge whether to trigger the sliding of the outermost LinearLayout or trigger the sliding of RecyclerView itself.
-
The sliding triggered by itself is to call its own scrollBy(0, dy). Notice that the event at this time will still be passed down to RecyclerView, but the sliding difference is very small compared with RecyclerView itself, which can be ignored visually.
-
Do not trigger their own sliding will be directly distributed, at this time, the vertical (DY) difference of RecyclerView itself changes greatly, normal sliding.
-
When there is a problem, the user’s hand is triggered to slide left and right first. At this time, some critical judgments in RecyclerView parent layout ViewPager are not triggered, so events are not intercepted. Events are still in RecyclerView. Also considered to be left or right sliding events, so the LinearLayout itself does not roll, but RecyclerView normally responds to rolling, resulting in sliding deviation.
Optimization scheme
The problem analysis is almost done, in fact, it was also over, but surprised to find that this custom sliding layout is extended from the open source library: github.com/cpoopc/Scro… But it hasn’t been maintained for a long time. But through this original library. It can be seen that the core logic is consistent. After debugging and compiling, it is found that this library also has this problem, so we will try to solve it based on this library.
The original code for the library is shown below:
Else in the figure actually triggers the sliding logic up and down, while the outer custom LinearLayout layout does not follow the sliding. Add a judgment inside, remove the true left/right sliding logic (ViewPager event), the remaining events are triggered RecylcerView sliding (filter horizontal, leave vertical), we again determine whether the outer custom LinearLayout needs linkage. It would be nice if we needed to link again.
Standing on the shoulders of giants, the processing of system controls can generally be used for reference, under the source code, all clear, horizontal can refer to ViewPager event interception, vertical can refer to RecyclerView event processing logic. Analyze the onIntercepetTouchEvent() of the two controls to get its core judgment whether to respond to the sliding logic, for our use.
ViewPager 图 文
Core interception logic:
1.If I have a slider in the transverse directionView,Don’t intercept, let sonThe View of * * * *
2. If the horizontal sliding exceeds the critical value mTouchSlop** and is greater than 2 times of the vertical sliding distance, intercept **
We need to copy all the relevant judgment codes, and then add them to our custom LinearLayout
At this point, Log debugging found that there is still a problem…… If the LinearLayout has a horizontal slippable View, our isHorizontalDrag method should return true****. If the LinearLayout has a horizontal sliding View, our isHorizontalDrag method should return true****. **
The picture after modification is as follows:
So I’ve written the filter for horizontal judgment here. Look at the vertical RecyclerView interceptor code, actually very simple:
1. When the vertical is slippable and the vertical difference dy is greater than the critical value mTouchSlop, it is the response event.
Copy to join the test:
After running tests, it was found that the problem had indeed been resolved.
-
In simple terms, when the user swiped horizontally, he could determine whether any child View consumed a horizontal event by adding ****isHorizontalDrag().
-
If they do, they do nothing
-
No, so let’s decide if we want the outermost oneLinearLayoutConsumption of the vertical part, after meeting the conditions, their own consumption events scroll.
other
The above is my opinion on the slide conflict optimization of the “Personal Center” page of Douyin Android terminal. The optimization scheme is just a simple test done by myself. If there is a plan in the future, I think that Google’s representative CoordinatorLayout can deal with this nesting slide (although there are some holes, both the official and the netizens are filling them in. Overall, it was a good performance…) . Welcome to exchange more.