Home | History | Annotate | Download | only in filled
      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 
     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