下面列出了android.app.assist.AssistStructure.ViewNode#getChildCount ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String[] hints = node.getAutofillHints();
if (hints != null) {
// We're simple, we only care about the first hint
String hint = hints[0];
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Adds any autofillable view from the {@link ViewNode} and its descendants to the map.
*/
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String[] hints = node.getAutofillHints();
if (hints != null) {
// We're simple, we only care about the first hint
String hint = hints[0].toLowerCase();
if (hint != null) {
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Adds any autofillable view from the {@link ViewNode} and its descendants to the map.
*/
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String hint = getHint(node);
if (hint != null) {
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Gets a node if it matches the filter criteria for the given id.
*/
public static ViewNode findNodeByFilter(@NonNull ViewNode node, @NonNull Object id,
@NonNull NodeFilter filter) {
if (filter.matches(node, id)) {
return node;
}
final int childrenSize = node.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
final ViewNode found = findNodeByFilter(node.getChildAt(i), id, filter);
if (found != null) {
return found;
}
}
}
return null;
}
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String[] hints = node.getAutofillHints();
if (hints != null) {
// We're simple, we only care about the first hint
String hint = hints[0];
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Adds any autofillable view from the {@link ViewNode} and its descendants to the map.
*/
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String[] hints = node.getAutofillHints();
if (hints != null) {
// We're simple, we only care about the first hint
String hint = hints[0].toLowerCase();
if (hint != null) {
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Adds any autofillable view from the {@link ViewNode} and its descendants to the map.
*/
private void addAutofillableFields(@NonNull Map<String, AutofillId> fields,
@NonNull ViewNode node) {
String hint = getHint(node);
if (hint != null) {
AutofillId id = node.getAutofillId();
if (!fields.containsKey(hint)) {
Log.v(TAG, "Setting hint '" + hint + "' on " + id);
fields.put(hint, id);
} else {
Log.v(TAG, "Ignoring hint '" + hint + "' on " + id
+ " because it was already set");
}
}
int childrenSize = node.getChildCount();
for (int i = 0; i < childrenSize; i++) {
addAutofillableFields(fields, node.getChildAt(i));
}
}
/**
* Gets a node if it matches the filter criteria for the given id.
*/
public static ViewNode findNodeByFilter(@NonNull ViewNode node, @NonNull Object id,
@NonNull NodeFilter filter) {
if (filter.matches(node, id)) {
return node;
}
final int childrenSize = node.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
final ViewNode found = findNodeByFilter(node.getChildAt(i), id, filter);
if (found != null) {
return found;
}
}
}
return null;
}
private static void dumpNode(StringBuilder builder, String prefix, ViewNode node, int childNumber) {
builder.append(prefix)
.append("child #").append(childNumber).append("\n");
builder.append(prefix)
.append("autoFillId: ").append(node.getAutofillId())
.append("\tidEntry: ").append(node.getIdEntry())
.append("\tid: ").append(node.getId())
.append("\tclassName: ").append(node.getClassName())
.append('\n');
builder.append(prefix)
.append("focused: ").append(node.isFocused())
.append("\tvisibility").append(node.getVisibility())
.append("\tchecked: ").append(node.isChecked())
.append("\twebDomain: ").append(node.getWebDomain())
.append("\thint: ").append(node.getHint())
.append('\n');
HtmlInfo htmlInfo = node.getHtmlInfo();
if (htmlInfo != null) {
builder.append(prefix)
.append("HTML TAG: ").append(htmlInfo.getTag())
.append(" attrs: ").append(htmlInfo.getAttributes())
.append('\n');
}
String[] afHints = node.getAutofillHints();
CharSequence[] options = node.getAutofillOptions();
builder.append(prefix).append("afType: ").append(getTypeAsString(node.getAutofillType()))
.append("\tafValue:")
.append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
.append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
.append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
.append("\tinputType:").append(node.getInputType())
.append('\n');
int numberChildren = node.getChildCount();
builder.append(prefix).append("# children: ").append(numberChildren)
.append("\ttext: ").append(node.getText())
.append('\n');
final String prefix2 = prefix + " ";
for (int i = 0; i < numberChildren; i++) {
dumpNode(builder, prefix2, node.getChildAt(i), i);
}
logv(builder.toString());
}
private static void dumpNode(String prefix, ViewNode node) {
StringBuilder builder = new StringBuilder();
builder.append(prefix)
.append("autoFillId: ").append(node.getAutofillId())
.append("\tidEntry: ").append(node.getIdEntry())
.append("\tid: ").append(node.getId())
.append("\tclassName: ").append(node.getClassName())
.append('\n');
builder.append(prefix)
.append("focused: ").append(node.isFocused())
.append("\tvisibility").append(node.getVisibility())
.append("\tchecked: ").append(node.isChecked())
.append("\twebDomain: ").append(node.getWebDomain())
.append("\thint: ").append(node.getHint())
.append('\n');
HtmlInfo htmlInfo = node.getHtmlInfo();
if (htmlInfo != null) {
builder.append(prefix)
.append("HTML TAG: ").append(htmlInfo.getTag())
.append(" attrs: ").append(htmlInfo.getAttributes())
.append('\n');
}
String[] afHints = node.getAutofillHints();
CharSequence[] options = node.getAutofillOptions();
builder.append(prefix).append("afType: ").append(getAutofillTypeAsString(node.getAutofillType()))
.append("\tafValue:")
.append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
.append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
.append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
.append("\tinputType:").append(node.getInputType())
.append('\n');
int numberChildren = node.getChildCount();
builder.append(prefix).append("# children: ").append(numberChildren)
.append("\ttext: ").append(node.getText())
.append('\n');
Log.v(TAG, builder.toString());
final String prefix2 = prefix + " ";
for (int i = 0; i < numberChildren; i++) {
Log.v(TAG, prefix + "child #" + i);
dumpNode(prefix2, node.getChildAt(i));
}
}
/**
* Finds {@link ViewNode ViewNodes} that have the requested ids.
*
* @param ids The ids of the node to find.
*
* @return The nodes indexed in the same way as the ids.
*
* @hide
*/
@NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) {
final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length];
// Indexes of foundNodes that are not found yet
final SparseIntArray missingNodeIndexes = new SparseIntArray(ids.length);
for (int i = 0; i < ids.length; i++) {
if (mViewNodeLookupTable != null) {
int lookupTableIndex = mViewNodeLookupTable.indexOfKey(ids[i]);
if (lookupTableIndex >= 0) {
foundNodes[i] = mViewNodeLookupTable.valueAt(lookupTableIndex);
} else {
missingNodeIndexes.put(i, /* ignored */ 0);
}
} else {
missingNodeIndexes.put(i, /* ignored */ 0);
}
}
final int numWindowNodes = mStructure.getWindowNodeCount();
for (int i = 0; i < numWindowNodes; i++) {
nodesToProcess.add(mStructure.getWindowNodeAt(i).getRootViewNode());
}
while (missingNodeIndexes.size() > 0 && !nodesToProcess.isEmpty()) {
final ViewNode node = nodesToProcess.removeFirst();
for (int i = 0; i < missingNodeIndexes.size(); i++) {
final int index = missingNodeIndexes.keyAt(i);
final AutofillId id = ids[index];
if (id.equals(node.getAutofillId())) {
foundNodes[index] = node;
if (mViewNodeLookupTable == null) {
mViewNodeLookupTable = new ArrayMap<>(ids.length);
}
mViewNodeLookupTable.put(id, node);
missingNodeIndexes.removeAt(i);
break;
}
}
for (int i = 0; i < node.getChildCount(); i++) {
nodesToProcess.addLast(node.getChildAt(i));
}
}
// Remember which ids could not be resolved to not search for them again the next time
for (int i = 0; i < missingNodeIndexes.size(); i++) {
if (mViewNodeLookupTable == null) {
mViewNodeLookupTable = new ArrayMap<>(missingNodeIndexes.size());
}
mViewNodeLookupTable.put(ids[missingNodeIndexes.keyAt(i)], null);
}
return foundNodes;
}
private static void dumpNode(StringBuilder builder, String prefix, ViewNode node, int childNumber) {
builder.append(prefix)
.append("child #").append(childNumber).append("\n");
builder.append(prefix)
.append("autoFillId: ").append(node.getAutofillId())
.append("\tidEntry: ").append(node.getIdEntry())
.append("\tid: ").append(node.getId())
.append("\tclassName: ").append(node.getClassName())
.append('\n');
builder.append(prefix)
.append("focused: ").append(node.isFocused())
.append("\tvisibility").append(node.getVisibility())
.append("\tchecked: ").append(node.isChecked())
.append("\twebDomain: ").append(node.getWebDomain())
.append("\thint: ").append(node.getHint())
.append('\n');
HtmlInfo htmlInfo = node.getHtmlInfo();
if (htmlInfo != null) {
builder.append(prefix)
.append("HTML TAG: ").append(htmlInfo.getTag())
.append(" attrs: ").append(htmlInfo.getAttributes())
.append('\n');
}
String[] afHints = node.getAutofillHints();
CharSequence[] options = node.getAutofillOptions();
builder.append(prefix).append("afType: ").append(getTypeAsString(node.getAutofillType()))
.append("\tafValue:")
.append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
.append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
.append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
.append("\tinputType:").append(node.getInputType())
.append('\n');
int numberChildren = node.getChildCount();
builder.append(prefix).append("# children: ").append(numberChildren)
.append("\ttext: ").append(node.getText())
.append('\n');
final String prefix2 = prefix + " ";
for (int i = 0; i < numberChildren; i++) {
dumpNode(builder, prefix2, node.getChildAt(i), i);
}
logv(builder.toString());
}
private static void dumpNode(String prefix, ViewNode node) {
StringBuilder builder = new StringBuilder();
builder.append(prefix)
.append("autoFillId: ").append(node.getAutofillId())
.append("\tidEntry: ").append(node.getIdEntry())
.append("\tid: ").append(node.getId())
.append("\tclassName: ").append(node.getClassName())
.append('\n');
builder.append(prefix)
.append("focused: ").append(node.isFocused())
.append("\tvisibility").append(node.getVisibility())
.append("\tchecked: ").append(node.isChecked())
.append("\twebDomain: ").append(node.getWebDomain())
.append("\thint: ").append(node.getHint())
.append('\n');
HtmlInfo htmlInfo = node.getHtmlInfo();
if (htmlInfo != null) {
builder.append(prefix)
.append("HTML TAG: ").append(htmlInfo.getTag())
.append(" attrs: ").append(htmlInfo.getAttributes())
.append('\n');
}
String[] afHints = node.getAutofillHints();
CharSequence[] options = node.getAutofillOptions();
builder.append(prefix).append("afType: ").append(getAutofillTypeAsString(node.getAutofillType()))
.append("\tafValue:")
.append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
.append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
.append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
.append("\tinputType:").append(node.getInputType())
.append('\n');
int numberChildren = node.getChildCount();
builder.append(prefix).append("# children: ").append(numberChildren)
.append("\ttext: ").append(node.getText())
.append('\n');
Log.v(TAG, builder.toString());
final String prefix2 = prefix + " ";
for (int i = 0; i < numberChildren; i++) {
Log.v(TAG, prefix + "child #" + i);
dumpNode(prefix2, node.getChildAt(i));
}
}