CustomLinearLayout.java revision 71c3531ac20401e25fa4175aa993d0bd99bed5ea
1package foo.bar.filled;
2
3import android.annotation.Nullable;
4import android.content.Context;
5import android.content.res.Resources;
6import android.graphics.Rect;
7import android.text.TextUtils;
8import android.util.AttributeSet;
9import android.util.SparseArray;
10import android.view.View;
11import android.view.ViewGroup;
12import android.view.ViewStructure;
13import android.view.autofill.AutofillManager;
14import android.view.autofill.AutofillValue;
15import android.widget.EditText;
16import android.widget.LinearLayout;
17import android.widget.TextView;
18
19public class CustomLinearLayout extends LinearLayout {
20    static final boolean VIRTUAL = false;
21
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
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
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
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
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
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