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