In Android, the focus acquisition and event is similar, there is a distribution mechanism, generally view tree upper node viewgroup than the underlying node's view has a higher priority to get focus, which is reflected in the ViewGroup has a property Descendantfocusability can be used to control the priority of focus acquisition. There are three values for this property:
- Beforedescendants:viewgroup takes precedence over its child controls, and if the parent control does not get the focus, the child controls may gain focus
- Afterdescendants: ViewGroup can get focus only if its subclass control does not need to get focus
- Blocksdescendants:viewgroup blocks the child control from gaining focus, regardless of whether the viewgroup gets the focus, the child controls are not able to gain focus
How to tell if a View can get focus
For the reasons above, it is possible to determine whether a view has the focus, and it is related to all of its parent nodes, so the Hasfocusable method of view is implemented as follows:
public boolean hasfocusable () {if (!isfocusableintouchmode ()) {for (viewparent p = mparent; p instanceof viewgroup; p = p.getparent ()) {final viewgroup g = (viewgroup) p; if (G.shouldblockfocusfortouchscreen ()) {return false ; }}} return (mviewflags & visibility_mask) = = VISIBLE && isfoc Usable ();}
- In touch mode, if the focus is not available, then all parent nodes of the view are traversed, and if a parent node sets the blocking sub-view to get the focus, the view cannot get the focus
- In touch mode, if the focus is not available, and there is no parent node setting blocking child View to get focus, and if the focus is available in touch mode, then the Visiable and focusable properties of the view itself are determined to determine whether the focus can be obtained, the Invisible view Of course, it is not possible to get the focus, so only visiable and focusable are true at the same time, the view may get focus
Determine if ViewGroup can get focus
Determine if a viewgroup is possible to get to the focus, also with its sub-view, if the child view can get focus, spicy, it can be counted as this viewgroup may also get (consume) focus, so viewgroup hasfocusable method implementation As follows:
Public Boolean hasfocusable() {if((Mviewflags & visibility_mask)! = VISIBLE) {return false; }if(Isfocusable ()) {return true; }Final intDescendantfocusability = Getdescendantfocusability ();if(descendantfocusability! = focus_block_descendants) {Final intCount = Mchildrencount;FinalView[] children = Mchildren; for(inti =0; I < count; i++) {FinalView child = Children[i];if(Child.hasfocusable ()) {return true; } } }return false;}
According to the above source, it is much easier to judge whether ViewGroup can get the focus.
- If ViewGroup visiable and focusable are true, even if you can get the focus
- If the 1th is not met, even if the child View node can get the focus, the ViewGroup can also get the focus
- Otherwise, it is counted as not being able to get the focus
- ViewGroup oneself can get the focus, completely did not consider whether in the touch mode situation, do not know is not the Google engineer's bug
Whether the View can get the focus of the actual application
Whether the View can get the focus is usually applied to the use of Abslistview's Onitemclicklistener,edittext,button and key event distribution. For example, the Onitemclicklistener of a ListView will call Onitemclicklistener's Onitemclick method only if the ListView's Itemview cannot get to focus. The specific code can refer to Abslistview's Ontouchup method:
Private void Ontouchup(Motionevent ev) {Switch(Mtouchmode) { CaseTouch_mode_down: CaseTouch_mode_tap: CaseTouch_mode_done_waiting: ... The province on the province, I was omitting the code break ^_^ ...if(Inlist &&!child.hasfocusable ()) {if(Mperformclick = =NULL) {Mperformclick =NewPerformClick (); }FinalAbslistview.performclick PerformClick = Mperformclick; Performclick.mclickmotionposition = motionposition; Performclick.rememberwindowattachcount (); ...... The province is province, I am omitting the code separator ^_^ ... mtouchmodereset =NewRunnable () {@Override Public void Run() {Mtouchmodereset =NULL; Mtouchmode = Touch_mode_rest; Child.setpressed (false); Setpressed (false);if(!mdatachanged &&!misdetaching && Isattachedtowindow ()) {Performclick.run (); } } }; Postdelayed (Mtouchmodereset, Viewconfiguration.getpressedstateduration ()); }Else{mtouchmode = touch_mode_rest; Updateselectorstate (); }return; }Else if(!mdatachanged && madapter.isenabled (motionposition)) {Performclick.run (); } } } ...... The province is province, I am omitting the code break ^_^ ...}
The 9th line of the above code shows that the Hasfocusable method of the ListView's Itemview must return Fasle to execute Performclick.run () before it executes to Onitemclicklistener ONITEMCL Ick method. This is why we usually use the Onitemclicklistener method of the ListView to set the Descendantfocusability property of the root node of the Item layout file to Blocksdescendants, and cannot be true for the node's Focusable property.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
View and ViewGroup's hasfocusable