• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package foo.bar.filled;
2 
3 import android.annotation.Nullable;
4 import android.content.Context;
5 import android.content.res.Resources;
6 import android.graphics.Rect;
7 import android.text.TextUtils;
8 import android.util.AttributeSet;
9 import android.util.SparseArray;
10 import android.view.View;
11 import android.view.ViewGroup;
12 import android.view.ViewStructure;
13 import android.view.autofill.AutofillManager;
14 import android.view.autofill.AutofillValue;
15 import android.widget.EditText;
16 import android.widget.LinearLayout;
17 import android.widget.TextView;
18 
19 public class CustomLinearLayout extends LinearLayout {
20     static final boolean VIRTUAL = false;
21 
CustomLinearLayout(Context context, @Nullable AttributeSet attrs)22     public CustomLinearLayout(Context context, @Nullable AttributeSet attrs) {
23         super(context, attrs);
24         if (VIRTUAL) {
25             getViewTreeObserver().addOnGlobalFocusChangeListener((oldFocus, newFocus) -> {
26                 AutofillManager autofillManager = getContext().getSystemService(
27                         AutofillManager.class);
28                 if (oldFocus != null) {
29                     autofillManager.notifyViewExited(CustomLinearLayout.this,
30                             oldFocus.getAccessibilityViewId());
31                 }
32                 if (newFocus != null) {
33                     Rect bounds = new Rect();
34                     newFocus.getBoundsOnScreen(bounds);
35                     autofillManager.notifyViewEntered(CustomLinearLayout.this,
36                             newFocus.getAccessibilityViewId(), bounds);
37                 }
38             });
39         }
40     }
41 
42     @Override
dispatchProvideAutofillStructure(ViewStructure structure, int flags)43     public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
44         if (!VIRTUAL) {
45             super.dispatchProvideAutofillStructure(structure, flags);
46         } else {
47             onProvideAutofillVirtualStructure(structure, flags);
48         }
49     }
50 
51     @Override
onProvideAutofillVirtualStructure(ViewStructure structure, int flags)52     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
53         if (!VIRTUAL) {
54             return;
55         }
56         populateViewStructure(this, structure);
57         onProvideAutofillVirtualStructureRecursive(this, structure);
58     }
59 
60     @Override
autofill(SparseArray<AutofillValue> values)61     public void autofill(SparseArray<AutofillValue> values) {
62         final int valueCount = values.size();
63         for (int i = 0; i < valueCount; i++) {
64             final int virtualId = values.keyAt(i);
65             final AutofillValue value = values.valueAt(i);
66             View view = findViewByAccessibilityIdTraversal(virtualId);
67             if (view instanceof EditText && !TextUtils.isEmpty(value.getTextValue())) {
68                 EditText editText = (EditText) view;
69                 editText.setText(value.getTextValue());
70 
71             }
72         }
73     }
74 
onProvideAutofillVirtualStructureRecursive(View view, ViewStructure node)75     private void onProvideAutofillVirtualStructureRecursive(View view, ViewStructure node) {
76         if (node == null) {
77             return;
78         }
79         if (view instanceof ViewGroup) {
80             ViewGroup viewGroup = (ViewGroup) view;
81             final int childCount = viewGroup.getChildCount();
82             node.setChildCount(childCount);
83             for (int i = 0; i < childCount; i++) {
84                 View child = viewGroup.getChildAt(i);
85                 ViewStructure chlidNode = node.newChild(i);
86                 chlidNode.setAutofillId(node, child.getAccessibilityViewId());
87                 populateViewStructure(child, chlidNode);
88                 onProvideAutofillVirtualStructureRecursive(child, chlidNode);
89             }
90         }
91     }
92 
populateViewStructure(View view, ViewStructure structure)93     private void populateViewStructure(View view, ViewStructure structure) {
94         if (view.getId() != NO_ID) {
95             String pkg, type, entry;
96             try {
97                 final Resources res = getResources();
98                 entry = res.getResourceEntryName(view.getId());
99                 type = res.getResourceTypeName(view.getId());
100                 pkg = res.getResourcePackageName(view.getId());
101             } catch (Resources.NotFoundException e) {
102                 entry = type = pkg = null;
103             }
104             structure.setId(view.getId(), pkg, type, entry);
105         } else {
106             structure.setId(view.getId(), null, null, null);
107         }
108         Rect rect = structure.getTempRect();
109         view.getDrawingRect(rect);
110         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
111         structure.setVisibility(VISIBLE);
112         structure.setEnabled(view.isEnabled());
113         if (view.isClickable()) {
114             structure.setClickable(true);
115         }
116         if (view.isFocusable()) {
117             structure.setFocusable(true);
118         }
119         if (view.isFocused()) {
120             structure.setFocused(true);
121         }
122         if (view.isAccessibilityFocused()) {
123             structure.setAccessibilityFocused(true);
124         }
125         if (view.isSelected()) {
126             structure.setSelected(true);
127         }
128         if (view.isLongClickable()) {
129             structure.setLongClickable(true);
130         }
131         CharSequence cname = view.getClass().getName();
132         structure.setClassName(cname != null ? cname.toString() : null);
133         structure.setContentDescription(view.getContentDescription());
134         if (view instanceof TextView) {
135             TextView textView = (TextView) view;
136             structure.setText(textView.getText(), textView.getSelectionStart(),
137                     textView.getSelectionEnd());
138         }
139         structure.setAutofillHints(view.getAutofillHints());
140         structure.setAutofillType(view.getAutofillType());
141         structure.setAutofillValue(view.getAutofillValue());
142     }
143 }
144