@Override public void requestChildFocus(View child, View focused) { if (!mIsLayoutDirty) { scrollToChild(focused); } else { mChildToScrollTo = focused; } super.requestChildFocus(child, focused); }
Because the requestLayout() method was called before addViewInner:
@Override public void requestLayout() { mIsLayoutDirty = true; super.requestLayout(); }
Therefore, when we execute requestChildFocus, we will enter else judgment, mchildtoscollto = focused.
2. Next, let's continue to analyze the mParent.requestChildFocus(this, focused) method?
android.view.ViewGroup{ @Override public void requestChildFocus(View child, View focused) { if (DBG) { System.out.println(this + " requestChildFocus()"); } if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) { return; } // Unfocus us, if necessary super.unFocus(focused); // We had a previous notion of who had focus. Clear it. if (mFocused != child) { if (mFocused != null) { mFocused.unFocus(focused); } mFocused = child; } if (mParent != null) { mParent.requestChildFocus(this, focused); } } }
First, we will judge the descendantFocusability attribute of ViewGroup. If it is focus_ BLOCK_ If the values of scenarios are returned directly (as will be explained later in this section, the Android: descendantFocusability = "blocksdecedents" attribute can solve the problem of automatic sliding). Let's take a look at if (mparent= When null) mparent. requestChildFocus (this, focused)} is established, it will be called here until the requestChildFocus method of ViewRootImpl is called
@Override public void requestChildFocus(View child, View focused) { if (DEBUG_INPUT_RESIZE) { Log.v(mTag, "Request child focus: focus now " + focused); } checkThread(); scheduleTraversals(); }
scheduleTraversals () will start a runnable and execute the performTraversals method to redraw the view tree.
3. Then why does the ScrollView slide to the position of the sub view that gets the focus?
A: through the above analysis, we can see that when the Scrollview contains a focused view, the view tree will be redrawn eventually, so the onLayout method of the view will be called. Let's take a look at the onLayout method of the Scrollview
android.view.ScrollView{ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); ...... if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) { scrollToChild(mChildToScrollTo); } mChildToScrollTo = null; ...... } }
From the first step, we can see that in the requestChildFocus method, we assigned the value to mchildtoscollto, so at this time, we will enter the execution of if judgment and call the scrolltochild (mchildtoscollto) method:
private void scrollToChild(View child) { child.getDrawingRect(mTempRect); offsetDescendantRectToMyCoords(child, mTempRect); int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect); if (scrollDelta != 0) { scrollBy(0, scrollDelta); } }
Obviously, the current method is to move the ScrollView to the view to obtain the specified. Here we can understand why the ScrollView will automatically slide to the position of the sub view to obtain the focus.
4. Why can adding the android:descendantFocusability = "blocksdecedents" attribute in the viewGroup of the child of ScrollView prevent the ScrollView from sliding automatically?
A: as mentioned in the first step, the drawing principle of view: it is the hierarchical drawing of the view tree. It is the mechanism of drawing the top of the tree, that is, the child view and then the parent view. Therefore, when we set the android:descendantFocusability = "blocksdecedents" attribute in the direct child view of ScrollView, we directly return it at this time, The requestChildFocus(View child, View focused) method of the parent view, that is, the ScrollView, will no longer be executed, resulting in the following automatic sliding will not be triggered.
@Override public void requestChildFocus(View child, View focused) { ...... if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) { return; } ...... if (mParent != null) { mParent.requestChildFocus(this, focused); } }
5. I believe many people have questions here: according to your explanation, can adding android:descendantFocusability = "blocksdecedents" attribute to ScrollView also prevent automatic sliding?
A: according to the previous analysis, it seems possible, but looking at the source code of ScrollView, we can see that
private void initScrollView() { mScroller = new OverScroller(getContext()); setFocusable(true); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setWillNotDraw(false); final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); }
When you happily set the android:descendantFocusability = "blocksdecedents" attribute, you think the problem has been solved, but unexpectedly, people set the descendantFocusability attribute to focus in the ScrollView code_ AFTER_ Scendants, so it doesn't have any effect if you add them in xml.
6. From the above analysis, once the ScrollView is loaded, it will slide to the position of the sub view to obtain the focus. We also understand the reason why adding the Android: descendantfocusability = "blocksdecedents" attribute can prevent the ScrollView from automatically scrolling to the sub view to obtain the focus, but why set a layer of view outside the sub view to obtain the focus, Then adding the focusableInTouchMode=true attribute can also solve such sliding?
A: we notice that when calling the addViewInner method, we will first judge the view.hasFocus(), where there are two rules for judging the view.hasFocus(): 1. Only when the current view is just displayed, can hasFocus() be true; 2. If a view at the same level has multiple focus views, then only the first view obtains the focus. If the focusableInTouchMode=true attribute is added to the view tag in the layout, it means that the hasfocus of the tag view is true when we are loading, but they are false when we get the value of the hasfocus method of the child view( This means that although the Scrollview will slide, it will slide to the position of the view with the focusableInTouchMode=true attribute. If the position of the view is filled with Scrollview, it is equivalent to no sliding, This is why adding the focusableInTouchMode=true attribute to the external layout can prevent the Scrollview from automatically scrolling to the child view that gets the focus. Therefore, setting a layer of focusableInTouchMode=true on the external layout is not a strict statement, because although we set a layer of view, if the view is not covered with scrollviews, It is likely that automatic sliding will still occur. Therefore, when we set the focusableInTouchMode=true attribute, we'd better add it on the direct child view of Scrollview.
summary
Through the above analysis, we can actually get a variety of methods to solve the problem that Scrollview will automatically scroll to the sub view to obtain the focus. For example, if you customize and rewrite the requestChildFocus method of Scrollview, you can interrupt the automatic sliding of Scrollview by directly returning return. In essence, it interrupts the process of rewriting the requestChildFocus method of Scrollview, Or let the sub views covered with Scrollview in the Scrollview get the focus. In this way, although it slides, the sliding distance is only 0, which is equivalent to no sliding** Similarly, we can also understand that if RecyclerView nested RecyclerView, resulting in automatic sliding, requestChildFocus should also be rewritten in RecyclerView to prepare for automatic sliding. I also hope you can verify yourself by reading the source code.
Sort out the following three methods: the first
<ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusableInTouchMode="true" android:orientation="vertical"> </LinearLayout> </ScrollView>
The second
<ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:orientation="vertical"> </LinearLayout> </ScrollView>
The third
public class StopAutoScrollView extends ScrollView { public StopAutoScrollView(Context context) { ##### **How to do interview raids and plan the learning direction** The interview question set can help you find out and fill vacancies, study in a direction and pertinence, and prepare for entering a large factory later. But if you just watch it once without learning and delving into it. Then this interview question will be of limited help to you. Finally, it depends on the senior technical level. Online learning Android There are a lot of materials, but if the knowledge learned is not systematic, only a superficial taste when encountering problems and no further research, it is difficult to achieve real technical improvement. It is suggested to make a learning plan first, and connect the knowledge points according to the learning plan to form a systematic knowledge system. The learning direction is easy to plan, but if you only study through fragmentation, your improvement is very slow. We have collected and sorted out the interview questions of Tencent, Alibaba, Huawei, Xiaomi and other companies in recent years, and sorted out the interview requirements and technical points into a large and comprehensive report“ Android "Architect" interview Xmind(In fact, it takes a lot more energy than expected), including the context of knowledge + Branch details. ![img](https://img-blog.csdnimg.cn/img_convert/1775c64126605884e1dfce13790a288c.png) When building these technical frameworks, we also sorted out the advanced tutorials of the system, which will be much more effective than our own fragmented learning; Your promotion is very slow. We have collected and sorted out the interview questions of Tencent, Alibaba, Huawei, Xiaomi and other companies in recent years, and sorted out the interview requirements and technical points into a large and comprehensive report“ Android "Architect" interview Xmind(In fact, it takes a lot more energy than expected), including the context of knowledge + Branch details. [External chain picture transfer...(img-KjHVMeiI-1630586163923)] When building these technical frameworks, we also sorted out the advanced tutorials of the system, which will be much more effective than our own fragmented learning; ##### **[CodeChina open source project: Android learning notes summary + mobile architecture Video + big factory interview real questions + project actual combat source code]( https://codechina.csdn.net/m0_60958482/android_p7)**