Reputation: 3497
My Accessibility service would go through the focusable nodes. I am trying to use the focusSearch function for this, but that is not giving any node back. But the layout contains focusable items. Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:text="Button" />
<TextView
android:id="@+id/text"
android:layout_width="122dp"
android:layout_height="fill_parent"
android:text="Hello World2" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:focusable="true"
android:text="Button2" />
</LinearLayout>
So what I tried is to find the first button:
AccessibilityNodeInfo root = getRootInActiveWindow();
AccessibilityNodeInfo node1 = null;
node1 = root.findAccessibilityNodeInfosByViewId("my.app:id/button1").get(0);
//returns button view
node1 = root.focusSearch(View.FOCUS_DOWN); //returns null
node1 = root.focusSearch(View.FOCUS_LEFT); //returns null
node1 = root.focusSearch(View.FOCUS_RIGHT); //returns null
node1 = root.focusSearch(View.FOCUS_FORWARD); //returns null
However using findFocus it gives back the framelayout
node1 = root.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
//returns node of the main framelayout
Then I used this node for next search, but nothing found again.
node1 = node1.focusSearch(View.FOCUS_FORWARD); //returns null
And when I call findfocus
instead of focusSearch
i got the same node back
node1 = node1.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
//returns the same node
So the question is how can I go through on the focusable nodes within a layout?
Upvotes: 1
Views: 2652
Reputation: 1701
Exactly! The view containers are returned because they are present in the tree.
What you need is the leaf nodes.
This code will give you a list of nodes(leaf nodes) that are focusable:
ArrayList<AccessibilityNodeInfo> inputViewsList = new ArrayList<AccessibilityNodeInfo>();
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
refreshChildViewsList(rootNode);
for(AccessibilityNodeInfo mNode : inputViewsList){
if(mNode.isFocusable()){
//do whatever you want with the node...
}
}
refreshChildViewsList
method:
private void refreshChildViews(AccessibilityNodeInfo rootNode){
int childCount = rootNode.getChildCount();
for(int i=0; i<childCount ; i++){
AccessibilityNodeInfo tmpNode = rootNode.getChildAt(i);
int subChildCount = tmpNode.getChildCount();
if(subChildCount==0){
inputViewsList.add(tmpNode);
return;
} else {
refreshChildViews(tmpNode);
}
}
}
Let me know if there's any issue with this code!
Upvotes: 1
Reputation: 18870
This is a common misconception. What you are searching for is objects that can take input focus (think EditText controls). This is fundamentally different from Accessibility Focus. There are no input focusable controls in your layout.
The functions you want are:
someAccessibilityNodeInfo.getTraversalAfter();
and
someAccessibilityNodeInfo.getTraversalBefore();
There is no up/down equivalent. Though you could calculate this however you want. You could store the entire heirarchy of accessibility focusable nodes in an array, and calculate up/down based on x and y positions.
Upvotes: 3